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
171bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee#include "arm_lir.h"
1802031b185b4653e6c72e21f7a51238b903f6d638buzbee#include "codegen_arm.h"
197940e44f4517de5e2634a7e07d58d0fb26160513Brian Carlstrom#include "dex/quick/mir_to_lir-inl.h"
201bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee
2111d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughesnamespace art {
2211d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughes
23b046e16d8b8da318d6055f9308950131f1255e08buzbee/* This file contains codegen for the Thumb ISA. */
2467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
252ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromstatic int EncodeImmSingle(int value) {
26a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  int res;
27fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  int bit_a =  (value & 0x80000000) >> 31;
28fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  int not_bit_b = (value & 0x40000000) >> 30;
29fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  int bit_b =  (value & 0x20000000) >> 29;
30fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  int b_smear =  (value & 0x3e000000) >> 25;
31a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  int slice =   (value & 0x01f80000) >> 19;
32a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  int zeroes =  (value & 0x0007ffff);
33a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  if (zeroes != 0)
34a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    return -1;
35fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (bit_b) {
36fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if ((not_bit_b != 0) || (b_smear != 0x1f))
37a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      return -1;
38a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  } else {
39fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if ((not_bit_b != 1) || (b_smear != 0x0))
40a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      return -1;
41a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
42fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  res = (bit_a << 7) | (bit_b << 6) | slice;
43a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return res;
4467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
4567bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
464ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee/*
474ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee * Determine whether value can be encoded as a Thumb2 floating point
484ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee * immediate.  If not, return -1.  If so return encoded 8-bit value.
494ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee */
502ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromstatic int EncodeImmDouble(int64_t value) {
514ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  int res;
524ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  int bit_a = (value & 0x8000000000000000ll) >> 63;
534ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  int not_bit_b = (value & 0x4000000000000000ll) >> 62;
544ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  int bit_b = (value & 0x2000000000000000ll) >> 61;
554ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  int b_smear = (value & 0x3fc0000000000000ll) >> 54;
564ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  int slice =  (value & 0x003f000000000000ll) >> 48;
574ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  uint64_t zeroes = (value & 0x0000ffffffffffffll);
584ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  if (zeroes != 0)
594ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    return -1;
604ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  if (bit_b) {
614ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    if ((not_bit_b != 0) || (b_smear != 0xff))
624ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      return -1;
634ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  } else {
644ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    if ((not_bit_b != 1) || (b_smear != 0x0))
654ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      return -1;
664ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  }
674ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  res = (bit_a << 7) | (bit_b << 6) | slice;
684ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  return res;
694ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee}
704ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
712ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromLIR* ArmMir2Lir::LoadFPConstantValue(int r_dest, int value) {
72fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  DCHECK(ARM_SINGLEREG(r_dest));
737da142fc1cefeeb24d997ae21b34381fdd2c0466buzbee  if (value == 0) {
747da142fc1cefeeb24d997ae21b34381fdd2c0466buzbee    // TODO: we need better info about the target CPU.  a vector exclusive or
757da142fc1cefeeb24d997ae21b34381fdd2c0466buzbee    //       would probably be better here if we could rely on its existance.
767da142fc1cefeeb24d997ae21b34381fdd2c0466buzbee    // Load an immediate +2.0 (which encodes to 0)
771fd3346740dfb7f47be9922312b68a4227fada96buzbee    NewLIR2(kThumb2Vmovs_IMM8, r_dest, 0);
787da142fc1cefeeb24d997ae21b34381fdd2c0466buzbee    // +0.0 = +2.0 - +2.0
791fd3346740dfb7f47be9922312b68a4227fada96buzbee    return NewLIR3(kThumb2Vsubs, r_dest, r_dest, r_dest);
807da142fc1cefeeb24d997ae21b34381fdd2c0466buzbee  } else {
817da142fc1cefeeb24d997ae21b34381fdd2c0466buzbee    int encoded_imm = EncodeImmSingle(value);
827da142fc1cefeeb24d997ae21b34381fdd2c0466buzbee    if (encoded_imm >= 0) {
831fd3346740dfb7f47be9922312b68a4227fada96buzbee      return NewLIR2(kThumb2Vmovs_IMM8, r_dest, encoded_imm);
847da142fc1cefeeb24d997ae21b34381fdd2c0466buzbee    }
85a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
861fd3346740dfb7f47be9922312b68a4227fada96buzbee  LIR* data_target = ScanLiteralPool(literal_list_, value, 0);
87fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (data_target == NULL) {
881fd3346740dfb7f47be9922312b68a4227fada96buzbee    data_target = AddWordData(&literal_list_, value);
89a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
901fd3346740dfb7f47be9922312b68a4227fada96buzbee  LIR* load_pc_rel = RawLIR(current_dalvik_offset_, kThumb2Vldrs,
91fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                          r_dest, r15pc, 0, 0, 0, data_target);
921fd3346740dfb7f47be9922312b68a4227fada96buzbee  SetMemRefType(load_pc_rel, true, kLiteral);
93fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  load_pc_rel->alias_info = reinterpret_cast<uintptr_t>(data_target);
941fd3346740dfb7f47be9922312b68a4227fada96buzbee  AppendLIR(load_pc_rel);
95fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  return load_pc_rel;
9667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
9767bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
982ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromstatic int LeadingZeros(uint32_t val) {
99eaf09bc65f9a10d12befcdb239156938c9bceef2buzbee  uint32_t alt;
100a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  int n;
101a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  int count;
10267bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
103a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  count = 16;
104a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  n = 32;
105a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  do {
106a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    alt = val >> count;
107a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    if (alt != 0) {
108a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      n = n - count;
109a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      val = alt;
110a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    }
111a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    count >>= 1;
112a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  } while (count);
113a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return n - val;
11467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
11567bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
11667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee/*
11767bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * Determine whether value can be encoded as a Thumb2 modified
11867bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * immediate.  If not, return -1.  If so, return i:imm3:a:bcdefgh form.
11967bf885d62b1473c833bece1c9e0bb624e6ba391buzbee */
1202ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromint ArmMir2Lir::ModifiedImmediate(uint32_t value) {
1216f485c62b9cfce3ab71020c646ab9f48d9d29d6dBrian Carlstrom  int z_leading;
1226f485c62b9cfce3ab71020c646ab9f48d9d29d6dBrian Carlstrom  int z_trailing;
1236f485c62b9cfce3ab71020c646ab9f48d9d29d6dBrian Carlstrom  uint32_t b0 = value & 0xff;
12467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
1256f485c62b9cfce3ab71020c646ab9f48d9d29d6dBrian Carlstrom  /* Note: case of value==0 must use 0:000:0:0000000 encoding */
1266f485c62b9cfce3ab71020c646ab9f48d9d29d6dBrian Carlstrom  if (value <= 0xFF)
1276f485c62b9cfce3ab71020c646ab9f48d9d29d6dBrian Carlstrom    return b0;  // 0:000:a:bcdefgh
1286f485c62b9cfce3ab71020c646ab9f48d9d29d6dBrian Carlstrom  if (value == ((b0 << 16) | b0))
1296f485c62b9cfce3ab71020c646ab9f48d9d29d6dBrian Carlstrom    return (0x1 << 8) | b0; /* 0:001:a:bcdefgh */
1306f485c62b9cfce3ab71020c646ab9f48d9d29d6dBrian Carlstrom  if (value == ((b0 << 24) | (b0 << 16) | (b0 << 8) | b0))
1316f485c62b9cfce3ab71020c646ab9f48d9d29d6dBrian Carlstrom    return (0x3 << 8) | b0; /* 0:011:a:bcdefgh */
1326f485c62b9cfce3ab71020c646ab9f48d9d29d6dBrian Carlstrom  b0 = (value >> 8) & 0xff;
1336f485c62b9cfce3ab71020c646ab9f48d9d29d6dBrian Carlstrom  if (value == ((b0 << 24) | (b0 << 8)))
1346f485c62b9cfce3ab71020c646ab9f48d9d29d6dBrian Carlstrom    return (0x2 << 8) | b0; /* 0:010:a:bcdefgh */
1356f485c62b9cfce3ab71020c646ab9f48d9d29d6dBrian Carlstrom  /* Can we do it with rotation? */
1366f485c62b9cfce3ab71020c646ab9f48d9d29d6dBrian Carlstrom  z_leading = LeadingZeros(value);
1376f485c62b9cfce3ab71020c646ab9f48d9d29d6dBrian Carlstrom  z_trailing = 32 - LeadingZeros(~value & (value - 1));
1386f485c62b9cfce3ab71020c646ab9f48d9d29d6dBrian Carlstrom  /* A run of eight or fewer active bits? */
1396f485c62b9cfce3ab71020c646ab9f48d9d29d6dBrian Carlstrom  if ((z_leading + z_trailing) < 24)
1406f485c62b9cfce3ab71020c646ab9f48d9d29d6dBrian Carlstrom    return -1;  /* No - bail */
1416f485c62b9cfce3ab71020c646ab9f48d9d29d6dBrian Carlstrom  /* left-justify the constant, discarding msb (known to be 1) */
1426f485c62b9cfce3ab71020c646ab9f48d9d29d6dBrian Carlstrom  value <<= z_leading + 1;
1436f485c62b9cfce3ab71020c646ab9f48d9d29d6dBrian Carlstrom  /* Create bcdefgh */
1446f485c62b9cfce3ab71020c646ab9f48d9d29d6dBrian Carlstrom  value >>= 25;
1456f485c62b9cfce3ab71020c646ab9f48d9d29d6dBrian Carlstrom  /* Put it all together */
1466f485c62b9cfce3ab71020c646ab9f48d9d29d6dBrian Carlstrom  return value | ((0x8 + z_leading) << 7); /* [01000..11111]:bcdefgh */
14767bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
14867bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
1492ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrombool ArmMir2Lir::InexpensiveConstantInt(int32_t value) {
1504ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  return (ModifiedImmediate(value) >= 0) || (ModifiedImmediate(~value) >= 0);
1514ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee}
1524ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
1532ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrombool ArmMir2Lir::InexpensiveConstantFloat(int32_t value) {
1544ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  return EncodeImmSingle(value) >= 0;
1554ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee}
1564ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
1572ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrombool ArmMir2Lir::InexpensiveConstantLong(int64_t value) {
1584ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  return InexpensiveConstantInt(High32Bits(value)) && InexpensiveConstantInt(Low32Bits(value));
1594ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee}
1604ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
1612ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrombool ArmMir2Lir::InexpensiveConstantDouble(int64_t value) {
1624ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  return EncodeImmDouble(value) >= 0;
163e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee}
164e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee
16567bf885d62b1473c833bece1c9e0bb624e6ba391buzbee/*
16667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * Load a immediate using a shortcut if possible; otherwise
16767bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * grab from the per-translation literal pool.
16867bf885d62b1473c833bece1c9e0bb624e6ba391buzbee *
16967bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * No additional register clobbering operation performed. Use this version when
170fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee * 1) r_dest is freshly returned from AllocTemp or
17167bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * 2) The codegen is under fixed register usage
17267bf885d62b1473c833bece1c9e0bb624e6ba391buzbee */
1732ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromLIR* ArmMir2Lir::LoadConstantNoClobber(int r_dest, int value) {
174a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  LIR* res;
175fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  int mod_imm;
17667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
177fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (ARM_FPREG(r_dest)) {
1781fd3346740dfb7f47be9922312b68a4227fada96buzbee    return LoadFPConstantValue(r_dest, value);
179a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
18067bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
181a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /* See if the value can be constructed cheaply */
182fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (ARM_LOWREG(r_dest) && (value >= 0) && (value <= 255)) {
1831fd3346740dfb7f47be9922312b68a4227fada96buzbee    return NewLIR2(kThumbMovImm, r_dest, value);
184a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
185a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /* Check Modified immediate special cases */
186fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  mod_imm = ModifiedImmediate(value);
187fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (mod_imm >= 0) {
1881fd3346740dfb7f47be9922312b68a4227fada96buzbee    res = NewLIR2(kThumb2MovImmShift, r_dest, mod_imm);
18967bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    return res;
190a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
191fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  mod_imm = ModifiedImmediate(~value);
192fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (mod_imm >= 0) {
1931fd3346740dfb7f47be9922312b68a4227fada96buzbee    res = NewLIR2(kThumb2MvnImm12, r_dest, mod_imm);
194a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    return res;
195a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
196a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /* 16-bit immediate? */
197a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  if ((value & 0xffff) == value) {
1981fd3346740dfb7f47be9922312b68a4227fada96buzbee    res = NewLIR2(kThumb2MovImm16, r_dest, value);
199a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    return res;
200a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
2014ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  /* Do a low/high pair */
2021fd3346740dfb7f47be9922312b68a4227fada96buzbee  res = NewLIR2(kThumb2MovImm16, r_dest, Low16Bits(value));
2031fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR2(kThumb2MovImm16H, r_dest, High16Bits(value));
204a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return res;
20567bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
20667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
2072ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromLIR* ArmMir2Lir::OpUnconditionalBranch(LIR* target) {
2081fd3346740dfb7f47be9922312b68a4227fada96buzbee  LIR* res = NewLIR1(kThumbBUncond, 0 /* offset to be patched  during assembly*/);
20902031b185b4653e6c72e21f7a51238b903f6d638buzbee  res->target = target;
21002031b185b4653e6c72e21f7a51238b903f6d638buzbee  return res;
21167bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
21267bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
2132ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromLIR* ArmMir2Lir::OpCondBranch(ConditionCode cc, LIR* target) {
2141fd3346740dfb7f47be9922312b68a4227fada96buzbee  LIR* branch = NewLIR2(kThumb2BCond, 0 /* offset to be patched */,
21552a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee                        ArmConditionEncoding(cc));
216a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  branch->target = target;
217a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return branch;
21867bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
21967bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
2202ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromLIR* ArmMir2Lir::OpReg(OpKind op, int r_dest_src) {
221a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  ArmOpcode opcode = kThumbBkpt;
222a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  switch (op) {
223a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpBlx:
224a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      opcode = kThumbBlxR;
225a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
226c0f96d03a1855fda7d94332331b94860404874ddBrian Carlstrom    case kOpBx:
227c0f96d03a1855fda7d94332331b94860404874ddBrian Carlstrom      opcode = kThumbBx;
228c0f96d03a1855fda7d94332331b94860404874ddBrian Carlstrom      break;
229a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    default:
230cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      LOG(FATAL) << "Bad opcode " << op;
231a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
2321fd3346740dfb7f47be9922312b68a4227fada96buzbee  return NewLIR1(opcode, r_dest_src);
23367bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
23467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
2351fd3346740dfb7f47be9922312b68a4227fada96buzbeeLIR* ArmMir2Lir::OpRegRegShift(OpKind op, int r_dest_src1, int r_src2,
2362ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                               int shift) {
237fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  bool thumb_form = ((shift == 0) && ARM_LOWREG(r_dest_src1) && ARM_LOWREG(r_src2));
238a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  ArmOpcode opcode = kThumbBkpt;
239a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  switch (op) {
240a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpAdc:
241fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = (thumb_form) ? kThumbAdcRR : kThumb2AdcRRR;
242a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
243a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpAnd:
244fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = (thumb_form) ? kThumbAndRR : kThumb2AndRRR;
245a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
246a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpBic:
247fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = (thumb_form) ? kThumbBicRR : kThumb2BicRRR;
248a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
249a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpCmn:
250a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      DCHECK_EQ(shift, 0);
251fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = (thumb_form) ? kThumbCmnRR : kThumb2CmnRR;
252a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
253a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpCmp:
254fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (thumb_form)
255a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        opcode = kThumbCmpRR;
256fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      else if ((shift == 0) && !ARM_LOWREG(r_dest_src1) && !ARM_LOWREG(r_src2))
257a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        opcode = kThumbCmpHH;
258fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      else if ((shift == 0) && ARM_LOWREG(r_dest_src1))
259a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        opcode = kThumbCmpLH;
260a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      else if (shift == 0)
261a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        opcode = kThumbCmpHL;
262a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      else
263a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        opcode = kThumb2CmpRR;
264a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
265a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpXor:
266fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = (thumb_form) ? kThumbEorRR : kThumb2EorRRR;
267a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
268a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpMov:
269a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      DCHECK_EQ(shift, 0);
270fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (ARM_LOWREG(r_dest_src1) && ARM_LOWREG(r_src2))
271a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        opcode = kThumbMovRR;
272fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      else if (!ARM_LOWREG(r_dest_src1) && !ARM_LOWREG(r_src2))
273a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        opcode = kThumbMovRR_H2H;
274fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      else if (ARM_LOWREG(r_dest_src1))
275a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        opcode = kThumbMovRR_H2L;
276a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      else
277a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        opcode = kThumbMovRR_L2H;
278a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
279a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpMul:
280a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      DCHECK_EQ(shift, 0);
281fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = (thumb_form) ? kThumbMul : kThumb2MulRRR;
282a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
283a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpMvn:
284fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = (thumb_form) ? kThumbMvn : kThumb2MnvRR;
285a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
286a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpNeg:
287a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      DCHECK_EQ(shift, 0);
288fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = (thumb_form) ? kThumbNeg : kThumb2NegRR;
289a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
290a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpOr:
291fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = (thumb_form) ? kThumbOrr : kThumb2OrrRRR;
292a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
293a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpSbc:
294fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = (thumb_form) ? kThumbSbc : kThumb2SbcRRR;
295a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
296a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpTst:
297fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = (thumb_form) ? kThumbTst : kThumb2TstRR;
298a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
299a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpLsl:
300a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      DCHECK_EQ(shift, 0);
301fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = (thumb_form) ? kThumbLslRR : kThumb2LslRRR;
302a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
303a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpLsr:
304a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      DCHECK_EQ(shift, 0);
305fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = (thumb_form) ? kThumbLsrRR : kThumb2LsrRRR;
306a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
307a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpAsr:
308a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      DCHECK_EQ(shift, 0);
309fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = (thumb_form) ? kThumbAsrRR : kThumb2AsrRRR;
310a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
311a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpRor:
312a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      DCHECK_EQ(shift, 0);
313fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = (thumb_form) ? kThumbRorRR : kThumb2RorRRR;
314a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
315a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpAdd:
316fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = (thumb_form) ? kThumbAddRRR : kThumb2AddRRR;
317a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
318a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpSub:
319fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = (thumb_form) ? kThumbSubRRR : kThumb2SubRRR;
320a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
321a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOp2Byte:
322a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      DCHECK_EQ(shift, 0);
3231fd3346740dfb7f47be9922312b68a4227fada96buzbee      return NewLIR4(kThumb2Sbfx, r_dest_src1, r_src2, 0, 8);
324a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOp2Short:
325a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      DCHECK_EQ(shift, 0);
3261fd3346740dfb7f47be9922312b68a4227fada96buzbee      return NewLIR4(kThumb2Sbfx, r_dest_src1, r_src2, 0, 16);
327a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOp2Char:
328a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      DCHECK_EQ(shift, 0);
3291fd3346740dfb7f47be9922312b68a4227fada96buzbee      return NewLIR4(kThumb2Ubfx, r_dest_src1, r_src2, 0, 16);
330a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    default:
331cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      LOG(FATAL) << "Bad opcode: " << op;
332a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
333a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
334a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  DCHECK_GE(static_cast<int>(opcode), 0);
3359b7085a4e7c40e7fa01932ea1647a4a33ac1c585Brian Carlstrom  if (EncodingMap[opcode].flags & IS_BINARY_OP) {
3361fd3346740dfb7f47be9922312b68a4227fada96buzbee    return NewLIR2(opcode, r_dest_src1, r_src2);
3379b7085a4e7c40e7fa01932ea1647a4a33ac1c585Brian Carlstrom  } else if (EncodingMap[opcode].flags & IS_TERTIARY_OP) {
3389b7085a4e7c40e7fa01932ea1647a4a33ac1c585Brian Carlstrom    if (EncodingMap[opcode].field_loc[2].kind == kFmtShift) {
3391fd3346740dfb7f47be9922312b68a4227fada96buzbee      return NewLIR3(opcode, r_dest_src1, r_src2, shift);
3409b7085a4e7c40e7fa01932ea1647a4a33ac1c585Brian Carlstrom    } else {
3411fd3346740dfb7f47be9922312b68a4227fada96buzbee      return NewLIR3(opcode, r_dest_src1, r_dest_src1, r_src2);
3429b7085a4e7c40e7fa01932ea1647a4a33ac1c585Brian Carlstrom    }
3439b7085a4e7c40e7fa01932ea1647a4a33ac1c585Brian Carlstrom  } else if (EncodingMap[opcode].flags & IS_QUAD_OP) {
3441fd3346740dfb7f47be9922312b68a4227fada96buzbee    return NewLIR4(opcode, r_dest_src1, r_dest_src1, r_src2, shift);
3459b7085a4e7c40e7fa01932ea1647a4a33ac1c585Brian Carlstrom  } else {
346a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    LOG(FATAL) << "Unexpected encoding operand count";
347a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    return NULL;
348a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
34967bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
35067bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
3512ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromLIR* ArmMir2Lir::OpRegReg(OpKind op, int r_dest_src1, int r_src2) {
3521fd3346740dfb7f47be9922312b68a4227fada96buzbee  return OpRegRegShift(op, r_dest_src1, r_src2, 0);
35367bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
35467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
3551fd3346740dfb7f47be9922312b68a4227fada96buzbeeLIR* ArmMir2Lir::OpRegRegRegShift(OpKind op, int r_dest, int r_src1,
3562ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                                  int r_src2, int shift) {
357a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  ArmOpcode opcode = kThumbBkpt;
358fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  bool thumb_form = (shift == 0) && ARM_LOWREG(r_dest) && ARM_LOWREG(r_src1) &&
359fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      ARM_LOWREG(r_src2);
360a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  switch (op) {
361a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpAdd:
362fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = (thumb_form) ? kThumbAddRRR : kThumb2AddRRR;
363a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
364a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpSub:
365fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = (thumb_form) ? kThumbSubRRR : kThumb2SubRRR;
366a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
367a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpRsub:
368a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      opcode = kThumb2RsubRRR;
369a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
370a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpAdc:
371a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      opcode = kThumb2AdcRRR;
372a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
373a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpAnd:
374a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      opcode = kThumb2AndRRR;
375a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
376a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpBic:
377a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      opcode = kThumb2BicRRR;
378a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
379a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpXor:
380a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      opcode = kThumb2EorRRR;
381a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
382a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpMul:
383a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      DCHECK_EQ(shift, 0);
384a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      opcode = kThumb2MulRRR;
385a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
386a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpOr:
387a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      opcode = kThumb2OrrRRR;
388a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
389a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpSbc:
390a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      opcode = kThumb2SbcRRR;
391a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
392a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpLsl:
393a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      DCHECK_EQ(shift, 0);
394a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      opcode = kThumb2LslRRR;
395a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
396a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpLsr:
397a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      DCHECK_EQ(shift, 0);
398a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      opcode = kThumb2LsrRRR;
399a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
400a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpAsr:
401a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      DCHECK_EQ(shift, 0);
402a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      opcode = kThumb2AsrRRR;
403a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
404a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpRor:
405a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      DCHECK_EQ(shift, 0);
406a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      opcode = kThumb2RorRRR;
407a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
408a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    default:
409cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      LOG(FATAL) << "Bad opcode: " << op;
410a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
411a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
412a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  DCHECK_GE(static_cast<int>(opcode), 0);
4139b7085a4e7c40e7fa01932ea1647a4a33ac1c585Brian Carlstrom  if (EncodingMap[opcode].flags & IS_QUAD_OP) {
4141fd3346740dfb7f47be9922312b68a4227fada96buzbee    return NewLIR4(opcode, r_dest, r_src1, r_src2, shift);
4159b7085a4e7c40e7fa01932ea1647a4a33ac1c585Brian Carlstrom  } else {
416a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    DCHECK(EncodingMap[opcode].flags & IS_TERTIARY_OP);
4171fd3346740dfb7f47be9922312b68a4227fada96buzbee    return NewLIR3(opcode, r_dest, r_src1, r_src2);
418a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
41967bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
42067bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
4212ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromLIR* ArmMir2Lir::OpRegRegReg(OpKind op, int r_dest, int r_src1, int r_src2) {
4221fd3346740dfb7f47be9922312b68a4227fada96buzbee  return OpRegRegRegShift(op, r_dest, r_src1, r_src2, 0);
42367bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
42467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
4252ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromLIR* ArmMir2Lir::OpRegRegImm(OpKind op, int r_dest, int r_src1, int value) {
426a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  LIR* res;
427a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  bool neg = (value < 0);
428fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  int abs_value = (neg) ? -value : value;
429a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  ArmOpcode opcode = kThumbBkpt;
430fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  ArmOpcode alt_opcode = kThumbBkpt;
431fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  bool all_low_regs = (ARM_LOWREG(r_dest) && ARM_LOWREG(r_src1));
432fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  int mod_imm = ModifiedImmediate(value);
433fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  int mod_imm_neg = ModifiedImmediate(-value);
43467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
435a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  switch (op) {
436a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpLsl:
437fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (all_low_regs)
4381fd3346740dfb7f47be9922312b68a4227fada96buzbee        return NewLIR3(kThumbLslRRI5, r_dest, r_src1, value);
439a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      else
4401fd3346740dfb7f47be9922312b68a4227fada96buzbee        return NewLIR3(kThumb2LslRRI5, r_dest, r_src1, value);
441a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpLsr:
442fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (all_low_regs)
4431fd3346740dfb7f47be9922312b68a4227fada96buzbee        return NewLIR3(kThumbLsrRRI5, r_dest, r_src1, value);
444a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      else
4451fd3346740dfb7f47be9922312b68a4227fada96buzbee        return NewLIR3(kThumb2LsrRRI5, r_dest, r_src1, value);
446a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpAsr:
447fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (all_low_regs)
4481fd3346740dfb7f47be9922312b68a4227fada96buzbee        return NewLIR3(kThumbAsrRRI5, r_dest, r_src1, value);
449a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      else
4501fd3346740dfb7f47be9922312b68a4227fada96buzbee        return NewLIR3(kThumb2AsrRRI5, r_dest, r_src1, value);
451a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpRor:
4521fd3346740dfb7f47be9922312b68a4227fada96buzbee      return NewLIR3(kThumb2RorRRI5, r_dest, r_src1, value);
453a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpAdd:
454fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (ARM_LOWREG(r_dest) && (r_src1 == r13sp) &&
45538f85e4892f6504971bde994fec81fd61780ac30Brian Carlstrom        (value <= 1020) && ((value & 0x3) == 0)) {
4561fd3346740dfb7f47be9922312b68a4227fada96buzbee        return NewLIR3(kThumbAddSpRel, r_dest, r_src1, value >> 2);
457fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      } else if (ARM_LOWREG(r_dest) && (r_src1 == r15pc) &&
45838f85e4892f6504971bde994fec81fd61780ac30Brian Carlstrom          (value <= 1020) && ((value & 0x3) == 0)) {
4591fd3346740dfb7f47be9922312b68a4227fada96buzbee        return NewLIR3(kThumbAddPcRel, r_dest, r_src1, value >> 2);
460a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
461a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      // Note: intentional fallthrough
462a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpSub:
463fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (all_low_regs && ((abs_value & 0x7) == abs_value)) {
464a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        if (op == kOpAdd)
465a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee          opcode = (neg) ? kThumbSubRRI3 : kThumbAddRRI3;
46667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee        else
467a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee          opcode = (neg) ? kThumbAddRRI3 : kThumbSubRRI3;
4681fd3346740dfb7f47be9922312b68a4227fada96buzbee        return NewLIR3(opcode, r_dest, r_src1, abs_value);
469fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      } else if ((abs_value & 0xff) == abs_value) {
470a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        if (op == kOpAdd)
471a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee          opcode = (neg) ? kThumb2SubRRI12 : kThumb2AddRRI12;
472a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        else
473a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee          opcode = (neg) ? kThumb2AddRRI12 : kThumb2SubRRI12;
4741fd3346740dfb7f47be9922312b68a4227fada96buzbee        return NewLIR3(opcode, r_dest, r_src1, abs_value);
475a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
476fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (mod_imm_neg >= 0) {
477a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        op = (op == kOpAdd) ? kOpSub : kOpAdd;
478fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        mod_imm = mod_imm_neg;
479a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
480a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      if (op == kOpSub) {
481a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        opcode = kThumb2SubRRI8;
482fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        alt_opcode = kThumb2SubRRR;
483a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      } else {
484a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        opcode = kThumb2AddRRI8;
485fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        alt_opcode = kThumb2AddRRR;
486a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
487a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
488c7d1f91e024c5c560810376340aecb39d4e47fdcbuzbee    case kOpRsub:
489c7d1f91e024c5c560810376340aecb39d4e47fdcbuzbee      opcode = kThumb2RsubRRI8;
490c7d1f91e024c5c560810376340aecb39d4e47fdcbuzbee      alt_opcode = kThumb2RsubRRR;
491c7d1f91e024c5c560810376340aecb39d4e47fdcbuzbee      break;
492a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpAdc:
493a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      opcode = kThumb2AdcRRI8;
494fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      alt_opcode = kThumb2AdcRRR;
495a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
496a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpSbc:
497a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      opcode = kThumb2SbcRRI8;
498fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      alt_opcode = kThumb2SbcRRR;
499a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
500a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpOr:
501a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      opcode = kThumb2OrrRRI8;
502fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      alt_opcode = kThumb2OrrRRR;
503a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
504a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpAnd:
505a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      opcode = kThumb2AndRRI8;
506fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      alt_opcode = kThumb2AndRRR;
507a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
508a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpXor:
509a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      opcode = kThumb2EorRRI8;
510fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      alt_opcode = kThumb2EorRRR;
511a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
512a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpMul:
5137934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom      // TUNING: power of 2, shift & add
514fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      mod_imm = -1;
515fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      alt_opcode = kThumb2MulRRR;
516a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
517a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpCmp: {
518fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      int mod_imm = ModifiedImmediate(value);
519a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      LIR* res;
520fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (mod_imm >= 0) {
5211fd3346740dfb7f47be9922312b68a4227fada96buzbee        res = NewLIR2(kThumb2CmpRI12, r_src1, mod_imm);
522a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      } else {
5231fd3346740dfb7f47be9922312b68a4227fada96buzbee        int r_tmp = AllocTemp();
5241fd3346740dfb7f47be9922312b68a4227fada96buzbee        res = LoadConstant(r_tmp, value);
5251fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegReg(kOpCmp, r_src1, r_tmp);
5261fd3346740dfb7f47be9922312b68a4227fada96buzbee        FreeTemp(r_tmp);
527a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
528a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      return res;
52967bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    }
530a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    default:
531cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      LOG(FATAL) << "Bad opcode: " << op;
532a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
533a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee
534fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (mod_imm >= 0) {
5351fd3346740dfb7f47be9922312b68a4227fada96buzbee    return NewLIR3(opcode, r_dest, r_src1, mod_imm);
536a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  } else {
5371fd3346740dfb7f47be9922312b68a4227fada96buzbee    int r_scratch = AllocTemp();
5381fd3346740dfb7f47be9922312b68a4227fada96buzbee    LoadConstant(r_scratch, value);
539fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (EncodingMap[alt_opcode].flags & IS_QUAD_OP)
5401fd3346740dfb7f47be9922312b68a4227fada96buzbee      res = NewLIR4(alt_opcode, r_dest, r_src1, r_scratch, 0);
541a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    else
5421fd3346740dfb7f47be9922312b68a4227fada96buzbee      res = NewLIR3(alt_opcode, r_dest, r_src1, r_scratch);
5431fd3346740dfb7f47be9922312b68a4227fada96buzbee    FreeTemp(r_scratch);
544a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    return res;
545a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
54667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
54767bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
54852a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee/* Handle Thumb-only variants here - otherwise punt to OpRegRegImm */
5492ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromLIR* ArmMir2Lir::OpRegImm(OpKind op, int r_dest_src1, int value) {
550a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  bool neg = (value < 0);
551fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  int abs_value = (neg) ? -value : value;
552fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  bool short_form = (((abs_value & 0xff) == abs_value) && ARM_LOWREG(r_dest_src1));
553a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  ArmOpcode opcode = kThumbBkpt;
554a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  switch (op) {
555a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpAdd:
556df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom      if (!neg && (r_dest_src1 == r13sp) && (value <= 508)) { /* sp */
557a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        DCHECK_EQ((value & 0x3), 0);
5581fd3346740dfb7f47be9922312b68a4227fada96buzbee        return NewLIR1(kThumbAddSpI7, value >> 2);
559fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      } else if (short_form) {
560a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        opcode = (neg) ? kThumbSubRI8 : kThumbAddRI8;
561a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
562a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
563a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpSub:
564fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (!neg && (r_dest_src1 == r13sp) && (value <= 508)) { /* sp */
565a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        DCHECK_EQ((value & 0x3), 0);
5661fd3346740dfb7f47be9922312b68a4227fada96buzbee        return NewLIR1(kThumbSubSpI7, value >> 2);
567fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      } else if (short_form) {
568a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        opcode = (neg) ? kThumbAddRI8 : kThumbSubRI8;
569a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
570a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
571a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kOpCmp:
5729b7085a4e7c40e7fa01932ea1647a4a33ac1c585Brian Carlstrom      if (ARM_LOWREG(r_dest_src1) && short_form) {
573fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        opcode = (short_form) ?  kThumbCmpRI8 : kThumbCmpRR;
5749b7085a4e7c40e7fa01932ea1647a4a33ac1c585Brian Carlstrom      } else if (ARM_LOWREG(r_dest_src1)) {
575a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        opcode = kThumbCmpRR;
5769b7085a4e7c40e7fa01932ea1647a4a33ac1c585Brian Carlstrom      } else {
577fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        short_form = false;
578a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        opcode = kThumbCmpHL;
579a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
580a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
581a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    default:
58252a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee      /* Punt to OpRegRegImm - if bad case catch it there */
583fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      short_form = false;
584a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
585a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
5869b7085a4e7c40e7fa01932ea1647a4a33ac1c585Brian Carlstrom  if (short_form) {
5871fd3346740dfb7f47be9922312b68a4227fada96buzbee    return NewLIR2(opcode, r_dest_src1, abs_value);
5889b7085a4e7c40e7fa01932ea1647a4a33ac1c585Brian Carlstrom  } else {
5891fd3346740dfb7f47be9922312b68a4227fada96buzbee    return OpRegRegImm(op, r_dest_src1, r_dest_src1, value);
590a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
59167bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
59267bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
5932ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromLIR* ArmMir2Lir::LoadConstantWide(int r_dest_lo, int r_dest_hi, int64_t value) {
5944ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  LIR* res = NULL;
5954ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  int32_t val_lo = Low32Bits(value);
5964ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  int32_t val_hi = High32Bits(value);
5977da142fc1cefeeb24d997ae21b34381fdd2c0466buzbee  int target_reg = S2d(r_dest_lo, r_dest_hi);
598fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (ARM_FPREG(r_dest_lo)) {
5997da142fc1cefeeb24d997ae21b34381fdd2c0466buzbee    if ((val_lo == 0) && (val_hi == 0)) {
6007da142fc1cefeeb24d997ae21b34381fdd2c0466buzbee      // TODO: we need better info about the target CPU.  a vector exclusive or
6017da142fc1cefeeb24d997ae21b34381fdd2c0466buzbee      //       would probably be better here if we could rely on its existance.
6027da142fc1cefeeb24d997ae21b34381fdd2c0466buzbee      // Load an immediate +2.0 (which encodes to 0)
6031fd3346740dfb7f47be9922312b68a4227fada96buzbee      NewLIR2(kThumb2Vmovd_IMM8, target_reg, 0);
6047da142fc1cefeeb24d997ae21b34381fdd2c0466buzbee      // +0.0 = +2.0 - +2.0
6051fd3346740dfb7f47be9922312b68a4227fada96buzbee      res = NewLIR3(kThumb2Vsubd, target_reg, target_reg, target_reg);
60667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    } else {
6074ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      int encoded_imm = EncodeImmDouble(value);
6087da142fc1cefeeb24d997ae21b34381fdd2c0466buzbee      if (encoded_imm >= 0) {
6091fd3346740dfb7f47be9922312b68a4227fada96buzbee        res = NewLIR2(kThumb2Vmovd_IMM8, target_reg, encoded_imm);
610a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
61167bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    }
612a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  } else {
6134ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    if ((InexpensiveConstantInt(val_lo) && (InexpensiveConstantInt(val_hi)))) {
6141fd3346740dfb7f47be9922312b68a4227fada96buzbee      res = LoadConstantNoClobber(r_dest_lo, val_lo);
6151fd3346740dfb7f47be9922312b68a4227fada96buzbee      LoadConstantNoClobber(r_dest_hi, val_hi);
6164ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    }
6174ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  }
6184ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  if (res == NULL) {
6194ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    // No short form - load from the literal pool.
6201fd3346740dfb7f47be9922312b68a4227fada96buzbee    LIR* data_target = ScanLiteralPoolWide(literal_list_, val_lo, val_hi);
6214ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    if (data_target == NULL) {
6221fd3346740dfb7f47be9922312b68a4227fada96buzbee      data_target = AddWideData(&literal_list_, val_lo, val_hi);
6234ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    }
6244ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    if (ARM_FPREG(r_dest_lo)) {
6251fd3346740dfb7f47be9922312b68a4227fada96buzbee      res = RawLIR(current_dalvik_offset_, kThumb2Vldrd,
6264ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee                   target_reg, r15pc, 0, 0, 0, data_target);
6274ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    } else {
6281fd3346740dfb7f47be9922312b68a4227fada96buzbee      res = RawLIR(current_dalvik_offset_, kThumb2LdrdPcRel8,
6294ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee                   r_dest_lo, r_dest_hi, r15pc, 0, 0, data_target);
6304ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    }
6311fd3346740dfb7f47be9922312b68a4227fada96buzbee    SetMemRefType(res, true, kLiteral);
6324ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    res->alias_info = reinterpret_cast<uintptr_t>(data_target);
6331fd3346740dfb7f47be9922312b68a4227fada96buzbee    AppendLIR(res);
634a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
635a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return res;
63667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
63767bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
6381fd3346740dfb7f47be9922312b68a4227fada96buzbeeint ArmMir2Lir::EncodeShift(int code, int amount) {
639a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return ((amount & 0x1f) << 2) | code;
64067bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
64167bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
6421fd3346740dfb7f47be9922312b68a4227fada96buzbeeLIR* ArmMir2Lir::LoadBaseIndexed(int rBase, int r_index, int r_dest,
6432ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                                 int scale, OpSize size) {
644fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  bool all_low_regs = ARM_LOWREG(rBase) && ARM_LOWREG(r_index) && ARM_LOWREG(r_dest);
645a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  LIR* load;
646a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  ArmOpcode opcode = kThumbBkpt;
647fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  bool thumb_form = (all_low_regs && (scale == 0));
648fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  int reg_ptr;
64967bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
650fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (ARM_FPREG(r_dest)) {
651fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (ARM_SINGLEREG(r_dest)) {
652a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      DCHECK((size == kWord) || (size == kSingle));
653a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      opcode = kThumb2Vldrs;
654a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      size = kSingle;
65567bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    } else {
656fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      DCHECK(ARM_DOUBLEREG(r_dest));
657a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      DCHECK((size == kLong) || (size == kDouble));
658fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      DCHECK_EQ((r_dest & 0x1), 0);
659a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      opcode = kThumb2Vldrd;
660a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      size = kDouble;
66167bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    }
662a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  } else {
663a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    if (size == kSingle)
664a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      size = kWord;
665a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
66667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
667a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  switch (size) {
6687934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom    case kDouble:  // fall-through
669a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kSingle:
6701fd3346740dfb7f47be9922312b68a4227fada96buzbee      reg_ptr = AllocTemp();
671a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      if (scale) {
6721fd3346740dfb7f47be9922312b68a4227fada96buzbee        NewLIR4(kThumb2AddRRR, reg_ptr, rBase, r_index,
67352a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee                EncodeShift(kArmLsl, scale));
674a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      } else {
6751fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegReg(kOpAdd, reg_ptr, rBase, r_index);
676a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
6771fd3346740dfb7f47be9922312b68a4227fada96buzbee      load = NewLIR3(opcode, r_dest, reg_ptr, 0);
6781fd3346740dfb7f47be9922312b68a4227fada96buzbee      FreeTemp(reg_ptr);
679a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      return load;
680a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kWord:
681fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = (thumb_form) ? kThumbLdrRRR : kThumb2LdrRRR;
682a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
683a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kUnsignedHalf:
684fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = (thumb_form) ? kThumbLdrhRRR : kThumb2LdrhRRR;
685a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
686a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kSignedHalf:
687fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = (thumb_form) ? kThumbLdrshRRR : kThumb2LdrshRRR;
688a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
689a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kUnsignedByte:
690fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = (thumb_form) ? kThumbLdrbRRR : kThumb2LdrbRRR;
691a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
692a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kSignedByte:
693fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = (thumb_form) ? kThumbLdrsbRRR : kThumb2LdrsbRRR;
694a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
695a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    default:
696cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      LOG(FATAL) << "Bad size: " << size;
697a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
698fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (thumb_form)
6991fd3346740dfb7f47be9922312b68a4227fada96buzbee    load = NewLIR3(opcode, r_dest, rBase, r_index);
700a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  else
7011fd3346740dfb7f47be9922312b68a4227fada96buzbee    load = NewLIR4(opcode, r_dest, rBase, r_index, scale);
70267bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
703a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return load;
70467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
70567bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
7061fd3346740dfb7f47be9922312b68a4227fada96buzbeeLIR* ArmMir2Lir::StoreBaseIndexed(int rBase, int r_index, int r_src,
7072ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                                  int scale, OpSize size) {
708fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  bool all_low_regs = ARM_LOWREG(rBase) && ARM_LOWREG(r_index) && ARM_LOWREG(r_src);
7094ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  LIR* store = NULL;
710a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  ArmOpcode opcode = kThumbBkpt;
711fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  bool thumb_form = (all_low_regs && (scale == 0));
712fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  int reg_ptr;
71367bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
714fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (ARM_FPREG(r_src)) {
715fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (ARM_SINGLEREG(r_src)) {
716a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      DCHECK((size == kWord) || (size == kSingle));
717a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      opcode = kThumb2Vstrs;
718a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      size = kSingle;
71967bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    } else {
720fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      DCHECK(ARM_DOUBLEREG(r_src));
721a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      DCHECK((size == kLong) || (size == kDouble));
722fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      DCHECK_EQ((r_src & 0x1), 0);
723a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      opcode = kThumb2Vstrd;
724a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      size = kDouble;
72567bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    }
726a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  } else {
727a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    if (size == kSingle)
728a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      size = kWord;
729a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
73067bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
731a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  switch (size) {
7327934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom    case kDouble:  // fall-through
733a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kSingle:
7341fd3346740dfb7f47be9922312b68a4227fada96buzbee      reg_ptr = AllocTemp();
735a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      if (scale) {
7361fd3346740dfb7f47be9922312b68a4227fada96buzbee        NewLIR4(kThumb2AddRRR, reg_ptr, rBase, r_index,
73752a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee                EncodeShift(kArmLsl, scale));
738a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      } else {
7391fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegReg(kOpAdd, reg_ptr, rBase, r_index);
740a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
7411fd3346740dfb7f47be9922312b68a4227fada96buzbee      store = NewLIR3(opcode, r_src, reg_ptr, 0);
7421fd3346740dfb7f47be9922312b68a4227fada96buzbee      FreeTemp(reg_ptr);
743a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      return store;
744a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kWord:
745fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = (thumb_form) ? kThumbStrRRR : kThumb2StrRRR;
746a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
747a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kUnsignedHalf:
748a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kSignedHalf:
749fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = (thumb_form) ? kThumbStrhRRR : kThumb2StrhRRR;
750a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
751a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kUnsignedByte:
752a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kSignedByte:
753fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = (thumb_form) ? kThumbStrbRRR : kThumb2StrbRRR;
754a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
755a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    default:
756cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      LOG(FATAL) << "Bad size: " << size;
757a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
758fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (thumb_form)
7591fd3346740dfb7f47be9922312b68a4227fada96buzbee    store = NewLIR3(opcode, r_src, rBase, r_index);
760a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  else
7611fd3346740dfb7f47be9922312b68a4227fada96buzbee    store = NewLIR4(opcode, r_src, rBase, r_index, scale);
76267bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
763a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return store;
76467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
76567bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
76667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee/*
76767bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * Load value from base + displacement.  Optionally perform null check
768fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee * on base (which must have an associated s_reg and MIR).  If not
76967bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * performing null check, incoming MIR can be null.
77067bf885d62b1473c833bece1c9e0bb624e6ba391buzbee */
7711fd3346740dfb7f47be9922312b68a4227fada96buzbeeLIR* ArmMir2Lir::LoadBaseDispBody(int rBase, int displacement, int r_dest,
7722ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                                  int r_dest_hi, OpSize size, int s_reg) {
7734ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  LIR* load = NULL;
774a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  ArmOpcode opcode = kThumbBkpt;
775fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  bool short_form = false;
776a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  bool thumb2Form = (displacement < 4092 && displacement >= 0);
777fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  bool all_low_regs = (ARM_LOWREG(rBase) && ARM_LOWREG(r_dest));
778fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  int encoded_disp = displacement;
779a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  bool is64bit = false;
7804ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  bool already_generated = false;
781a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  switch (size) {
782a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kDouble:
783a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kLong:
784a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      is64bit = true;
785fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (ARM_FPREG(r_dest)) {
786fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        if (ARM_SINGLEREG(r_dest)) {
787fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee          DCHECK(ARM_FPREG(r_dest_hi));
7881fd3346740dfb7f47be9922312b68a4227fada96buzbee          r_dest = S2d(r_dest, r_dest_hi);
789a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        }
790a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        opcode = kThumb2Vldrd;
791a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        if (displacement <= 1020) {
792fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee          short_form = true;
793fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee          encoded_disp >>= 2;
794a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        }
795a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        break;
796a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      } else {
7974ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee        if (displacement <= 1020) {
7981fd3346740dfb7f47be9922312b68a4227fada96buzbee          load = NewLIR4(kThumb2LdrdI8, r_dest, r_dest_hi, rBase, displacement >> 2);
7994ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee        } else {
8001fd3346740dfb7f47be9922312b68a4227fada96buzbee          load = LoadBaseDispBody(rBase, displacement, r_dest,
8014ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee                                 -1, kWord, s_reg);
8021fd3346740dfb7f47be9922312b68a4227fada96buzbee          LoadBaseDispBody(rBase, displacement + 4, r_dest_hi,
8034ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee                           -1, kWord, INVALID_SREG);
8044ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee        }
8054ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee        already_generated = true;
806a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
807a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kSingle:
808a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kWord:
809fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (ARM_FPREG(r_dest)) {
810a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        opcode = kThumb2Vldrs;
811a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        if (displacement <= 1020) {
812fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee          short_form = true;
813fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee          encoded_disp >>= 2;
814a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        }
815a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        break;
816a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
817fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (ARM_LOWREG(r_dest) && (rBase == r15pc) &&
818a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee          (displacement <= 1020) && (displacement >= 0)) {
819fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        short_form = true;
820fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        encoded_disp >>= 2;
821a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        opcode = kThumbLdrPcRel;
822fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      } else if (ARM_LOWREG(r_dest) && (rBase == r13sp) &&
823a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee          (displacement <= 1020) && (displacement >= 0)) {
824fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        short_form = true;
825fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        encoded_disp >>= 2;
826a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        opcode = kThumbLdrSpRel;
827fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      } else if (all_low_regs && displacement < 128 && displacement >= 0) {
828a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        DCHECK_EQ((displacement & 0x3), 0);
829fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        short_form = true;
830fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        encoded_disp >>= 2;
831a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        opcode = kThumbLdrRRI5;
832a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      } else if (thumb2Form) {
833fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        short_form = true;
834a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        opcode = kThumb2LdrRRI12;
835a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
836a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
837a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kUnsignedHalf:
838fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (all_low_regs && displacement < 64 && displacement >= 0) {
839a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        DCHECK_EQ((displacement & 0x1), 0);
840fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        short_form = true;
841fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        encoded_disp >>= 1;
842a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        opcode = kThumbLdrhRRI5;
843a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      } else if (displacement < 4092 && displacement >= 0) {
844fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        short_form = true;
845a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        opcode = kThumb2LdrhRRI12;
846a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
847a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
848a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kSignedHalf:
849a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      if (thumb2Form) {
850fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        short_form = true;
851a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        opcode = kThumb2LdrshRRI12;
852a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
853a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
854a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kUnsignedByte:
855fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (all_low_regs && displacement < 32 && displacement >= 0) {
856fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        short_form = true;
857a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        opcode = kThumbLdrbRRI5;
858a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      } else if (thumb2Form) {
859fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        short_form = true;
860a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        opcode = kThumb2LdrbRRI12;
861a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
862a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
863a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kSignedByte:
864a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      if (thumb2Form) {
865fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        short_form = true;
866a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        opcode = kThumb2LdrsbRRI12;
867a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
868a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
869a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    default:
870cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      LOG(FATAL) << "Bad size: " << size;
871a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
87267bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
8734ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  if (!already_generated) {
8744ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    if (short_form) {
8751fd3346740dfb7f47be9922312b68a4227fada96buzbee      load = NewLIR3(opcode, r_dest, rBase, encoded_disp);
8764ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    } else {
8771fd3346740dfb7f47be9922312b68a4227fada96buzbee      int reg_offset = AllocTemp();
8781fd3346740dfb7f47be9922312b68a4227fada96buzbee      LoadConstant(reg_offset, encoded_disp);
8791fd3346740dfb7f47be9922312b68a4227fada96buzbee      load = LoadBaseIndexed(rBase, reg_offset, r_dest, 0, size);
8801fd3346740dfb7f47be9922312b68a4227fada96buzbee      FreeTemp(reg_offset);
8814ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    }
882a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
88367bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
884a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  // TODO: in future may need to differentiate Dalvik accesses w/ spills
885f0504cdc5b6400edd4b39eea64ac280465042d5bbuzbee  if (rBase == rARM_SP) {
8861fd3346740dfb7f47be9922312b68a4227fada96buzbee    AnnotateDalvikRegAccess(load, displacement >> 2, true /* is_load */, is64bit);
887a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
888a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return load;
88967bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
89067bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
8911fd3346740dfb7f47be9922312b68a4227fada96buzbeeLIR* ArmMir2Lir::LoadBaseDisp(int rBase, int displacement, int r_dest,
8922ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                              OpSize size, int s_reg) {
8931fd3346740dfb7f47be9922312b68a4227fada96buzbee  return LoadBaseDispBody(rBase, displacement, r_dest, -1, size, s_reg);
89467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
89567bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
8961fd3346740dfb7f47be9922312b68a4227fada96buzbeeLIR* ArmMir2Lir::LoadBaseDispWide(int rBase, int displacement, int r_dest_lo,
8972ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                                  int r_dest_hi, int s_reg) {
8981fd3346740dfb7f47be9922312b68a4227fada96buzbee  return LoadBaseDispBody(rBase, displacement, r_dest_lo, r_dest_hi, kLong, s_reg);
89967bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
90067bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
90167bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
9021fd3346740dfb7f47be9922312b68a4227fada96buzbeeLIR* ArmMir2Lir::StoreBaseDispBody(int rBase, int displacement,
90302031b185b4653e6c72e21f7a51238b903f6d638buzbee                                   int r_src, int r_src_hi, OpSize size) {
9044ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  LIR* store = NULL;
905a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  ArmOpcode opcode = kThumbBkpt;
906fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  bool short_form = false;
907a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  bool thumb2Form = (displacement < 4092 && displacement >= 0);
908fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  bool all_low_regs = (ARM_LOWREG(rBase) && ARM_LOWREG(r_src));
909fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  int encoded_disp = displacement;
910a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  bool is64bit = false;
9114ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  bool already_generated = false;
912a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  switch (size) {
913a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kLong:
914a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kDouble:
915a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      is64bit = true;
916fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (!ARM_FPREG(r_src)) {
9174ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee        if (displacement <= 1020) {
9181fd3346740dfb7f47be9922312b68a4227fada96buzbee          store = NewLIR4(kThumb2StrdI8, r_src, r_src_hi, rBase, displacement >> 2);
9194ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee        } else {
9201fd3346740dfb7f47be9922312b68a4227fada96buzbee          store = StoreBaseDispBody(rBase, displacement, r_src, -1, kWord);
9211fd3346740dfb7f47be9922312b68a4227fada96buzbee          StoreBaseDispBody(rBase, displacement + 4, r_src_hi, -1, kWord);
9224ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee        }
9234ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee        already_generated = true;
9244ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      } else {
9254ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee        if (ARM_SINGLEREG(r_src)) {
9264ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee          DCHECK(ARM_FPREG(r_src_hi));
9271fd3346740dfb7f47be9922312b68a4227fada96buzbee          r_src = S2d(r_src, r_src_hi);
9284ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee        }
9294ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee        opcode = kThumb2Vstrd;
9304ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee        if (displacement <= 1020) {
9314ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee          short_form = true;
9324ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee          encoded_disp >>= 2;
9334ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee        }
934a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
935a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
936a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kSingle:
937a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kWord:
938fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (ARM_FPREG(r_src)) {
939fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        DCHECK(ARM_SINGLEREG(r_src));
940a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        opcode = kThumb2Vstrs;
941a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        if (displacement <= 1020) {
942fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee          short_form = true;
943fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee          encoded_disp >>= 2;
944a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        }
945a188cd4ad38aa561742d5f3f5b45215f451cb834Sebastien Hertz        break;
946a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
947a188cd4ad38aa561742d5f3f5b45215f451cb834Sebastien Hertz      if (ARM_LOWREG(r_src) && (rBase == r13sp) &&
948a188cd4ad38aa561742d5f3f5b45215f451cb834Sebastien Hertz          (displacement <= 1020) && (displacement >= 0)) {
949a188cd4ad38aa561742d5f3f5b45215f451cb834Sebastien Hertz        short_form = true;
950a188cd4ad38aa561742d5f3f5b45215f451cb834Sebastien Hertz        encoded_disp >>= 2;
951a188cd4ad38aa561742d5f3f5b45215f451cb834Sebastien Hertz        opcode = kThumbStrSpRel;
952a188cd4ad38aa561742d5f3f5b45215f451cb834Sebastien Hertz      } else if (all_low_regs && displacement < 128 && displacement >= 0) {
953a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        DCHECK_EQ((displacement & 0x3), 0);
954fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        short_form = true;
955fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        encoded_disp >>= 2;
956a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        opcode = kThumbStrRRI5;
957a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      } else if (thumb2Form) {
958fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        short_form = true;
959a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        opcode = kThumb2StrRRI12;
960a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
961a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
962a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kUnsignedHalf:
963a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kSignedHalf:
964fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (all_low_regs && displacement < 64 && displacement >= 0) {
965a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        DCHECK_EQ((displacement & 0x1), 0);
966fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        short_form = true;
967fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        encoded_disp >>= 1;
968a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        opcode = kThumbStrhRRI5;
969a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      } else if (thumb2Form) {
970fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        short_form = true;
971a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        opcode = kThumb2StrhRRI12;
972a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
973a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
974a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kUnsignedByte:
975a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    case kSignedByte:
976fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (all_low_regs && displacement < 32 && displacement >= 0) {
977fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        short_form = true;
978a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        opcode = kThumbStrbRRI5;
979a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      } else if (thumb2Form) {
980fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        short_form = true;
981a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        opcode = kThumb2StrbRRI12;
982a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
983a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      break;
984a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    default:
985cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      LOG(FATAL) << "Bad size: " << size;
986a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
9874ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  if (!already_generated) {
9884ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    if (short_form) {
9891fd3346740dfb7f47be9922312b68a4227fada96buzbee      store = NewLIR3(opcode, r_src, rBase, encoded_disp);
9904ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    } else {
9911fd3346740dfb7f47be9922312b68a4227fada96buzbee      int r_scratch = AllocTemp();
9921fd3346740dfb7f47be9922312b68a4227fada96buzbee      LoadConstant(r_scratch, encoded_disp);
9931fd3346740dfb7f47be9922312b68a4227fada96buzbee      store = StoreBaseIndexed(rBase, r_scratch, r_src, 0, size);
9941fd3346740dfb7f47be9922312b68a4227fada96buzbee      FreeTemp(r_scratch);
9954ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    }
996a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
99767bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
998a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  // TODO: In future, may need to differentiate Dalvik & spill accesses
999f0504cdc5b6400edd4b39eea64ac280465042d5bbuzbee  if (rBase == rARM_SP) {
10001fd3346740dfb7f47be9922312b68a4227fada96buzbee    AnnotateDalvikRegAccess(store, displacement >> 2, false /* is_load */, is64bit);
1001a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
10024ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  return store;
100367bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
100467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
10051fd3346740dfb7f47be9922312b68a4227fada96buzbeeLIR* ArmMir2Lir::StoreBaseDisp(int rBase, int displacement, int r_src,
10062ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                               OpSize size) {
10071fd3346740dfb7f47be9922312b68a4227fada96buzbee  return StoreBaseDispBody(rBase, displacement, r_src, -1, size);
100867bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
100967bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
10101fd3346740dfb7f47be9922312b68a4227fada96buzbeeLIR* ArmMir2Lir::StoreBaseDispWide(int rBase, int displacement,
10112ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                                   int r_src_lo, int r_src_hi) {
10121fd3346740dfb7f47be9922312b68a4227fada96buzbee  return StoreBaseDispBody(rBase, displacement, r_src_lo, r_src_hi, kLong);
101367bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
101467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
10152ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromLIR* ArmMir2Lir::OpFpRegCopy(int r_dest, int r_src) {
1016a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  int opcode;
1017fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  DCHECK_EQ(ARM_DOUBLEREG(r_dest), ARM_DOUBLEREG(r_src));
1018fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (ARM_DOUBLEREG(r_dest)) {
1019a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    opcode = kThumb2Vmovd;
1020a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  } else {
1021fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (ARM_SINGLEREG(r_dest)) {
1022fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = ARM_SINGLEREG(r_src) ? kThumb2Vmovs : kThumb2Fmsr;
102367bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    } else {
1024fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      DCHECK(ARM_SINGLEREG(r_src));
1025a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      opcode = kThumb2Fmrs;
102667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    }
1027a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
10281fd3346740dfb7f47be9922312b68a4227fada96buzbee  LIR* res = RawLIR(current_dalvik_offset_, opcode, r_dest, r_src);
10291fd3346740dfb7f47be9922312b68a4227fada96buzbee  if (!(cu_->disable_opt & (1 << kSafeOptimizations)) && r_dest == r_src) {
1030fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    res->flags.is_nop = true;
1031a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
1032a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return res;
103367bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
103467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
1035468532ea115657709bc32ee498e701a4c71762d4Ian RogersLIR* ArmMir2Lir::OpThreadMem(OpKind op, ThreadOffset thread_offset) {
103652a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee  LOG(FATAL) << "Unexpected use of OpThreadMem for Arm";
1037b046e16d8b8da318d6055f9308950131f1255e08buzbee  return NULL;
1038b046e16d8b8da318d6055f9308950131f1255e08buzbee}
1039b046e16d8b8da318d6055f9308950131f1255e08buzbee
10402ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromLIR* ArmMir2Lir::OpMem(OpKind op, int rBase, int disp) {
104152a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee  LOG(FATAL) << "Unexpected use of OpMem for Arm";
1042b046e16d8b8da318d6055f9308950131f1255e08buzbee  return NULL;
1043b046e16d8b8da318d6055f9308950131f1255e08buzbee}
104467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
10451fd3346740dfb7f47be9922312b68a4227fada96buzbeeLIR* ArmMir2Lir::StoreBaseIndexedDisp(int rBase, int r_index, int scale,
104602031b185b4653e6c72e21f7a51238b903f6d638buzbee                                      int displacement, int r_src, int r_src_hi, OpSize size,
10472ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                                      int s_reg) {
104852a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee  LOG(FATAL) << "Unexpected use of StoreBaseIndexedDisp for Arm";
1049b046e16d8b8da318d6055f9308950131f1255e08buzbee  return NULL;
1050b046e16d8b8da318d6055f9308950131f1255e08buzbee}
1051b046e16d8b8da318d6055f9308950131f1255e08buzbee
10522ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromLIR* ArmMir2Lir::OpRegMem(OpKind op, int r_dest, int rBase, int offset) {
105352a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee  LOG(FATAL) << "Unexpected use of OpRegMem for Arm";
1054b046e16d8b8da318d6055f9308950131f1255e08buzbee  return NULL;
1055b046e16d8b8da318d6055f9308950131f1255e08buzbee}
1056b046e16d8b8da318d6055f9308950131f1255e08buzbee
10571fd3346740dfb7f47be9922312b68a4227fada96buzbeeLIR* ArmMir2Lir::LoadBaseIndexedDisp(int rBase, int r_index, int scale,
105802031b185b4653e6c72e21f7a51238b903f6d638buzbee                                     int displacement, int r_dest, int r_dest_hi, OpSize size,
10592ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                                     int s_reg) {
106052a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee  LOG(FATAL) << "Unexpected use of LoadBaseIndexedDisp for Arm";
1061b046e16d8b8da318d6055f9308950131f1255e08buzbee  return NULL;
1062b046e16d8b8da318d6055f9308950131f1255e08buzbee}
106311d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughes
106411d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughes}  // namespace art
1065