167bf885d62b1473c833bece1c9e0bb624e6ba391buzbee/*
267bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * Copyright (C) 2011 The Android Open Source Project
367bf885d62b1473c833bece1c9e0bb624e6ba391buzbee *
467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * Licensed under the Apache License, Version 2.0 (the "License");
567bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * you may not use this file except in compliance with the License.
667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * You may obtain a copy of the License at
767bf885d62b1473c833bece1c9e0bb624e6ba391buzbee *
867bf885d62b1473c833bece1c9e0bb624e6ba391buzbee *      http://www.apache.org/licenses/LICENSE-2.0
967bf885d62b1473c833bece1c9e0bb624e6ba391buzbee *
1067bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * Unless required by applicable law or agreed to in writing, software
1167bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * distributed under the License is distributed on an "AS IS" BASIS,
1267bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1367bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * See the License for the specific language governing permissions and
1467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * limitations under the License.
1567bf885d62b1473c833bece1c9e0bb624e6ba391buzbee */
1667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
1702031b185b4653e6c72e21f7a51238b903f6d638buzbee#include "codegen_arm.h"
18d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
19d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers#include "arch/arm/instruction_set_features_arm.h"
20d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers#include "arm_lir.h"
210b9203e7996ee1856f620f95d95d8a273c43a3dfAndreas Gampe#include "base/logging.h"
22cc23481b66fd1f2b459d82da4852073e32f033aaVladimir Marko#include "dex/mir_graph.h"
237940e44f4517de5e2634a7e07d58d0fb26160513Brian Carlstrom#include "dex/quick/mir_to_lir-inl.h"
24b5860fb459f1ed71f39d8a87b45bee6727d79fe8buzbee#include "dex/reg_storage_eq.h"
250b9203e7996ee1856f620f95d95d8a273c43a3dfAndreas Gampe#include "driver/compiler_driver.h"
261bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee
2711d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughesnamespace art {
2811d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughes
29b046e16d8b8da318d6055f9308950131f1255e08buzbee/* This file contains codegen for the Thumb ISA. */
3067bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
310d82948094d9a198e01aa95f64012bdedd5b6fc9buzbeestatic int32_t EncodeImmSingle(int32_t value) {
320d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  int32_t res;
330d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  int32_t bit_a =  (value & 0x80000000) >> 31;
340d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  int32_t not_bit_b = (value & 0x40000000) >> 30;
350d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  int32_t bit_b =  (value & 0x20000000) >> 29;
360d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  int32_t b_smear =  (value & 0x3e000000) >> 25;
370d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  int32_t slice =   (value & 0x01f80000) >> 19;
380d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  int32_t zeroes =  (value & 0x0007ffff);
39a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  if (zeroes != 0)
40a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    return -1;
41fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (bit_b) {
42fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if ((not_bit_b != 0) || (b_smear != 0x1f))
43a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      return -1;
44a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  } else {
45fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if ((not_bit_b != 1) || (b_smear != 0x0))
46a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      return -1;
47a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
48fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  res = (bit_a << 7) | (bit_b << 6) | slice;
49a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return res;
5067bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
5167bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
524ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee/*
534ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee * Determine whether value can be encoded as a Thumb2 floating point
544ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee * immediate.  If not, return -1.  If so return encoded 8-bit value.
554ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee */
560d82948094d9a198e01aa95f64012bdedd5b6fc9buzbeestatic int32_t EncodeImmDouble(int64_t value) {
570d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  int32_t res;
580f6784737882199197796b67b99e5f1ded383beeIan Rogers  int32_t bit_a = (value & INT64_C(0x8000000000000000)) >> 63;
590f6784737882199197796b67b99e5f1ded383beeIan Rogers  int32_t not_bit_b = (value & INT64_C(0x4000000000000000)) >> 62;
600f6784737882199197796b67b99e5f1ded383beeIan Rogers  int32_t bit_b = (value & INT64_C(0x2000000000000000)) >> 61;
610f6784737882199197796b67b99e5f1ded383beeIan Rogers  int32_t b_smear = (value & INT64_C(0x3fc0000000000000)) >> 54;
620f6784737882199197796b67b99e5f1ded383beeIan Rogers  int32_t slice =  (value & INT64_C(0x003f000000000000)) >> 48;
630f6784737882199197796b67b99e5f1ded383beeIan Rogers  uint64_t zeroes = (value & INT64_C(0x0000ffffffffffff));
640d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  if (zeroes != 0ull)
654ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    return -1;
664ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  if (bit_b) {
674ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    if ((not_bit_b != 0) || (b_smear != 0xff))
684ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      return -1;
694ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  } else {
704ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    if ((not_bit_b != 1) || (b_smear != 0x0))
714ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      return -1;
724ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  }
734ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  res = (bit_a << 7) | (bit_b << 6) | slice;
744ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  return res;
754ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee}
764ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
772ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromLIR* ArmMir2Lir::LoadFPConstantValue(int r_dest, int value) {
78091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  DCHECK(RegStorage::IsSingle(r_dest));
797da142fc1cefeeb24d997ae21b34381fdd2c0466buzbee  if (value == 0) {
807da142fc1cefeeb24d997ae21b34381fdd2c0466buzbee    // TODO: we need better info about the target CPU.  a vector exclusive or
817da142fc1cefeeb24d997ae21b34381fdd2c0466buzbee    //       would probably be better here if we could rely on its existance.
827da142fc1cefeeb24d997ae21b34381fdd2c0466buzbee    // Load an immediate +2.0 (which encodes to 0)
831fd3346740dfb7f47be9922312b68a4227fada96buzbee    NewLIR2(kThumb2Vmovs_IMM8, r_dest, 0);
847da142fc1cefeeb24d997ae21b34381fdd2c0466buzbee    // +0.0 = +2.0 - +2.0
851fd3346740dfb7f47be9922312b68a4227fada96buzbee    return NewLIR3(kThumb2Vsubs, r_dest, r_dest, r_dest);
867da142fc1cefeeb24d997ae21b34381fdd2c0466buzbee  } else {
877da142fc1cefeeb24d997ae21b34381fdd2c0466buzbee    int encoded_imm = EncodeImmSingle(value);
887da142fc1cefeeb24d997ae21b34381fdd2c0466buzbee    if (encoded_imm >= 0) {
891fd3346740dfb7f47be9922312b68a4227fada96buzbee      return NewLIR2(kThumb2Vmovs_IMM8, r_dest, encoded_imm);
907da142fc1cefeeb24d997ae21b34381fdd2c0466buzbee    }
91a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
921fd3346740dfb7f47be9922312b68a4227fada96buzbee  LIR* data_target = ScanLiteralPool(literal_list_, value, 0);
932cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  if (data_target == nullptr) {
941fd3346740dfb7f47be9922312b68a4227fada96buzbee    data_target = AddWordData(&literal_list_, value);
95a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
968dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko  ScopedMemRefType mem_ref_type(this, ResourceMask::kLiteral);
971fd3346740dfb7f47be9922312b68a4227fada96buzbee  LIR* load_pc_rel = RawLIR(current_dalvik_offset_, kThumb2Vldrs,
98091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee                          r_dest, rs_r15pc.GetReg(), 0, 0, 0, data_target);
991fd3346740dfb7f47be9922312b68a4227fada96buzbee  AppendLIR(load_pc_rel);
100fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  return load_pc_rel;
10167bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
10267bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
10367bf885d62b1473c833bece1c9e0bb624e6ba391buzbee/*
10467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * Determine whether value can be encoded as a Thumb2 modified
10567bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * immediate.  If not, return -1.  If so, return i:imm3:a:bcdefgh form.
10667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee */
1072ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromint ArmMir2Lir::ModifiedImmediate(uint32_t value) {
1086f485c62b9cfce3ab71020c646ab9f48d9d29d6dBrian Carlstrom  uint32_t b0 = value & 0xff;
10967bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
1106f485c62b9cfce3ab71020c646ab9f48d9d29d6dBrian Carlstrom  /* Note: case of value==0 must use 0:000:0:0000000 encoding */
1116f485c62b9cfce3ab71020c646ab9f48d9d29d6dBrian Carlstrom  if (value <= 0xFF)
1126f485c62b9cfce3ab71020c646ab9f48d9d29d6dBrian Carlstrom    return b0;  // 0:000:a:bcdefgh
1136f485c62b9cfce3ab71020c646ab9f48d9d29d6dBrian Carlstrom  if (value == ((b0 << 16) | b0))
1146f485c62b9cfce3ab71020c646ab9f48d9d29d6dBrian Carlstrom    return (0x1 << 8) | b0; /* 0:001:a:bcdefgh */
1156f485c62b9cfce3ab71020c646ab9f48d9d29d6dBrian Carlstrom  if (value == ((b0 << 24) | (b0 << 16) | (b0 << 8) | b0))
1166f485c62b9cfce3ab71020c646ab9f48d9d29d6dBrian Carlstrom    return (0x3 << 8) | b0; /* 0:011:a:bcdefgh */
1176f485c62b9cfce3ab71020c646ab9f48d9d29d6dBrian Carlstrom  b0 = (value >> 8) & 0xff;
1186f485c62b9cfce3ab71020c646ab9f48d9d29d6dBrian Carlstrom  if (value == ((b0 << 24) | (b0 << 8)))
1196f485c62b9cfce3ab71020c646ab9f48d9d29d6dBrian Carlstrom    return (0x2 << 8) | b0; /* 0:010:a:bcdefgh */
1206f485c62b9cfce3ab71020c646ab9f48d9d29d6dBrian Carlstrom  /* Can we do it with rotation? */
121a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko  int z_leading = CLZ(value);
122a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko  int z_trailing = CTZ(value);
1236f485c62b9cfce3ab71020c646ab9f48d9d29d6dBrian Carlstrom  /* A run of eight or fewer active bits? */
1246f485c62b9cfce3ab71020c646ab9f48d9d29d6dBrian Carlstrom  if ((z_leading + z_trailing) < 24)
1256f485c62b9cfce3ab71020c646ab9f48d9d29d6dBrian Carlstrom    return -1;  /* No - bail */
1266f485c62b9cfce3ab71020c646ab9f48d9d29d6dBrian Carlstrom  /* left-justify the constant, discarding msb (known to be 1) */
1276f485c62b9cfce3ab71020c646ab9f48d9d29d6dBrian Carlstrom  value <<= z_leading + 1;
1286f485c62b9cfce3ab71020c646ab9f48d9d29d6dBrian Carlstrom  /* Create bcdefgh */
1296f485c62b9cfce3ab71020c646ab9f48d9d29d6dBrian Carlstrom  value >>= 25;
1306f485c62b9cfce3ab71020c646ab9f48d9d29d6dBrian Carlstrom  /* Put it all together */
1316f485c62b9cfce3ab71020c646ab9f48d9d29d6dBrian Carlstrom  return value | ((0x8 + z_leading) << 7); /* [01000..11111]:bcdefgh */
13267bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
13367bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
1342ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrombool ArmMir2Lir::InexpensiveConstantInt(int32_t value) {
1354ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  return (ModifiedImmediate(value) >= 0) || (ModifiedImmediate(~value) >= 0);
1364ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee}
1374ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
138a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Markobool ArmMir2Lir::InexpensiveConstantInt(int32_t value, Instruction::Code opcode) {
139a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko  switch (opcode) {
140a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko    case Instruction::ADD_INT:
141a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko    case Instruction::ADD_INT_2ADDR:
142a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko    case Instruction::SUB_INT:
143a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko    case Instruction::SUB_INT_2ADDR:
144a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko      if ((value >> 12) == (value >> 31)) {  // Signed 12-bit, RRI12 versions of ADD/SUB.
145a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko        return true;
146a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko      }
147a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko      FALLTHROUGH_INTENDED;
148a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko    case Instruction::IF_EQ:
149a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko    case Instruction::IF_NE:
150a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko    case Instruction::IF_LT:
151a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko    case Instruction::IF_GE:
152a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko    case Instruction::IF_GT:
153a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko    case Instruction::IF_LE:
154a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko      return (ModifiedImmediate(value) >= 0) || (ModifiedImmediate(-value) >= 0);
155a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko    case Instruction::SHL_INT:
156a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko    case Instruction::SHL_INT_2ADDR:
157a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko    case Instruction::SHR_INT:
158a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko    case Instruction::SHR_INT_2ADDR:
159a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko    case Instruction::USHR_INT:
160a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko    case Instruction::USHR_INT_2ADDR:
161a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko      return true;
162aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko    case Instruction::CONST:
163aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko    case Instruction::CONST_4:
164aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko    case Instruction::CONST_16:
165aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      if ((value >> 16) == 0) {
166aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko        return true;  // movw, 16-bit unsigned.
167aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      }
168aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      FALLTHROUGH_INTENDED;
169a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko    case Instruction::AND_INT:
170a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko    case Instruction::AND_INT_2ADDR:
171a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko    case Instruction::AND_INT_LIT16:
172a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko    case Instruction::AND_INT_LIT8:
173a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko    case Instruction::OR_INT:
174a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko    case Instruction::OR_INT_2ADDR:
175a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko    case Instruction::OR_INT_LIT16:
176a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko    case Instruction::OR_INT_LIT8:
177a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko      return (ModifiedImmediate(value) >= 0) || (ModifiedImmediate(~value) >= 0);
178a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko    case Instruction::XOR_INT:
179a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko    case Instruction::XOR_INT_2ADDR:
180a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko    case Instruction::XOR_INT_LIT16:
181a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko    case Instruction::XOR_INT_LIT8:
182a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko      return (ModifiedImmediate(value) >= 0);
183a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko    case Instruction::MUL_INT:
184a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko    case Instruction::MUL_INT_2ADDR:
185a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko    case Instruction::MUL_INT_LIT8:
186a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko    case Instruction::MUL_INT_LIT16:
187a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko    case Instruction::DIV_INT:
188a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko    case Instruction::DIV_INT_2ADDR:
189a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko    case Instruction::DIV_INT_LIT8:
190a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko    case Instruction::DIV_INT_LIT16:
191a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko    case Instruction::REM_INT:
192a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko    case Instruction::REM_INT_2ADDR:
193a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko    case Instruction::REM_INT_LIT8:
194a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko    case Instruction::REM_INT_LIT16: {
195a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko      EasyMultiplyOp ops[2];
196a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko      return GetEasyMultiplyTwoOps(value, ops);
197a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko    }
198a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko    default:
199a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko      return false;
200a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko  }
201a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko}
202a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko
2032ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrombool ArmMir2Lir::InexpensiveConstantFloat(int32_t value) {
2044ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  return EncodeImmSingle(value) >= 0;
2054ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee}
2064ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
2072ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrombool ArmMir2Lir::InexpensiveConstantLong(int64_t value) {
2084ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  return InexpensiveConstantInt(High32Bits(value)) && InexpensiveConstantInt(Low32Bits(value));
2094ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee}
2104ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
2112ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrombool ArmMir2Lir::InexpensiveConstantDouble(int64_t value) {
2124ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  return EncodeImmDouble(value) >= 0;
213e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee}
214e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee
21567bf885d62b1473c833bece1c9e0bb624e6ba391buzbee/*
21667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * Load a immediate using a shortcut if possible; otherwise
21767bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * grab from the per-translation literal pool.
21867bf885d62b1473c833bece1c9e0bb624e6ba391buzbee *
21967bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * No additional register clobbering operation performed. Use this version when
220fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee * 1) r_dest is freshly returned from AllocTemp or
22167bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * 2) The codegen is under fixed register usage
22267bf885d62b1473c833bece1c9e0bb624e6ba391buzbee */
2232700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* ArmMir2Lir::LoadConstantNoClobber(RegStorage r_dest, int value) {
224a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  LIR* res;
225fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  int mod_imm;
22667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
227091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  if (r_dest.IsFloat()) {
2282700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    return LoadFPConstantValue(r_dest.GetReg(), value);
229a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
23067bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
231a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /* See if the value can be constructed cheaply */
232091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  if (r_dest.Low8() && (value >= 0) && (value <= 255)) {
2332700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    return NewLIR2(kThumbMovImm, r_dest.GetReg(), value);
234a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
235a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /* Check Modified immediate special cases */
236fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  mod_imm = ModifiedImmediate(value);
237fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (mod_imm >= 0) {
2382700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    res = NewLIR2(kThumb2MovI8M, r_dest.GetReg(), mod_imm);
23967bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    return res;
240a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
241fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  mod_imm = ModifiedImmediate(~value);
242fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (mod_imm >= 0) {
2432700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    res = NewLIR2(kThumb2MvnI8M, r_dest.GetReg(), mod_imm);
244a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    return res;
245a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
246a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /* 16-bit immediate? */
247a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  if ((value & 0xffff) == value) {
2482700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    res = NewLIR2(kThumb2MovImm16, r_dest.GetReg(), value);
249a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    return res;
250a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
2514ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  /* Do a low/high pair */
2522700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  res = NewLIR2(kThumb2MovImm16, r_dest.GetReg(), Low16Bits(value));
2532700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  NewLIR2(kThumb2MovImm16H, r_dest.GetReg(), High16Bits(value));
254a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return res;
25567bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
25667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
2572ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromLIR* ArmMir2Lir::OpUnconditionalBranch(LIR* target) {
258091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  LIR* res = NewLIR1(kThumbBUncond, 0 /* offset to be patched  during assembly */);
25902031b185b4653e6c72e21f7a51238b903f6d638buzbee  res->target = target;
26002031b185b4653e6c72e21f7a51238b903f6d638buzbee  return res;
26167bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
26267bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
2632ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromLIR* ArmMir2Lir::OpCondBranch(ConditionCode cc, LIR* target) {
264174636dad59068fc6e879b147ae02ac932f38c6fVladimir Marko  LIR* branch = NewLIR2(kThumbBCond, 0 /* offset to be patched */,
26552a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee                        ArmConditionEncoding(cc));
266a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  branch->target = target;
267a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return branch;
26867bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
26967bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
2702700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* ArmMir2Lir::OpReg(OpKind op, RegStorage r_dest_src) {
271a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  ArmOpcode opcode = kThumbBkpt;
272a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  switch (op) {
273a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpBlx:
274a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      opcode = kThumbBlxR;
275a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
27660d7a65f7fb60f502160a2e479e86014c7787553Brian Carlstrom    case kOpBx:
27760d7a65f7fb60f502160a2e479e86014c7787553Brian Carlstrom      opcode = kThumbBx;
27860d7a65f7fb60f502160a2e479e86014c7787553Brian Carlstrom      break;
279a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    default:
280cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      LOG(FATAL) << "Bad opcode " << op;
281a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
2822700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  return NewLIR1(opcode, r_dest_src.GetReg());
28367bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
28467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
285e2143c0a4af68c08e811885eb2f3ea5bfdb21ab6Ian RogersLIR* ArmMir2Lir::OpRegRegShift(OpKind op, RegStorage r_dest_src1, RegStorage r_src2,
2862ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                               int shift) {
287e2143c0a4af68c08e811885eb2f3ea5bfdb21ab6Ian Rogers  bool thumb_form =
288091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      ((shift == 0) && r_dest_src1.Low8() && r_src2.Low8());
289a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  ArmOpcode opcode = kThumbBkpt;
290a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  switch (op) {
291a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpAdc:
292fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = (thumb_form) ? kThumbAdcRR : kThumb2AdcRRR;
293a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
294a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpAnd:
295fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = (thumb_form) ? kThumbAndRR : kThumb2AndRRR;
296a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
297a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpBic:
298fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = (thumb_form) ? kThumbBicRR : kThumb2BicRRR;
299a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
300a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpCmn:
301a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      DCHECK_EQ(shift, 0);
302fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = (thumb_form) ? kThumbCmnRR : kThumb2CmnRR;
303a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
304a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpCmp:
305fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (thumb_form)
306a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        opcode = kThumbCmpRR;
307091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      else if ((shift == 0) && !r_dest_src1.Low8() && !r_src2.Low8())
308a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        opcode = kThumbCmpHH;
309091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      else if ((shift == 0) && r_dest_src1.Low8())
310a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        opcode = kThumbCmpLH;
311a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      else if (shift == 0)
312a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        opcode = kThumbCmpHL;
313a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      else
314a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        opcode = kThumb2CmpRR;
315a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
316a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpXor:
317fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = (thumb_form) ? kThumbEorRR : kThumb2EorRRR;
318a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
319a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpMov:
320a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      DCHECK_EQ(shift, 0);
321091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      if (r_dest_src1.Low8() && r_src2.Low8())
322a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        opcode = kThumbMovRR;
323091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      else if (!r_dest_src1.Low8() && !r_src2.Low8())
324a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        opcode = kThumbMovRR_H2H;
325091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      else if (r_dest_src1.Low8())
326a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        opcode = kThumbMovRR_H2L;
327a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      else
328a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        opcode = kThumbMovRR_L2H;
329a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
330a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpMul:
331a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      DCHECK_EQ(shift, 0);
332fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = (thumb_form) ? kThumbMul : kThumb2MulRRR;
333a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
334a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpMvn:
335fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = (thumb_form) ? kThumbMvn : kThumb2MnvRR;
336a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
337a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpNeg:
338a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      DCHECK_EQ(shift, 0);
339fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = (thumb_form) ? kThumbNeg : kThumb2NegRR;
340a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
341a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpOr:
342fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = (thumb_form) ? kThumbOrr : kThumb2OrrRRR;
343a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
344a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpSbc:
345fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = (thumb_form) ? kThumbSbc : kThumb2SbcRRR;
346a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
347a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpTst:
348fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = (thumb_form) ? kThumbTst : kThumb2TstRR;
349a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
350a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpLsl:
351a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      DCHECK_EQ(shift, 0);
352fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = (thumb_form) ? kThumbLslRR : kThumb2LslRRR;
353a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
354a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpLsr:
355a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      DCHECK_EQ(shift, 0);
356fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = (thumb_form) ? kThumbLsrRR : kThumb2LsrRRR;
357a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
358a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpAsr:
359a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      DCHECK_EQ(shift, 0);
360fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = (thumb_form) ? kThumbAsrRR : kThumb2AsrRRR;
361a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
362a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpRor:
363a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      DCHECK_EQ(shift, 0);
364fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = (thumb_form) ? kThumbRorRR : kThumb2RorRRR;
365a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
366a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpAdd:
367fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = (thumb_form) ? kThumbAddRRR : kThumb2AddRRR;
368a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
369a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpSub:
370fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = (thumb_form) ? kThumbSubRRR : kThumb2SubRRR;
371a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
372a8b4caf7526b6b66a8ae0826bd52c39c66e3c714Vladimir Marko    case kOpRev:
373a8b4caf7526b6b66a8ae0826bd52c39c66e3c714Vladimir Marko      DCHECK_EQ(shift, 0);
374a8b4caf7526b6b66a8ae0826bd52c39c66e3c714Vladimir Marko      if (!thumb_form) {
375a8b4caf7526b6b66a8ae0826bd52c39c66e3c714Vladimir Marko        // Binary, but rm is encoded twice.
376e2143c0a4af68c08e811885eb2f3ea5bfdb21ab6Ian Rogers        return NewLIR3(kThumb2RevRR, r_dest_src1.GetReg(), r_src2.GetReg(), r_src2.GetReg());
377a8b4caf7526b6b66a8ae0826bd52c39c66e3c714Vladimir Marko      }
378a8b4caf7526b6b66a8ae0826bd52c39c66e3c714Vladimir Marko      opcode = kThumbRev;
379a8b4caf7526b6b66a8ae0826bd52c39c66e3c714Vladimir Marko      break;
380a8b4caf7526b6b66a8ae0826bd52c39c66e3c714Vladimir Marko    case kOpRevsh:
381a8b4caf7526b6b66a8ae0826bd52c39c66e3c714Vladimir Marko      DCHECK_EQ(shift, 0);
382a8b4caf7526b6b66a8ae0826bd52c39c66e3c714Vladimir Marko      if (!thumb_form) {
383a8b4caf7526b6b66a8ae0826bd52c39c66e3c714Vladimir Marko        // Binary, but rm is encoded twice.
384e2143c0a4af68c08e811885eb2f3ea5bfdb21ab6Ian Rogers        return NewLIR3(kThumb2RevshRR, r_dest_src1.GetReg(), r_src2.GetReg(), r_src2.GetReg());
385a8b4caf7526b6b66a8ae0826bd52c39c66e3c714Vladimir Marko      }
386a8b4caf7526b6b66a8ae0826bd52c39c66e3c714Vladimir Marko      opcode = kThumbRevsh;
387a8b4caf7526b6b66a8ae0826bd52c39c66e3c714Vladimir Marko      break;
388a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOp2Byte:
389a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      DCHECK_EQ(shift, 0);
390e2143c0a4af68c08e811885eb2f3ea5bfdb21ab6Ian Rogers      return NewLIR4(kThumb2Sbfx, r_dest_src1.GetReg(), r_src2.GetReg(), 0, 8);
391a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOp2Short:
392a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      DCHECK_EQ(shift, 0);
393e2143c0a4af68c08e811885eb2f3ea5bfdb21ab6Ian Rogers      return NewLIR4(kThumb2Sbfx, r_dest_src1.GetReg(), r_src2.GetReg(), 0, 16);
394a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOp2Char:
395a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      DCHECK_EQ(shift, 0);
396e2143c0a4af68c08e811885eb2f3ea5bfdb21ab6Ian Rogers      return NewLIR4(kThumb2Ubfx, r_dest_src1.GetReg(), r_src2.GetReg(), 0, 16);
397a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    default:
398cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      LOG(FATAL) << "Bad opcode: " << op;
399a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
400a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
401409fe94ad529d9334587be80b9f6a3d166805508buzbee  DCHECK(!IsPseudoLirOp(opcode));
4029b7085a4e7c40e7fa01932ea1647a4a33ac1c585Brian Carlstrom  if (EncodingMap[opcode].flags & IS_BINARY_OP) {
403e2143c0a4af68c08e811885eb2f3ea5bfdb21ab6Ian Rogers    return NewLIR2(opcode, r_dest_src1.GetReg(), r_src2.GetReg());
4049b7085a4e7c40e7fa01932ea1647a4a33ac1c585Brian Carlstrom  } else if (EncodingMap[opcode].flags & IS_TERTIARY_OP) {
4059b7085a4e7c40e7fa01932ea1647a4a33ac1c585Brian Carlstrom    if (EncodingMap[opcode].field_loc[2].kind == kFmtShift) {
406e2143c0a4af68c08e811885eb2f3ea5bfdb21ab6Ian Rogers      return NewLIR3(opcode, r_dest_src1.GetReg(), r_src2.GetReg(), shift);
4079b7085a4e7c40e7fa01932ea1647a4a33ac1c585Brian Carlstrom    } else {
408e2143c0a4af68c08e811885eb2f3ea5bfdb21ab6Ian Rogers      return NewLIR3(opcode, r_dest_src1.GetReg(), r_dest_src1.GetReg(), r_src2.GetReg());
4099b7085a4e7c40e7fa01932ea1647a4a33ac1c585Brian Carlstrom    }
4109b7085a4e7c40e7fa01932ea1647a4a33ac1c585Brian Carlstrom  } else if (EncodingMap[opcode].flags & IS_QUAD_OP) {
411e2143c0a4af68c08e811885eb2f3ea5bfdb21ab6Ian Rogers    return NewLIR4(opcode, r_dest_src1.GetReg(), r_dest_src1.GetReg(), r_src2.GetReg(), shift);
4129b7085a4e7c40e7fa01932ea1647a4a33ac1c585Brian Carlstrom  } else {
413a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    LOG(FATAL) << "Unexpected encoding operand count";
4142cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier    return nullptr;
415a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
41667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
41767bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
4182700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* ArmMir2Lir::OpRegReg(OpKind op, RegStorage r_dest_src1, RegStorage r_src2) {
419e2143c0a4af68c08e811885eb2f3ea5bfdb21ab6Ian Rogers  return OpRegRegShift(op, r_dest_src1, r_src2, 0);
42067bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
42167bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
4222700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* ArmMir2Lir::OpMovRegMem(RegStorage r_dest, RegStorage r_base, int offset, MoveType move_type) {
4236a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers  UNUSED(r_dest, r_base, offset, move_type);
4242c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru  UNIMPLEMENTED(FATAL);
4256a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers  UNREACHABLE();
4262c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru}
4272c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru
4282700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* ArmMir2Lir::OpMovMemReg(RegStorage r_base, int offset, RegStorage r_src, MoveType move_type) {
4296a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers  UNUSED(r_base, offset, r_src, move_type);
4302c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru  UNIMPLEMENTED(FATAL);
4316a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers  UNREACHABLE();
4322c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru}
4332c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru
4342700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* ArmMir2Lir::OpCondRegReg(OpKind op, ConditionCode cc, RegStorage r_dest, RegStorage r_src) {
4356a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers  UNUSED(op, cc, r_dest, r_src);
436bd288c2c1206bc99fafebfb9120a83f13cf9723bRazvan A Lupusoru  LOG(FATAL) << "Unexpected use of OpCondRegReg for Arm";
4376a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers  UNREACHABLE();
438bd288c2c1206bc99fafebfb9120a83f13cf9723bRazvan A Lupusoru}
439bd288c2c1206bc99fafebfb9120a83f13cf9723bRazvan A Lupusoru
440e2143c0a4af68c08e811885eb2f3ea5bfdb21ab6Ian RogersLIR* ArmMir2Lir::OpRegRegRegShift(OpKind op, RegStorage r_dest, RegStorage r_src1,
441e2143c0a4af68c08e811885eb2f3ea5bfdb21ab6Ian Rogers                                  RegStorage r_src2, int shift) {
442a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  ArmOpcode opcode = kThumbBkpt;
443091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  bool thumb_form = (shift == 0) && r_dest.Low8() && r_src1.Low8() && r_src2.Low8();
444a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  switch (op) {
445a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpAdd:
446fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = (thumb_form) ? kThumbAddRRR : kThumb2AddRRR;
447a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
448a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpSub:
449fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = (thumb_form) ? kThumbSubRRR : kThumb2SubRRR;
450a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
451a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpRsub:
452a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      opcode = kThumb2RsubRRR;
453a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
454a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpAdc:
455a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      opcode = kThumb2AdcRRR;
456a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
457a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpAnd:
458a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      opcode = kThumb2AndRRR;
459a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
460a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpBic:
461a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      opcode = kThumb2BicRRR;
462a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
463a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpXor:
464a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      opcode = kThumb2EorRRR;
465a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
466a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpMul:
467a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      DCHECK_EQ(shift, 0);
468a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      opcode = kThumb2MulRRR;
469a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
4707020278bce98a0735dc6abcbd33bdf1ed2634f1dDave Allison    case kOpDiv:
4717020278bce98a0735dc6abcbd33bdf1ed2634f1dDave Allison      DCHECK_EQ(shift, 0);
4727020278bce98a0735dc6abcbd33bdf1ed2634f1dDave Allison      opcode = kThumb2SdivRRR;
4737020278bce98a0735dc6abcbd33bdf1ed2634f1dDave Allison      break;
474a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpOr:
475a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      opcode = kThumb2OrrRRR;
476a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
477a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpSbc:
478a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      opcode = kThumb2SbcRRR;
479a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
480a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpLsl:
481a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      DCHECK_EQ(shift, 0);
482a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      opcode = kThumb2LslRRR;
483a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
484a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpLsr:
485a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      DCHECK_EQ(shift, 0);
486a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      opcode = kThumb2LsrRRR;
487a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
488a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpAsr:
489a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      DCHECK_EQ(shift, 0);
490a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      opcode = kThumb2AsrRRR;
491a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
492a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpRor:
493a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      DCHECK_EQ(shift, 0);
494a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      opcode = kThumb2RorRRR;
495a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
496a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    default:
497cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      LOG(FATAL) << "Bad opcode: " << op;
498a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
499a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
500409fe94ad529d9334587be80b9f6a3d166805508buzbee  DCHECK(!IsPseudoLirOp(opcode));
5019b7085a4e7c40e7fa01932ea1647a4a33ac1c585Brian Carlstrom  if (EncodingMap[opcode].flags & IS_QUAD_OP) {
502e2143c0a4af68c08e811885eb2f3ea5bfdb21ab6Ian Rogers    return NewLIR4(opcode, r_dest.GetReg(), r_src1.GetReg(), r_src2.GetReg(), shift);
5039b7085a4e7c40e7fa01932ea1647a4a33ac1c585Brian Carlstrom  } else {
504a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    DCHECK(EncodingMap[opcode].flags & IS_TERTIARY_OP);
505e2143c0a4af68c08e811885eb2f3ea5bfdb21ab6Ian Rogers    return NewLIR3(opcode, r_dest.GetReg(), r_src1.GetReg(), r_src2.GetReg());
506a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
50767bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
50867bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
5092700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* ArmMir2Lir::OpRegRegReg(OpKind op, RegStorage r_dest, RegStorage r_src1, RegStorage r_src2) {
510e2143c0a4af68c08e811885eb2f3ea5bfdb21ab6Ian Rogers  return OpRegRegRegShift(op, r_dest, r_src1, r_src2, 0);
51167bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
51267bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
5132700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* ArmMir2Lir::OpRegRegImm(OpKind op, RegStorage r_dest, RegStorage r_src1, int value) {
514a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  bool neg = (value < 0);
5150d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  int32_t abs_value = (neg) ? -value : value;
516a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  ArmOpcode opcode = kThumbBkpt;
517fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  ArmOpcode alt_opcode = kThumbBkpt;
518091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  bool all_low_regs = r_dest.Low8() && r_src1.Low8();
5190d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  int32_t mod_imm = ModifiedImmediate(value);
52067bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
521a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  switch (op) {
522a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpLsl:
523fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (all_low_regs)
5242700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee        return NewLIR3(kThumbLslRRI5, r_dest.GetReg(), r_src1.GetReg(), value);
525a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      else
5262700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee        return NewLIR3(kThumb2LslRRI5, r_dest.GetReg(), r_src1.GetReg(), value);
527a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpLsr:
528fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (all_low_regs)
5292700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee        return NewLIR3(kThumbLsrRRI5, r_dest.GetReg(), r_src1.GetReg(), value);
530a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      else
5312700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee        return NewLIR3(kThumb2LsrRRI5, r_dest.GetReg(), r_src1.GetReg(), value);
532a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpAsr:
533fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (all_low_regs)
5342700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee        return NewLIR3(kThumbAsrRRI5, r_dest.GetReg(), r_src1.GetReg(), value);
535a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      else
5362700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee        return NewLIR3(kThumb2AsrRRI5, r_dest.GetReg(), r_src1.GetReg(), value);
537a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpRor:
5382700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee      return NewLIR3(kThumb2RorRRI5, r_dest.GetReg(), r_src1.GetReg(), value);
539a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpAdd:
540091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      if (r_dest.Low8() && (r_src1 == rs_r13sp) && (value <= 1020) && ((value & 0x3) == 0)) {
5412700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee        return NewLIR3(kThumbAddSpRel, r_dest.GetReg(), r_src1.GetReg(), value >> 2);
542091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      } else if (r_dest.Low8() && (r_src1 == rs_r15pc) &&
54338f85e4892f6504971bde994fec81fd61780ac30Brian Carlstrom          (value <= 1020) && ((value & 0x3) == 0)) {
5442700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee        return NewLIR3(kThumbAddPcRel, r_dest.GetReg(), r_src1.GetReg(), value >> 2);
545a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
546fc787ecd91127b2c8458afd94e5148e2ae51a1f5Ian Rogers      FALLTHROUGH_INTENDED;
547a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpSub:
548fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (all_low_regs && ((abs_value & 0x7) == abs_value)) {
549a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        if (op == kOpAdd)
550a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee          opcode = (neg) ? kThumbSubRRI3 : kThumbAddRRI3;
55167bf885d62b1473c833bece1c9e0bb624e6ba391buzbee        else
552a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee          opcode = (neg) ? kThumbAddRRI3 : kThumbSubRRI3;
5532700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee        return NewLIR3(opcode, r_dest.GetReg(), r_src1.GetReg(), abs_value);
554a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
555332b7aa6220124dc638b9f7e59611c376473f128Vladimir Marko      if (mod_imm < 0) {
556332b7aa6220124dc638b9f7e59611c376473f128Vladimir Marko        mod_imm = ModifiedImmediate(-value);
557332b7aa6220124dc638b9f7e59611c376473f128Vladimir Marko        if (mod_imm >= 0) {
558332b7aa6220124dc638b9f7e59611c376473f128Vladimir Marko          op = (op == kOpAdd) ? kOpSub : kOpAdd;
559332b7aa6220124dc638b9f7e59611c376473f128Vladimir Marko        }
560a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
561a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko      if (mod_imm < 0 && (abs_value >> 12) == 0) {
562dbb8c49d540edd2a39076093163c7218f03aa502Vladimir Marko        // This is deliberately used only if modified immediate encoding is inadequate since
563dbb8c49d540edd2a39076093163c7218f03aa502Vladimir Marko        // we sometimes actually use the flags for small values but not necessarily low regs.
564dbb8c49d540edd2a39076093163c7218f03aa502Vladimir Marko        if (op == kOpAdd)
565dbb8c49d540edd2a39076093163c7218f03aa502Vladimir Marko          opcode = (neg) ? kThumb2SubRRI12 : kThumb2AddRRI12;
566dbb8c49d540edd2a39076093163c7218f03aa502Vladimir Marko        else
567dbb8c49d540edd2a39076093163c7218f03aa502Vladimir Marko          opcode = (neg) ? kThumb2AddRRI12 : kThumb2SubRRI12;
5682700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee        return NewLIR3(opcode, r_dest.GetReg(), r_src1.GetReg(), abs_value);
569dbb8c49d540edd2a39076093163c7218f03aa502Vladimir Marko      }
570a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      if (op == kOpSub) {
571332b7aa6220124dc638b9f7e59611c376473f128Vladimir Marko        opcode = kThumb2SubRRI8M;
572fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        alt_opcode = kThumb2SubRRR;
573a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      } else {
574332b7aa6220124dc638b9f7e59611c376473f128Vladimir Marko        opcode = kThumb2AddRRI8M;
575fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        alt_opcode = kThumb2AddRRR;
576a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
577a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
578c7d1f91e024c5c560810376340aecb39d4e47fdcbuzbee    case kOpRsub:
579332b7aa6220124dc638b9f7e59611c376473f128Vladimir Marko      opcode = kThumb2RsubRRI8M;
580c7d1f91e024c5c560810376340aecb39d4e47fdcbuzbee      alt_opcode = kThumb2RsubRRR;
581c7d1f91e024c5c560810376340aecb39d4e47fdcbuzbee      break;
582a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpAdc:
583332b7aa6220124dc638b9f7e59611c376473f128Vladimir Marko      opcode = kThumb2AdcRRI8M;
584fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      alt_opcode = kThumb2AdcRRR;
585a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
586a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpSbc:
587332b7aa6220124dc638b9f7e59611c376473f128Vladimir Marko      opcode = kThumb2SbcRRI8M;
588fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      alt_opcode = kThumb2SbcRRR;
589a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
590a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpOr:
591332b7aa6220124dc638b9f7e59611c376473f128Vladimir Marko      opcode = kThumb2OrrRRI8M;
592fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      alt_opcode = kThumb2OrrRRR;
593a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko      if (mod_imm < 0) {
594a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko        mod_imm = ModifiedImmediate(~value);
595a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko        if (mod_imm >= 0) {
596a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko          opcode = kThumb2OrnRRI8M;
597a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko        }
598a29f698b1754ee0ea2f46b6f5900e0da840dff79Vladimir Marko      }
599a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
600a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpAnd:
601332b7aa6220124dc638b9f7e59611c376473f128Vladimir Marko      if (mod_imm < 0) {
602332b7aa6220124dc638b9f7e59611c376473f128Vladimir Marko        mod_imm = ModifiedImmediate(~value);
603332b7aa6220124dc638b9f7e59611c376473f128Vladimir Marko        if (mod_imm >= 0) {
6042700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee          return NewLIR3(kThumb2BicRRI8M, r_dest.GetReg(), r_src1.GetReg(), mod_imm);
605332b7aa6220124dc638b9f7e59611c376473f128Vladimir Marko        }
606332b7aa6220124dc638b9f7e59611c376473f128Vladimir Marko      }
607332b7aa6220124dc638b9f7e59611c376473f128Vladimir Marko      opcode = kThumb2AndRRI8M;
608fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      alt_opcode = kThumb2AndRRR;
609a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
610a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpXor:
611332b7aa6220124dc638b9f7e59611c376473f128Vladimir Marko      opcode = kThumb2EorRRI8M;
612fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      alt_opcode = kThumb2EorRRR;
613a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
614a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpMul:
6157934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom      // TUNING: power of 2, shift & add
616fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      mod_imm = -1;
617fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      alt_opcode = kThumb2MulRRR;
618a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
619a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpCmp: {
620a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      LIR* res;
621fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (mod_imm >= 0) {
6222700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee        res = NewLIR2(kThumb2CmpRI8M, r_src1.GetReg(), mod_imm);
623a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      } else {
624332b7aa6220124dc638b9f7e59611c376473f128Vladimir Marko        mod_imm = ModifiedImmediate(-value);
625332b7aa6220124dc638b9f7e59611c376473f128Vladimir Marko        if (mod_imm >= 0) {
6262700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee          res = NewLIR2(kThumb2CmnRI8M, r_src1.GetReg(), mod_imm);
627332b7aa6220124dc638b9f7e59611c376473f128Vladimir Marko        } else {
6282700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee          RegStorage r_tmp = AllocTemp();
629332b7aa6220124dc638b9f7e59611c376473f128Vladimir Marko          res = LoadConstant(r_tmp, value);
630332b7aa6220124dc638b9f7e59611c376473f128Vladimir Marko          OpRegReg(kOpCmp, r_src1, r_tmp);
631332b7aa6220124dc638b9f7e59611c376473f128Vladimir Marko          FreeTemp(r_tmp);
632332b7aa6220124dc638b9f7e59611c376473f128Vladimir Marko        }
633a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
634a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      return res;
63567bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    }
636a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    default:
637cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      LOG(FATAL) << "Bad opcode: " << op;
638a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
639a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee
640fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (mod_imm >= 0) {
6412700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    return NewLIR3(opcode, r_dest.GetReg(), r_src1.GetReg(), mod_imm);
642a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  } else {
6432700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    RegStorage r_scratch = AllocTemp();
6441fd3346740dfb7f47be9922312b68a4227fada96buzbee    LoadConstant(r_scratch, value);
645277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe    LIR* res;
646fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (EncodingMap[alt_opcode].flags & IS_QUAD_OP)
6472700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee      res = NewLIR4(alt_opcode, r_dest.GetReg(), r_src1.GetReg(), r_scratch.GetReg(), 0);
648a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    else
6492700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee      res = NewLIR3(alt_opcode, r_dest.GetReg(), r_src1.GetReg(), r_scratch.GetReg());
6501fd3346740dfb7f47be9922312b68a4227fada96buzbee    FreeTemp(r_scratch);
651a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    return res;
652a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
65367bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
65467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
65552a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee/* Handle Thumb-only variants here - otherwise punt to OpRegRegImm */
6562700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* ArmMir2Lir::OpRegImm(OpKind op, RegStorage r_dest_src1, int value) {
657a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  bool neg = (value < 0);
6580d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  int32_t abs_value = (neg) ? -value : value;
659091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  bool short_form = (((abs_value & 0xff) == abs_value) && r_dest_src1.Low8());
660a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  ArmOpcode opcode = kThumbBkpt;
661a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  switch (op) {
662a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpAdd:
6632700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee      if (!neg && (r_dest_src1 == rs_r13sp) && (value <= 508)) { /* sp */
664a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        DCHECK_EQ((value & 0x3), 0);
6651fd3346740dfb7f47be9922312b68a4227fada96buzbee        return NewLIR1(kThumbAddSpI7, value >> 2);
666fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      } else if (short_form) {
667a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        opcode = (neg) ? kThumbSubRI8 : kThumbAddRI8;
668a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
669a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
670a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpSub:
6712700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee      if (!neg && (r_dest_src1 == rs_r13sp) && (value <= 508)) { /* sp */
672a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        DCHECK_EQ((value & 0x3), 0);
6731fd3346740dfb7f47be9922312b68a4227fada96buzbee        return NewLIR1(kThumbSubSpI7, value >> 2);
674fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      } else if (short_form) {
675a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        opcode = (neg) ? kThumbAddRI8 : kThumbSubRI8;
676a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
677a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
678a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpCmp:
6792247984899247b1402408d39731ff64048f0e274Vladimir Marko      if (!neg && short_form) {
6802247984899247b1402408d39731ff64048f0e274Vladimir Marko        opcode = kThumbCmpRI8;
6819b7085a4e7c40e7fa01932ea1647a4a33ac1c585Brian Carlstrom      } else {
682fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        short_form = false;
683a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
684a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
685a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    default:
68652a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee      /* Punt to OpRegRegImm - if bad case catch it there */
687fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      short_form = false;
688a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
689a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
6909b7085a4e7c40e7fa01932ea1647a4a33ac1c585Brian Carlstrom  if (short_form) {
6912700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    return NewLIR2(opcode, r_dest_src1.GetReg(), abs_value);
6929b7085a4e7c40e7fa01932ea1647a4a33ac1c585Brian Carlstrom  } else {
6931fd3346740dfb7f47be9922312b68a4227fada96buzbee    return OpRegRegImm(op, r_dest_src1, r_dest_src1, value);
694a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
69567bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
69667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
6972700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* ArmMir2Lir::LoadConstantWide(RegStorage r_dest, int64_t value) {
6982cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  LIR* res = nullptr;
6994ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  int32_t val_lo = Low32Bits(value);
7004ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  int32_t val_hi = High32Bits(value);
701091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  if (r_dest.IsFloat()) {
702091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    DCHECK(!r_dest.IsPair());
7037da142fc1cefeeb24d997ae21b34381fdd2c0466buzbee    if ((val_lo == 0) && (val_hi == 0)) {
7047da142fc1cefeeb24d997ae21b34381fdd2c0466buzbee      // TODO: we need better info about the target CPU.  a vector exclusive or
7057da142fc1cefeeb24d997ae21b34381fdd2c0466buzbee      //       would probably be better here if we could rely on its existance.
7067da142fc1cefeeb24d997ae21b34381fdd2c0466buzbee      // Load an immediate +2.0 (which encodes to 0)
707091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      NewLIR2(kThumb2Vmovd_IMM8, r_dest.GetReg(), 0);
7087da142fc1cefeeb24d997ae21b34381fdd2c0466buzbee      // +0.0 = +2.0 - +2.0
709091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      res = NewLIR3(kThumb2Vsubd, r_dest.GetReg(), r_dest.GetReg(), r_dest.GetReg());
71067bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    } else {
7114ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      int encoded_imm = EncodeImmDouble(value);
7127da142fc1cefeeb24d997ae21b34381fdd2c0466buzbee      if (encoded_imm >= 0) {
713091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee        res = NewLIR2(kThumb2Vmovd_IMM8, r_dest.GetReg(), encoded_imm);
714a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
71567bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    }
716a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  } else {
717091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    // NOTE: Arm32 assumption here.
718091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    DCHECK(r_dest.IsPair());
7194ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    if ((InexpensiveConstantInt(val_lo) && (InexpensiveConstantInt(val_hi)))) {
7202700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee      res = LoadConstantNoClobber(r_dest.GetLow(), val_lo);
7212700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee      LoadConstantNoClobber(r_dest.GetHigh(), val_hi);
7224ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    }
7234ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  }
7242cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  if (res == nullptr) {
7254ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    // No short form - load from the literal pool.
7261fd3346740dfb7f47be9922312b68a4227fada96buzbee    LIR* data_target = ScanLiteralPoolWide(literal_list_, val_lo, val_hi);
7272cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier    if (data_target == nullptr) {
7281fd3346740dfb7f47be9922312b68a4227fada96buzbee      data_target = AddWideData(&literal_list_, val_lo, val_hi);
7294ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    }
7308dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko    ScopedMemRefType mem_ref_type(this, ResourceMask::kLiteral);
731091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    if (r_dest.IsFloat()) {
7321fd3346740dfb7f47be9922312b68a4227fada96buzbee      res = RawLIR(current_dalvik_offset_, kThumb2Vldrd,
733091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee                   r_dest.GetReg(), rs_r15pc.GetReg(), 0, 0, 0, data_target);
7344ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    } else {
7352700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee      DCHECK(r_dest.IsPair());
7361fd3346740dfb7f47be9922312b68a4227fada96buzbee      res = RawLIR(current_dalvik_offset_, kThumb2LdrdPcRel8,
737091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee                   r_dest.GetLowReg(), r_dest.GetHighReg(), rs_r15pc.GetReg(), 0, 0, data_target);
7384ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    }
7391fd3346740dfb7f47be9922312b68a4227fada96buzbee    AppendLIR(res);
740a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
741a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return res;
74267bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
74367bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
7441fd3346740dfb7f47be9922312b68a4227fada96buzbeeint ArmMir2Lir::EncodeShift(int code, int amount) {
745a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return ((amount & 0x1f) << 2) | code;
74667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
74767bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
7482700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* ArmMir2Lir::LoadBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_dest,
7492ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                                 int scale, OpSize size) {
750091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  bool all_low_regs = r_base.Low8() && r_index.Low8() && r_dest.Low8();
751a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  LIR* load;
752a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  ArmOpcode opcode = kThumbBkpt;
753fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  bool thumb_form = (all_low_regs && (scale == 0));
7542700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  RegStorage reg_ptr;
75567bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
756091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  if (r_dest.IsFloat()) {
757091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    if (r_dest.IsSingle()) {
758fd698e67953e40e804d7c9d1a3e8460e9d67382abuzbee      DCHECK((size == k32) || (size == kSingle) || (size == kReference));
759a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      opcode = kThumb2Vldrs;
760a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      size = kSingle;
76167bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    } else {
762091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      DCHECK(r_dest.IsDouble());
763695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee      DCHECK((size == k64) || (size == kDouble));
764a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      opcode = kThumb2Vldrd;
765a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      size = kDouble;
76667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    }
767a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  } else {
768a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    if (size == kSingle)
769695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee      size = k32;
770a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
77167bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
772a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  switch (size) {
7737934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom    case kDouble:  // fall-through
774695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee    // Intentional fall-though.
775a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kSingle:
7761fd3346740dfb7f47be9922312b68a4227fada96buzbee      reg_ptr = AllocTemp();
777a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      if (scale) {
7782700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee        NewLIR4(kThumb2AddRRR, reg_ptr.GetReg(), r_base.GetReg(), r_index.GetReg(),
77952a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee                EncodeShift(kArmLsl, scale));
780a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      } else {
7812700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee        OpRegRegReg(kOpAdd, reg_ptr, r_base, r_index);
782a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
7832700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee      load = NewLIR3(opcode, r_dest.GetReg(), reg_ptr.GetReg(), 0);
7841fd3346740dfb7f47be9922312b68a4227fada96buzbee      FreeTemp(reg_ptr);
785a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      return load;
786695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee    case k32:
787695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee    // Intentional fall-though.
788695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee    case kReference:
789fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = (thumb_form) ? kThumbLdrRRR : kThumb2LdrRRR;
790a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
791a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kUnsignedHalf:
792fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = (thumb_form) ? kThumbLdrhRRR : kThumb2LdrhRRR;
793a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
794a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kSignedHalf:
795fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = (thumb_form) ? kThumbLdrshRRR : kThumb2LdrshRRR;
796a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
797a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kUnsignedByte:
798fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = (thumb_form) ? kThumbLdrbRRR : kThumb2LdrbRRR;
799a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
800a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kSignedByte:
801fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = (thumb_form) ? kThumbLdrsbRRR : kThumb2LdrsbRRR;
802a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
803a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    default:
804cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      LOG(FATAL) << "Bad size: " << size;
805a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
806fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (thumb_form)
8072700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    load = NewLIR3(opcode, r_dest.GetReg(), r_base.GetReg(), r_index.GetReg());
808a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  else
8092700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    load = NewLIR4(opcode, r_dest.GetReg(), r_base.GetReg(), r_index.GetReg(), scale);
81067bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
811a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return load;
81267bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
81367bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
8142700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* ArmMir2Lir::StoreBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_src,
8152ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                                  int scale, OpSize size) {
816091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  bool all_low_regs = r_base.Low8() && r_index.Low8() && r_src.Low8();
8172cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  LIR* store = nullptr;
818a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  ArmOpcode opcode = kThumbBkpt;
819fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  bool thumb_form = (all_low_regs && (scale == 0));
8202700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  RegStorage reg_ptr;
82167bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
822091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  if (r_src.IsFloat()) {
823091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    if (r_src.IsSingle()) {
824fd698e67953e40e804d7c9d1a3e8460e9d67382abuzbee      DCHECK((size == k32) || (size == kSingle) || (size == kReference));
825a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      opcode = kThumb2Vstrs;
826a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      size = kSingle;
82767bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    } else {
828091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      DCHECK(r_src.IsDouble());
829695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee      DCHECK((size == k64) || (size == kDouble));
8302700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee      DCHECK_EQ((r_src.GetReg() & 0x1), 0);
831a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      opcode = kThumb2Vstrd;
832a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      size = kDouble;
83367bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    }
834a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  } else {
835a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    if (size == kSingle)
836695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee      size = k32;
837a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
83867bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
839a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  switch (size) {
8407934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom    case kDouble:  // fall-through
841695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee    // Intentional fall-though.
842a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kSingle:
8431fd3346740dfb7f47be9922312b68a4227fada96buzbee      reg_ptr = AllocTemp();
844a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      if (scale) {
8452700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee        NewLIR4(kThumb2AddRRR, reg_ptr.GetReg(), r_base.GetReg(), r_index.GetReg(),
84652a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee                EncodeShift(kArmLsl, scale));
847a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      } else {
8482700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee        OpRegRegReg(kOpAdd, reg_ptr, r_base, r_index);
849a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
8502700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee      store = NewLIR3(opcode, r_src.GetReg(), reg_ptr.GetReg(), 0);
8511fd3346740dfb7f47be9922312b68a4227fada96buzbee      FreeTemp(reg_ptr);
852a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      return store;
853695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee    case k32:
854695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee    // Intentional fall-though.
855695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee    case kReference:
856fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = (thumb_form) ? kThumbStrRRR : kThumb2StrRRR;
857a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
858a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kUnsignedHalf:
859695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee    // Intentional fall-though.
860a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kSignedHalf:
861fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = (thumb_form) ? kThumbStrhRRR : kThumb2StrhRRR;
862a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
863a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kUnsignedByte:
864695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee    // Intentional fall-though.
865a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kSignedByte:
866fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = (thumb_form) ? kThumbStrbRRR : kThumb2StrbRRR;
867a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
868a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    default:
869cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      LOG(FATAL) << "Bad size: " << size;
870a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
871fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (thumb_form)
8722700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    store = NewLIR3(opcode, r_src.GetReg(), r_base.GetReg(), r_index.GetReg());
873a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  else
8742700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    store = NewLIR4(opcode, r_src.GetReg(), r_base.GetReg(), r_index.GetReg(), scale);
87567bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
876a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return store;
87767bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
87867bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
879db9d523ff305721d4ca3f1470d1b2ce64c736e0aVladimir Marko// Helper function for LoadBaseDispBody()/StoreBaseDispBody().
88037573977769e9068874506050c62acd4e324d246Vladimir MarkoLIR* ArmMir2Lir::LoadStoreUsingInsnWithOffsetImm8Shl2(ArmOpcode opcode, RegStorage r_base,
88137573977769e9068874506050c62acd4e324d246Vladimir Marko                                                      int displacement, RegStorage r_src_dest,
88237573977769e9068874506050c62acd4e324d246Vladimir Marko                                                      RegStorage r_work) {
883db9d523ff305721d4ca3f1470d1b2ce64c736e0aVladimir Marko  DCHECK_EQ(displacement & 3, 0);
88437573977769e9068874506050c62acd4e324d246Vladimir Marko  constexpr int kOffsetMask = 0xff << 2;
88537573977769e9068874506050c62acd4e324d246Vladimir Marko  int encoded_disp = (displacement & kOffsetMask) >> 2;  // Within range of the instruction.
886db9d523ff305721d4ca3f1470d1b2ce64c736e0aVladimir Marko  RegStorage r_ptr = r_base;
88737573977769e9068874506050c62acd4e324d246Vladimir Marko  if ((displacement & ~kOffsetMask) != 0) {
888db9d523ff305721d4ca3f1470d1b2ce64c736e0aVladimir Marko    r_ptr = r_work.Valid() ? r_work : AllocTemp();
88937573977769e9068874506050c62acd4e324d246Vladimir Marko    // Add displacement & ~kOffsetMask to base, it's a single instruction for up to +-256KiB.
89037573977769e9068874506050c62acd4e324d246Vladimir Marko    OpRegRegImm(kOpAdd, r_ptr, r_base, displacement & ~kOffsetMask);
891db9d523ff305721d4ca3f1470d1b2ce64c736e0aVladimir Marko  }
892db9d523ff305721d4ca3f1470d1b2ce64c736e0aVladimir Marko  LIR* lir = nullptr;
893db9d523ff305721d4ca3f1470d1b2ce64c736e0aVladimir Marko  if (!r_src_dest.IsPair()) {
894db9d523ff305721d4ca3f1470d1b2ce64c736e0aVladimir Marko    lir = NewLIR3(opcode, r_src_dest.GetReg(), r_ptr.GetReg(), encoded_disp);
895db9d523ff305721d4ca3f1470d1b2ce64c736e0aVladimir Marko  } else {
896db9d523ff305721d4ca3f1470d1b2ce64c736e0aVladimir Marko    lir = NewLIR4(opcode, r_src_dest.GetLowReg(), r_src_dest.GetHighReg(), r_ptr.GetReg(),
897db9d523ff305721d4ca3f1470d1b2ce64c736e0aVladimir Marko                  encoded_disp);
898db9d523ff305721d4ca3f1470d1b2ce64c736e0aVladimir Marko  }
89937573977769e9068874506050c62acd4e324d246Vladimir Marko  if ((displacement & ~kOffsetMask) != 0 && !r_work.Valid()) {
900db9d523ff305721d4ca3f1470d1b2ce64c736e0aVladimir Marko    FreeTemp(r_ptr);
901db9d523ff305721d4ca3f1470d1b2ce64c736e0aVladimir Marko  }
902db9d523ff305721d4ca3f1470d1b2ce64c736e0aVladimir Marko  return lir;
903db9d523ff305721d4ca3f1470d1b2ce64c736e0aVladimir Marko}
904db9d523ff305721d4ca3f1470d1b2ce64c736e0aVladimir Marko
90567bf885d62b1473c833bece1c9e0bb624e6ba391buzbee/*
90667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * Load value from base + displacement.  Optionally perform null check
907fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee * on base (which must have an associated s_reg and MIR).  If not
90867bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * performing null check, incoming MIR can be null.
90967bf885d62b1473c833bece1c9e0bb624e6ba391buzbee */
9102700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* ArmMir2Lir::LoadBaseDispBody(RegStorage r_base, int displacement, RegStorage r_dest,
9113bf7c60a86d49bf8c05c5d2ac5ca8e9f80bd9824Vladimir Marko                                  OpSize size) {
912aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko  LIR* load = nullptr;
913aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko  ArmOpcode opcode16 = kThumbBkpt;  // 16-bit Thumb opcode.
914aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko  ArmOpcode opcode32 = kThumbBkpt;  // 32-bit Thumb2 opcode.
915fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  bool short_form = false;
916091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  bool all_low = r_dest.Is32Bit() && r_base.Low8() && r_dest.Low8();
917aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko  int scale = 0;  // Used for opcode16 and some indexed loads.
9184ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  bool already_generated = false;
919a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  switch (size) {
920a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kDouble:
921695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee    // Intentional fall-though.
922db9d523ff305721d4ca3f1470d1b2ce64c736e0aVladimir Marko    case k64:
923091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      if (r_dest.IsFloat()) {
924091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee        DCHECK(!r_dest.IsPair());
92537573977769e9068874506050c62acd4e324d246Vladimir Marko        load = LoadStoreUsingInsnWithOffsetImm8Shl2(kThumb2Vldrd, r_base, displacement, r_dest);
926a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      } else {
927db9d523ff305721d4ca3f1470d1b2ce64c736e0aVladimir Marko        DCHECK(r_dest.IsPair());
928db9d523ff305721d4ca3f1470d1b2ce64c736e0aVladimir Marko        // Use the r_dest.GetLow() for the temporary pointer if needed.
92937573977769e9068874506050c62acd4e324d246Vladimir Marko        load = LoadStoreUsingInsnWithOffsetImm8Shl2(kThumb2LdrdI8, r_base, displacement, r_dest,
93037573977769e9068874506050c62acd4e324d246Vladimir Marko                                                    r_dest.GetLow());
931a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
9323bf7c60a86d49bf8c05c5d2ac5ca8e9f80bd9824Vladimir Marko      already_generated = true;
9332700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee      break;
934a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kSingle:
935695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee    // Intentional fall-though.
936695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee    case k32:
937695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee    // Intentional fall-though.
938695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee    case kReference:
939091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      if (r_dest.IsFloat()) {
940db9d523ff305721d4ca3f1470d1b2ce64c736e0aVladimir Marko        DCHECK(r_dest.IsSingle());
94137573977769e9068874506050c62acd4e324d246Vladimir Marko        load = LoadStoreUsingInsnWithOffsetImm8Shl2(kThumb2Vldrs, r_base, displacement, r_dest);
942db9d523ff305721d4ca3f1470d1b2ce64c736e0aVladimir Marko        already_generated = true;
943a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        break;
944a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
945aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      DCHECK_EQ((displacement & 0x3), 0);
946aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      scale = 2;
947091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      if (r_dest.Low8() && (r_base == rs_rARM_PC) && (displacement <= 1020) &&
948091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee          (displacement >= 0)) {
949fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        short_form = true;
950aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko        opcode16 = kThumbLdrPcRel;
951091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      } else if (r_dest.Low8() && (r_base == rs_rARM_SP) && (displacement <= 1020) &&
952091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee                 (displacement >= 0)) {
953fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        short_form = true;
954aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko        opcode16 = kThumbLdrSpRel;
955aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      } else {
956aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko        short_form = all_low && (displacement >> (5 + scale)) == 0;
957aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko        opcode16 = kThumbLdrRRI5;
958aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko        opcode32 = kThumb2LdrRRI12;
959a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
960a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
961a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kUnsignedHalf:
962aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      DCHECK_EQ((displacement & 0x1), 0);
963aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      scale = 1;
964aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      short_form = all_low && (displacement >> (5 + scale)) == 0;
965aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      opcode16 = kThumbLdrhRRI5;
966aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      opcode32 = kThumb2LdrhRRI12;
967a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
968a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kSignedHalf:
969aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      DCHECK_EQ((displacement & 0x1), 0);
970aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      scale = 1;
971aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      DCHECK_EQ(opcode16, kThumbBkpt);  // Not available.
972aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      opcode32 = kThumb2LdrshRRI12;
973a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
974a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kUnsignedByte:
975aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      DCHECK_EQ(scale, 0);  // Keep scale = 0.
976aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      short_form = all_low && (displacement >> (5 + scale)) == 0;
977aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      opcode16 = kThumbLdrbRRI5;
978aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      opcode32 = kThumb2LdrbRRI12;
979a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
980a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kSignedByte:
981aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      DCHECK_EQ(scale, 0);  // Keep scale = 0.
982aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      DCHECK_EQ(opcode16, kThumbBkpt);  // Not available.
983aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      opcode32 = kThumb2LdrsbRRI12;
984a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
985a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    default:
986cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      LOG(FATAL) << "Bad size: " << size;
987a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
98867bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
9894ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  if (!already_generated) {
9904ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    if (short_form) {
991aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      load = NewLIR3(opcode16, r_dest.GetReg(), r_base.GetReg(), displacement >> scale);
992aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko    } else if ((displacement >> 12) == 0) {  // Thumb2 form.
993aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      load = NewLIR3(opcode32, r_dest.GetReg(), r_base.GetReg(), displacement);
994aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko    } else if (!InexpensiveConstantInt(displacement >> scale, Instruction::CONST) &&
995aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko        InexpensiveConstantInt(displacement & ~0x00000fff, Instruction::ADD_INT)) {
996aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      // In this case, using LoadIndexed would emit 3 insns (movw+movt+ldr) but we can
997aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      // actually do it in two because we know that the kOpAdd is a single insn. On the
998aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      // other hand, we introduce an extra dependency, so this is not necessarily faster.
999aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      if (opcode16 != kThumbBkpt && r_dest.Low8() &&
1000aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko          InexpensiveConstantInt(displacement & ~(0x1f << scale), Instruction::ADD_INT)) {
1001aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko        // We can use the 16-bit Thumb opcode for the load.
1002aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko        OpRegRegImm(kOpAdd, r_dest, r_base, displacement & ~(0x1f << scale));
1003aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko        load = NewLIR3(opcode16, r_dest.GetReg(), r_dest.GetReg(), (displacement >> scale) & 0x1f);
1004aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      } else {
1005aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko        DCHECK_NE(opcode32, kThumbBkpt);
1006aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko        OpRegRegImm(kOpAdd, r_dest, r_base, displacement & ~0x00000fff);
1007aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko        load = NewLIR3(opcode32, r_dest.GetReg(), r_dest.GetReg(), displacement & 0x00000fff);
1008aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      }
10094ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    } else {
1010aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      if (!InexpensiveConstantInt(displacement >> scale, Instruction::CONST) ||
1011aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko          (scale != 0 && InexpensiveConstantInt(displacement, Instruction::CONST))) {
1012aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko        scale = 0;  // Prefer unscaled indexing if the same number of insns.
1013aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      }
10142700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee      RegStorage reg_offset = AllocTemp();
1015aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      LoadConstant(reg_offset, displacement >> scale);
1016db9d523ff305721d4ca3f1470d1b2ce64c736e0aVladimir Marko      DCHECK(!r_dest.IsFloat());
1017aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      load = LoadBaseIndexed(r_base, reg_offset, r_dest, scale, size);
10181fd3346740dfb7f47be9922312b68a4227fada96buzbee      FreeTemp(reg_offset);
10194ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    }
1020a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
102167bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
1022a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  // TODO: in future may need to differentiate Dalvik accesses w/ spills
10238dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko  if (mem_ref_type_ == ResourceMask::kDalvikReg) {
1024b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers    DCHECK_EQ(r_base, rs_rARM_SP);
10252700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    AnnotateDalvikRegAccess(load, displacement >> 2, true /* is_load */, r_dest.Is64Bit());
1026a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
1027a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return load;
102867bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
102967bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
1030674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir MarkoLIR* ArmMir2Lir::LoadBaseDisp(RegStorage r_base, int displacement, RegStorage r_dest,
10313c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe                              OpSize size, VolatileKind is_volatile) {
1032695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee  // TODO: base this on target.
1033695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee  if (size == kWord) {
1034695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee    size = k32;
1035695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee  }
10363c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe  LIR* load;
10376f3dbbadf4ce66982eb3d400e0a74cb73eb034f3Ian Rogers  if (is_volatile == kVolatile && (size == k64 || size == kDouble) &&
10386f3dbbadf4ce66982eb3d400e0a74cb73eb034f3Ian Rogers      !cu_->compiler_driver->GetInstructionSetFeatures()->
1039d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers          AsArmInstructionSetFeatures()->HasAtomicLdrdAndStrd()) {
10403c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe    // Only 64-bit load needs special handling.
10413c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe    // If the cpu supports LPAE, aligned LDRD is atomic - fall through to LoadBaseDisp().
10423c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe    DCHECK(!r_dest.IsFloat());  // See RegClassForFieldLoadSave().
10433c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe    // Use LDREXD for the atomic load. (Expect displacement > 0, don't optimize for == 0.)
10443c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe    RegStorage r_ptr = AllocTemp();
10453c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe    OpRegRegImm(kOpAdd, r_ptr, r_base, displacement);
1046ee5e273e4d0dd91b480c8d5dbcccad15c1b7353cVladimir Marko    load = NewLIR3(kThumb2Ldrexd, r_dest.GetLowReg(), r_dest.GetHighReg(), r_ptr.GetReg());
10473c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe    FreeTemp(r_ptr);
10483c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe  } else {
10493c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe    load = LoadBaseDispBody(r_base, displacement, r_dest, size);
10503c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe  }
10513c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe
10523c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe  if (UNLIKELY(is_volatile == kVolatile)) {
105348f5c47907654350ce30a8dfdda0e977f5d3d39fHans Boehm    GenMemBarrier(kLoadAny);
10543c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe  }
10553c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe
10563c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe  return load;
105767bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
105867bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
105967bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
10602700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* ArmMir2Lir::StoreBaseDispBody(RegStorage r_base, int displacement, RegStorage r_src,
10612700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee                                   OpSize size) {
1062aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko  LIR* store = nullptr;
1063aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko  ArmOpcode opcode16 = kThumbBkpt;  // 16-bit Thumb opcode.
1064aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko  ArmOpcode opcode32 = kThumbBkpt;  // 32-bit Thumb2 opcode.
1065fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  bool short_form = false;
1066091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  bool all_low = r_src.Is32Bit() && r_base.Low8() && r_src.Low8();
1067aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko  int scale = 0;  // Used for opcode16 and some indexed loads.
10684ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  bool already_generated = false;
1069a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  switch (size) {
1070a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kDouble:
10713bf7c60a86d49bf8c05c5d2ac5ca8e9f80bd9824Vladimir Marko    // Intentional fall-though.
1072db9d523ff305721d4ca3f1470d1b2ce64c736e0aVladimir Marko    case k64:
10733bf7c60a86d49bf8c05c5d2ac5ca8e9f80bd9824Vladimir Marko      if (r_src.IsFloat()) {
10745667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu        // Note: If the register is retrieved by register allocator, it should never be a pair.
10755667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu        // But some functions in mir2lir assume 64-bit registers are 32-bit register pairs.
10765667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu        // TODO: Rework Mir2Lir::LoadArg() and Mir2Lir::LoadArgDirect().
10775667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu        if (r_src.IsPair()) {
10785667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu          r_src = As64BitFloatReg(r_src);
10795667fdbb6e441dee7534ade18b628ed396daf593Zheng Xu        }
1080091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee        DCHECK(!r_src.IsPair());
108137573977769e9068874506050c62acd4e324d246Vladimir Marko        store = LoadStoreUsingInsnWithOffsetImm8Shl2(kThumb2Vstrd, r_base, displacement, r_src);
10823bf7c60a86d49bf8c05c5d2ac5ca8e9f80bd9824Vladimir Marko      } else {
1083db9d523ff305721d4ca3f1470d1b2ce64c736e0aVladimir Marko        DCHECK(r_src.IsPair());
108437573977769e9068874506050c62acd4e324d246Vladimir Marko        store = LoadStoreUsingInsnWithOffsetImm8Shl2(kThumb2StrdI8, r_base, displacement, r_src);
1085a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
10863bf7c60a86d49bf8c05c5d2ac5ca8e9f80bd9824Vladimir Marko      already_generated = true;
1087a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
1088a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kSingle:
1089091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    // Intentional fall-through.
1090695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee    case k32:
1091091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    // Intentional fall-through.
1092695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee    case kReference:
1093091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      if (r_src.IsFloat()) {
1094091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee        DCHECK(r_src.IsSingle());
109537573977769e9068874506050c62acd4e324d246Vladimir Marko        store = LoadStoreUsingInsnWithOffsetImm8Shl2(kThumb2Vstrs, r_base, displacement, r_src);
1096db9d523ff305721d4ca3f1470d1b2ce64c736e0aVladimir Marko        already_generated = true;
1097a188cd4ad38aa561742d5f3f5b45215f451cb834Sebastien Hertz        break;
1098a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
1099aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      DCHECK_EQ((displacement & 0x3), 0);
1100aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      scale = 2;
1101091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      if (r_src.Low8() && (r_base == rs_r13sp) && (displacement <= 1020) && (displacement >= 0)) {
1102a188cd4ad38aa561742d5f3f5b45215f451cb834Sebastien Hertz        short_form = true;
1103aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko        opcode16 = kThumbStrSpRel;
1104aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      } else {
1105aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko        short_form = all_low && (displacement >> (5 + scale)) == 0;
1106aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko        opcode16 = kThumbStrRRI5;
1107aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko        opcode32 = kThumb2StrRRI12;
1108a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
1109a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
1110a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kUnsignedHalf:
1111a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kSignedHalf:
1112aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      DCHECK_EQ((displacement & 0x1), 0);
1113aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      scale = 1;
1114aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      short_form = all_low && (displacement >> (5 + scale)) == 0;
1115aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      opcode16 = kThumbStrhRRI5;
1116aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      opcode32 = kThumb2StrhRRI12;
1117a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
1118a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kUnsignedByte:
1119a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kSignedByte:
1120aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      DCHECK_EQ(scale, 0);  // Keep scale = 0.
1121aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      short_form = all_low && (displacement >> (5 + scale)) == 0;
1122aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      opcode16 = kThumbStrbRRI5;
1123aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      opcode32 = kThumb2StrbRRI12;
1124a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
1125a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    default:
1126cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      LOG(FATAL) << "Bad size: " << size;
1127a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
11284ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  if (!already_generated) {
11294ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    if (short_form) {
1130aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      store = NewLIR3(opcode16, r_src.GetReg(), r_base.GetReg(), displacement >> scale);
1131aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko    } else if ((displacement >> 12) == 0) {
1132aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      store = NewLIR3(opcode32, r_src.GetReg(), r_base.GetReg(), displacement);
1133aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko    } else if (!InexpensiveConstantInt(displacement >> scale, Instruction::CONST) &&
1134aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko        InexpensiveConstantInt(displacement & ~0x00000fff, Instruction::ADD_INT)) {
1135aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      // In this case, using StoreIndexed would emit 3 insns (movw+movt+str) but we can
1136aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      // actually do it in two because we know that the kOpAdd is a single insn. On the
1137aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      // other hand, we introduce an extra dependency, so this is not necessarily faster.
1138aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      RegStorage r_scratch = AllocTemp();
1139aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      if (opcode16 != kThumbBkpt && r_src.Low8() && r_scratch.Low8() &&
1140aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko          InexpensiveConstantInt(displacement & ~(0x1f << scale), Instruction::ADD_INT)) {
1141aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko        // We can use the 16-bit Thumb opcode for the load.
1142aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko        OpRegRegImm(kOpAdd, r_scratch, r_base, displacement & ~(0x1f << scale));
1143aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko        store = NewLIR3(opcode16, r_src.GetReg(), r_scratch.GetReg(),
1144aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko                        (displacement >> scale) & 0x1f);
1145aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      } else {
1146aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko        DCHECK_NE(opcode32, kThumbBkpt);
1147aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko        OpRegRegImm(kOpAdd, r_scratch, r_base, displacement & ~0x00000fff);
1148aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko        store = NewLIR3(opcode32, r_src.GetReg(), r_scratch.GetReg(), displacement & 0x00000fff);
1149aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      }
1150aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      FreeTemp(r_scratch);
11514ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    } else {
1152aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      if (!InexpensiveConstantInt(displacement >> scale, Instruction::CONST) ||
1153aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko          (scale != 0 && InexpensiveConstantInt(displacement, Instruction::CONST))) {
1154aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko        scale = 0;  // Prefer unscaled indexing if the same number of insns.
1155aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      }
11562700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee      RegStorage r_scratch = AllocTemp();
1157aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      LoadConstant(r_scratch, displacement >> scale);
1158db9d523ff305721d4ca3f1470d1b2ce64c736e0aVladimir Marko      DCHECK(!r_src.IsFloat());
1159aed3ad734c47fdccf179ff65971284a0d38583cdVladimir Marko      store = StoreBaseIndexed(r_base, r_scratch, r_src, scale, size);
11601fd3346740dfb7f47be9922312b68a4227fada96buzbee      FreeTemp(r_scratch);
11614ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    }
1162a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
116367bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
1164a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  // TODO: In future, may need to differentiate Dalvik & spill accesses
11658dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko  if (mem_ref_type_ == ResourceMask::kDalvikReg) {
1166b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers    DCHECK_EQ(r_base, rs_rARM_SP);
11672700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    AnnotateDalvikRegAccess(store, displacement >> 2, false /* is_load */, r_src.Is64Bit());
1168a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
11694ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  return store;
117067bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
117167bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
11723c12c512faf6837844d5465b23b9410889e5eb11Andreas GampeLIR* ArmMir2Lir::StoreBaseDisp(RegStorage r_base, int displacement, RegStorage r_src,
11733c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe                               OpSize size, VolatileKind is_volatile) {
11743c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe  if (UNLIKELY(is_volatile == kVolatile)) {
117548f5c47907654350ce30a8dfdda0e977f5d3d39fHans Boehm    // Ensure that prior accesses become visible to other threads first.
117648f5c47907654350ce30a8dfdda0e977f5d3d39fHans Boehm    GenMemBarrier(kAnyStore);
11773c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe  }
11783c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe
1179ee5e273e4d0dd91b480c8d5dbcccad15c1b7353cVladimir Marko  LIR* null_ck_insn;
11806f3dbbadf4ce66982eb3d400e0a74cb73eb034f3Ian Rogers  if (is_volatile == kVolatile && (size == k64 || size == kDouble) &&
11816f3dbbadf4ce66982eb3d400e0a74cb73eb034f3Ian Rogers      !cu_->compiler_driver->GetInstructionSetFeatures()->
1182d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers          AsArmInstructionSetFeatures()->HasAtomicLdrdAndStrd()) {
11833c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe    // Only 64-bit store needs special handling.
1184de68676b24f61a55adc0b22fe828f036a5925c41Andreas Gampe    // If the cpu supports LPAE, aligned STRD is atomic - fall through to StoreBaseDisp().
11853c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe    // Use STREXD for the atomic store. (Expect displacement > 0, don't optimize for == 0.)
11863c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe    DCHECK(!r_src.IsFloat());  // See RegClassForFieldLoadSave().
11873c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe    RegStorage r_ptr = AllocTemp();
11883c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe    OpRegRegImm(kOpAdd, r_ptr, r_base, displacement);
11893c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe    LIR* fail_target = NewLIR0(kPseudoTargetLabel);
11903c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe    // We have only 5 temporary registers available and if r_base, r_src and r_ptr already
11913c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe    // take 4, we can't directly allocate 2 more for LDREXD temps. In that case clobber r_ptr
11923c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe    // in LDREXD and recalculate it from r_base.
11933c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe    RegStorage r_temp = AllocTemp();
11949ee4519afd97121f893f82d41d23164fc6c9ed34Serguei Katkov    RegStorage r_temp_high = AllocTemp(false);  // We may not have another temp.
11953c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe    if (r_temp_high.Valid()) {
1196ee5e273e4d0dd91b480c8d5dbcccad15c1b7353cVladimir Marko      null_ck_insn = NewLIR3(kThumb2Ldrexd, r_temp.GetReg(), r_temp_high.GetReg(), r_ptr.GetReg());
11973c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe      FreeTemp(r_temp_high);
11983c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe      FreeTemp(r_temp);
11993c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe    } else {
12003c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe      // If we don't have another temp, clobber r_ptr in LDREXD and reload it.
1201ee5e273e4d0dd91b480c8d5dbcccad15c1b7353cVladimir Marko      null_ck_insn = NewLIR3(kThumb2Ldrexd, r_temp.GetReg(), r_ptr.GetReg(), r_ptr.GetReg());
12023c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe      FreeTemp(r_temp);  // May need the temp for kOpAdd.
1203674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko      OpRegRegImm(kOpAdd, r_ptr, r_base, displacement);
1204674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko    }
1205ee5e273e4d0dd91b480c8d5dbcccad15c1b7353cVladimir Marko    NewLIR4(kThumb2Strexd, r_temp.GetReg(), r_src.GetLowReg(), r_src.GetHighReg(), r_ptr.GetReg());
12063c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe    OpCmpImmBranch(kCondNe, r_temp, 0, fail_target);
12073c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe    FreeTemp(r_ptr);
12083c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe  } else {
12093c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe    // TODO: base this on target.
12103c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe    if (size == kWord) {
12113c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe      size = k32;
12123c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe    }
12133c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe
1214ee5e273e4d0dd91b480c8d5dbcccad15c1b7353cVladimir Marko    null_ck_insn = StoreBaseDispBody(r_base, displacement, r_src, size);
1215674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko  }
1216674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko
12173c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe  if (UNLIKELY(is_volatile == kVolatile)) {
121848f5c47907654350ce30a8dfdda0e977f5d3d39fHans Boehm    // Preserve order with respect to any subsequent volatile loads.
121948f5c47907654350ce30a8dfdda0e977f5d3d39fHans Boehm    // We need StoreLoad, but that generally requires the most expensive barrier.
122048f5c47907654350ce30a8dfdda0e977f5d3d39fHans Boehm    GenMemBarrier(kAnyAny);
1221695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee  }
12223c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe
1223ee5e273e4d0dd91b480c8d5dbcccad15c1b7353cVladimir Marko  return null_ck_insn;
122467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
122567bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
12262700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* ArmMir2Lir::OpFpRegCopy(RegStorage r_dest, RegStorage r_src) {
1227a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  int opcode;
1228091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  DCHECK_EQ(r_dest.IsDouble(), r_src.IsDouble());
1229091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  if (r_dest.IsDouble()) {
1230a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    opcode = kThumb2Vmovd;
1231a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  } else {
1232091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    if (r_dest.IsSingle()) {
1233091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      opcode = r_src.IsSingle() ? kThumb2Vmovs : kThumb2Fmsr;
123467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    } else {
1235091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      DCHECK(r_src.IsSingle());
1236a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      opcode = kThumb2Fmrs;
123767bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    }
1238a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
12392700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  LIR* res = RawLIR(current_dalvik_offset_, opcode, r_dest.GetReg(), r_src.GetReg());
12401fd3346740dfb7f47be9922312b68a4227fada96buzbee  if (!(cu_->disable_opt & (1 << kSafeOptimizations)) && r_dest == r_src) {
1241fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    res->flags.is_nop = true;
1242a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
1243a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return res;
124467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
124567bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
12462700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* ArmMir2Lir::OpMem(OpKind op, RegStorage r_base, int disp) {
12476a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers  UNUSED(op, r_base, disp);
124852a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee  LOG(FATAL) << "Unexpected use of OpMem for Arm";
12496a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers  UNREACHABLE();
1250b046e16d8b8da318d6055f9308950131f1255e08buzbee}
125167bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
1252984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas GampeLIR* ArmMir2Lir::InvokeTrampoline(OpKind op, RegStorage r_tgt, QuickEntrypointEnum trampoline) {
12536a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers  UNUSED(trampoline);  // The address of the trampoline is already loaded into r_tgt.
1254984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe  return OpReg(op, r_tgt);
1255b046e16d8b8da318d6055f9308950131f1255e08buzbee}
125611d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughes
125763999683329612292d534e6be09dbde9480f1250Serban Constantinescusize_t ArmMir2Lir::GetInstructionOffset(LIR* lir) {
125863999683329612292d534e6be09dbde9480f1250Serban Constantinescu  uint64_t check_flags = GetTargetInstFlags(lir->opcode);
125963999683329612292d534e6be09dbde9480f1250Serban Constantinescu  DCHECK((check_flags & IS_LOAD) || (check_flags & IS_STORE));
126063999683329612292d534e6be09dbde9480f1250Serban Constantinescu  size_t offset = (check_flags & IS_TERTIARY_OP) ? lir->operands[2] : 0;
126163999683329612292d534e6be09dbde9480f1250Serban Constantinescu
126263999683329612292d534e6be09dbde9480f1250Serban Constantinescu  if (check_flags & SCALED_OFFSET_X2) {
126363999683329612292d534e6be09dbde9480f1250Serban Constantinescu    offset = offset * 2;
126463999683329612292d534e6be09dbde9480f1250Serban Constantinescu  } else if (check_flags & SCALED_OFFSET_X4) {
126563999683329612292d534e6be09dbde9480f1250Serban Constantinescu    offset = offset * 4;
126663999683329612292d534e6be09dbde9480f1250Serban Constantinescu  }
126763999683329612292d534e6be09dbde9480f1250Serban Constantinescu  return offset;
126863999683329612292d534e6be09dbde9480f1250Serban Constantinescu}
126963999683329612292d534e6be09dbde9480f1250Serban Constantinescu
1270cc23481b66fd1f2b459d82da4852073e32f033aaVladimir Markovoid ArmMir2Lir::CountRefs(RefCounts* core_counts, RefCounts* fp_counts, size_t num_regs) {
1271cc23481b66fd1f2b459d82da4852073e32f033aaVladimir Marko  // Start with the default counts.
1272cc23481b66fd1f2b459d82da4852073e32f033aaVladimir Marko  Mir2Lir::CountRefs(core_counts, fp_counts, num_regs);
1273cc23481b66fd1f2b459d82da4852073e32f033aaVladimir Marko
1274cc23481b66fd1f2b459d82da4852073e32f033aaVladimir Marko  if (pc_rel_temp_ != nullptr) {
1275cc23481b66fd1f2b459d82da4852073e32f033aaVladimir Marko    // Now, if the dex cache array base temp is used only once outside any loops (weight = 1),
12761961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko    // avoid the promotion, otherwise boost the weight by factor 3 because the full PC-relative
12771961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko    // load sequence is 4 instructions long and by promoting the PC base we save up to 3
12781961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko    // instructions per use.
1279cc23481b66fd1f2b459d82da4852073e32f033aaVladimir Marko    int p_map_idx = SRegToPMap(pc_rel_temp_->s_reg_low);
1280cc23481b66fd1f2b459d82da4852073e32f033aaVladimir Marko    if (core_counts[p_map_idx].count == 1) {
1281cc23481b66fd1f2b459d82da4852073e32f033aaVladimir Marko      core_counts[p_map_idx].count = 0;
1282cc23481b66fd1f2b459d82da4852073e32f033aaVladimir Marko    } else {
12831961b609bfefaedb71cee3651c4f931cc3e7393dVladimir Marko      core_counts[p_map_idx].count *= 3;
1284cc23481b66fd1f2b459d82da4852073e32f033aaVladimir Marko    }
1285cc23481b66fd1f2b459d82da4852073e32f033aaVladimir Marko  }
1286cc23481b66fd1f2b459d82da4852073e32f033aaVladimir Marko}
1287cc23481b66fd1f2b459d82da4852073e32f033aaVladimir Marko
1288cc23481b66fd1f2b459d82da4852073e32f033aaVladimir Markovoid ArmMir2Lir::DoPromotion() {
1289cc23481b66fd1f2b459d82da4852073e32f033aaVladimir Marko  if (CanUseOpPcRelDexCacheArrayLoad()) {
1290cc23481b66fd1f2b459d82da4852073e32f033aaVladimir Marko    pc_rel_temp_ = mir_graph_->GetNewCompilerTemp(kCompilerTempBackend, false);
1291cc23481b66fd1f2b459d82da4852073e32f033aaVladimir Marko  }
1292cc23481b66fd1f2b459d82da4852073e32f033aaVladimir Marko
1293cc23481b66fd1f2b459d82da4852073e32f033aaVladimir Marko  Mir2Lir::DoPromotion();
1294cc23481b66fd1f2b459d82da4852073e32f033aaVladimir Marko
1295cc23481b66fd1f2b459d82da4852073e32f033aaVladimir Marko  if (pc_rel_temp_ != nullptr) {
1296cc23481b66fd1f2b459d82da4852073e32f033aaVladimir Marko    // Now, if the dex cache array base temp is promoted, remember the register but
1297cc23481b66fd1f2b459d82da4852073e32f033aaVladimir Marko    // always remove the temp's stack location to avoid unnecessarily bloating the stack.
1298cc23481b66fd1f2b459d82da4852073e32f033aaVladimir Marko    dex_cache_arrays_base_reg_ = mir_graph_->reg_location_[pc_rel_temp_->s_reg_low].reg;
1299cc23481b66fd1f2b459d82da4852073e32f033aaVladimir Marko    DCHECK(!dex_cache_arrays_base_reg_.Valid() || !dex_cache_arrays_base_reg_.IsFloat());
1300cc23481b66fd1f2b459d82da4852073e32f033aaVladimir Marko    mir_graph_->RemoveLastCompilerTemp(kCompilerTempBackend, false, pc_rel_temp_);
1301cc23481b66fd1f2b459d82da4852073e32f033aaVladimir Marko    pc_rel_temp_ = nullptr;
1302cc23481b66fd1f2b459d82da4852073e32f033aaVladimir Marko  }
1303cc23481b66fd1f2b459d82da4852073e32f033aaVladimir Marko}
1304cc23481b66fd1f2b459d82da4852073e32f033aaVladimir Marko
130511d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughes}  // namespace art
1306