int_arm.cc revision 0d82948094d9a198e01aa95f64012bdedd5b6fc9
1efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/*
2efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Copyright (C) 2011 The Android Open Source Project
3efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *
4efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Licensed under the Apache License, Version 2.0 (the "License");
5efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * you may not use this file except in compliance with the License.
6efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * You may obtain a copy of the License at
7efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *
8efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *      http://www.apache.org/licenses/LICENSE-2.0
9efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *
10efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Unless required by applicable law or agreed to in writing, software
11efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * distributed under the License is distributed on an "AS IS" BASIS,
12efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * See the License for the specific language governing permissions and
14efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * limitations under the License.
15efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */
16efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
17efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* This file contains codegen for the Thumb2 ISA. */
18efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
191bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee#include "arm_lir.h"
2002031b185b4653e6c72e21f7a51238b903f6d638buzbee#include "codegen_arm.h"
217940e44f4517de5e2634a7e07d58d0fb26160513Brian Carlstrom#include "dex/quick/mir_to_lir-inl.h"
22166db04e259ca51838c311891598664deeed85adIan Rogers#include "entrypoints/quick/quick_entrypoints.h"
2333e9566255c426e7a2c8fca5b8a1b6a94a5d352cIan Rogers#include "mirror/array.h"
24efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
25efc6369224b036a1fb77849f7ae65b3492c832c0buzbeenamespace art {
26efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
27d9c4fc94fa618617f94e1de9af5f034549100753Ian RogersLIR* ArmMir2Lir::OpCmpBranch(ConditionCode cond, int src1, int src2, LIR* target) {
281fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpRegReg(kOpCmp, src1, src2);
291fd3346740dfb7f47be9922312b68a4227fada96buzbee  return OpCondBranch(cond, target);
30efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
31efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
32efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/*
33efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Generate a Thumb2 IT instruction, which can nullify up to
34efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * four subsequent instructions based on a condition and its
35efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * inverse.  The condition applies to the first instruction, which
36efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * is executed if the condition is met.  The string "guide" consists
37efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * of 0 to 3 chars, and applies to the 2nd through 4th instruction.
38efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * A "T" means the instruction is executed if the condition is
39efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * met, and an "E" means the instruction is executed if the condition
40efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * is not met.
41efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */
422ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromLIR* ArmMir2Lir::OpIT(ConditionCode ccode, const char* guide) {
43efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  int mask;
44efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  int mask3 = 0;
45efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  int mask2 = 0;
46efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  int mask1 = 0;
4702031b185b4653e6c72e21f7a51238b903f6d638buzbee  ArmConditionCode code = ArmConditionEncoding(ccode);
4802031b185b4653e6c72e21f7a51238b903f6d638buzbee  int cond_bit = code & 1;
4902031b185b4653e6c72e21f7a51238b903f6d638buzbee  int alt_bit = cond_bit ^ 1;
50efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
517934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom  // Note: case fallthroughs intentional
52efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  switch (strlen(guide)) {
53efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    case 3:
54fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      mask1 = (guide[2] == 'T') ? cond_bit : alt_bit;
55efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    case 2:
56fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      mask2 = (guide[1] == 'T') ? cond_bit : alt_bit;
57efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    case 1:
58fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      mask3 = (guide[0] == 'T') ? cond_bit : alt_bit;
59efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      break;
60efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    case 0:
61efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      break;
62efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    default:
6352a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee      LOG(FATAL) << "OAT: bad case in OpIT";
64efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
65efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  mask = (mask3 << 3) | (mask2 << 2) | (mask1 << 1) |
66efc6369224b036a1fb77849f7ae65b3492c832c0buzbee       (1 << (3 - strlen(guide)));
671fd3346740dfb7f47be9922312b68a4227fada96buzbee  return NewLIR2(kThumb2It, code, mask);
68efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
69efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
70efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/*
71efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * 64-bit 3way compare function.
72efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *     mov   rX, #-1
73efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *     cmp   op1hi, op2hi
74efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *     blt   done
75efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *     bgt   flip
76efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *     sub   rX, op1lo, op2lo (treat as unsigned)
77efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *     beq   done
78efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *     ite   hi
79efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *     mov(hi)   rX, #-1
80efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *     mov(!hi)  rX, #1
81efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * flip:
82efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *     neg   rX
83efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * done:
84efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */
851fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::GenCmpLong(RegLocation rl_dest, RegLocation rl_src1,
862ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                            RegLocation rl_src2) {
87efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  LIR* target1;
88efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  LIR* target2;
891fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src1 = LoadValueWide(rl_src1, kCoreReg);
901fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src2 = LoadValueWide(rl_src2, kCoreReg);
911fd3346740dfb7f47be9922312b68a4227fada96buzbee  int t_reg = AllocTemp();
921fd3346740dfb7f47be9922312b68a4227fada96buzbee  LoadConstant(t_reg, -1);
931fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpRegReg(kOpCmp, rl_src1.high_reg, rl_src2.high_reg);
941fd3346740dfb7f47be9922312b68a4227fada96buzbee  LIR* branch1 = OpCondBranch(kCondLt, NULL);
951fd3346740dfb7f47be9922312b68a4227fada96buzbee  LIR* branch2 = OpCondBranch(kCondGt, NULL);
961fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpRegRegReg(kOpSub, t_reg, rl_src1.low_reg, rl_src2.low_reg);
971fd3346740dfb7f47be9922312b68a4227fada96buzbee  LIR* branch3 = OpCondBranch(kCondEq, NULL);
981fd3346740dfb7f47be9922312b68a4227fada96buzbee
991fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpIT(kCondHi, "E");
1001fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR2(kThumb2MovImmShift, t_reg, ModifiedImmediate(-1));
1011fd3346740dfb7f47be9922312b68a4227fada96buzbee  LoadConstant(t_reg, 1);
1021fd3346740dfb7f47be9922312b68a4227fada96buzbee  GenBarrier();
1031fd3346740dfb7f47be9922312b68a4227fada96buzbee
1041fd3346740dfb7f47be9922312b68a4227fada96buzbee  target2 = NewLIR0(kPseudoTargetLabel);
1051fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpRegReg(kOpNeg, t_reg, t_reg);
1061fd3346740dfb7f47be9922312b68a4227fada96buzbee
1071fd3346740dfb7f47be9922312b68a4227fada96buzbee  target1 = NewLIR0(kPseudoTargetLabel);
108fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee
1097934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom  RegLocation rl_temp = LocCReturn();  // Just using as template, will change
110fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  rl_temp.low_reg = t_reg;
1111fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValue(rl_dest, rl_temp);
1121fd3346740dfb7f47be9922312b68a4227fada96buzbee  FreeTemp(t_reg);
113efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
114cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee  branch1->target = target1;
115cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee  branch2->target = target2;
116efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  branch3->target = branch1->target;
117efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
118efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
1191fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::GenFusedLongCmpImmBranch(BasicBlock* bb, RegLocation rl_src1,
1202ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                                          int64_t val, ConditionCode ccode) {
1214ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  int32_t val_lo = Low32Bits(val);
1224ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  int32_t val_hi = High32Bits(val);
1234274889d48ef82369bf2c1ca70d84689b4f9e93aBrian Carlstrom  DCHECK_GE(ModifiedImmediate(val_lo), 0);
1244274889d48ef82369bf2c1ca70d84689b4f9e93aBrian Carlstrom  DCHECK_GE(ModifiedImmediate(val_hi), 0);
1250d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  LIR* taken = &block_label_list_[bb->taken];
1260d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  LIR* not_taken = &block_label_list_[bb->fall_through];
1271fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src1 = LoadValueWide(rl_src1, kCoreReg);
1284ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  int32_t low_reg = rl_src1.low_reg;
1294ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  int32_t high_reg = rl_src1.high_reg;
1304ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
131df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom  switch (ccode) {
1324ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case kCondEq:
1334ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case kCondNe:
134c7d1f91e024c5c560810376340aecb39d4e47fdcbuzbee      LIR* target;
135c7d1f91e024c5c560810376340aecb39d4e47fdcbuzbee      ConditionCode condition;
136c7d1f91e024c5c560810376340aecb39d4e47fdcbuzbee      if (ccode == kCondEq) {
137c7d1f91e024c5c560810376340aecb39d4e47fdcbuzbee        target = not_taken;
138c7d1f91e024c5c560810376340aecb39d4e47fdcbuzbee        condition = kCondEq;
139c7d1f91e024c5c560810376340aecb39d4e47fdcbuzbee      } else {
140c7d1f91e024c5c560810376340aecb39d4e47fdcbuzbee        target = taken;
141c7d1f91e024c5c560810376340aecb39d4e47fdcbuzbee        condition = kCondNe;
142c7d1f91e024c5c560810376340aecb39d4e47fdcbuzbee      }
143c7d1f91e024c5c560810376340aecb39d4e47fdcbuzbee      if (val == 0) {
1441fd3346740dfb7f47be9922312b68a4227fada96buzbee        int t_reg = AllocTemp();
1451fd3346740dfb7f47be9922312b68a4227fada96buzbee        NewLIR4(kThumb2OrrRRRs, t_reg, low_reg, high_reg, 0);
1461fd3346740dfb7f47be9922312b68a4227fada96buzbee        FreeTemp(t_reg);
1471fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpCondBranch(condition, taken);
148c7d1f91e024c5c560810376340aecb39d4e47fdcbuzbee        return;
149c7d1f91e024c5c560810376340aecb39d4e47fdcbuzbee      }
1501fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCmpImmBranch(kCondNe, high_reg, val_hi, target);
1514ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      break;
1524ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case kCondLt:
1531fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCmpImmBranch(kCondLt, high_reg, val_hi, taken);
1541fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCmpImmBranch(kCondGt, high_reg, val_hi, not_taken);
1554ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      ccode = kCondCc;
1564ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      break;
1574ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case kCondLe:
1581fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCmpImmBranch(kCondLt, high_reg, val_hi, taken);
1591fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCmpImmBranch(kCondGt, high_reg, val_hi, not_taken);
1604ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      ccode = kCondLs;
1614ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      break;
1624ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case kCondGt:
1631fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCmpImmBranch(kCondGt, high_reg, val_hi, taken);
1641fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCmpImmBranch(kCondLt, high_reg, val_hi, not_taken);
1654ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      ccode = kCondHi;
1664ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      break;
1674ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case kCondGe:
1681fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCmpImmBranch(kCondGt, high_reg, val_hi, taken);
1691fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCmpImmBranch(kCondLt, high_reg, val_hi, not_taken);
1704ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      ccode = kCondCs;
1714ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      break;
1724ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    default:
1734ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      LOG(FATAL) << "Unexpected ccode: " << ccode;
1744ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  }
1751fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpCmpImmBranch(ccode, low_reg, val_lo, taken);
1764ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee}
1774ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
1782ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid ArmMir2Lir::GenSelect(BasicBlock* bb, MIR* mir) {
179f662a7c625b1067f61b23c04459eba9b12bc027ebuzbee  RegLocation rl_result;
1801fd3346740dfb7f47be9922312b68a4227fada96buzbee  RegLocation rl_src = mir_graph_->GetSrc(mir, 0);
1811fd3346740dfb7f47be9922312b68a4227fada96buzbee  RegLocation rl_dest = mir_graph_->GetDest(mir);
1821fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src = LoadValue(rl_src, kCoreReg);
183f662a7c625b1067f61b23c04459eba9b12bc027ebuzbee  if (mir->ssa_rep->num_uses == 1) {
184f662a7c625b1067f61b23c04459eba9b12bc027ebuzbee    // CONST case
185f662a7c625b1067f61b23c04459eba9b12bc027ebuzbee    int true_val = mir->dalvikInsn.vB;
186f662a7c625b1067f61b23c04459eba9b12bc027ebuzbee    int false_val = mir->dalvikInsn.vC;
1871fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_result = EvalLoc(rl_dest, kCoreReg, true);
188f662a7c625b1067f61b23c04459eba9b12bc027ebuzbee    if ((true_val == 1) && (false_val == 0)) {
1891fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpRegRegImm(kOpRsub, rl_result.low_reg, rl_src.low_reg, 1);
1901fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpIT(kCondCc, "");
1911fd3346740dfb7f47be9922312b68a4227fada96buzbee      LoadConstant(rl_result.low_reg, 0);
1927934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom      GenBarrier();  // Add a scheduling barrier to keep the IT shadow intact
193f662a7c625b1067f61b23c04459eba9b12bc027ebuzbee    } else if (InexpensiveConstantInt(true_val) && InexpensiveConstantInt(false_val)) {
1941fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpRegImm(kOpCmp, rl_src.low_reg, 0);
1951fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpIT(kCondEq, "E");
1961fd3346740dfb7f47be9922312b68a4227fada96buzbee      LoadConstant(rl_result.low_reg, true_val);
1971fd3346740dfb7f47be9922312b68a4227fada96buzbee      LoadConstant(rl_result.low_reg, false_val);
1987934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom      GenBarrier();  // Add a scheduling barrier to keep the IT shadow intact
199f662a7c625b1067f61b23c04459eba9b12bc027ebuzbee    } else {
200f662a7c625b1067f61b23c04459eba9b12bc027ebuzbee      // Unlikely case - could be tuned.
2011fd3346740dfb7f47be9922312b68a4227fada96buzbee      int t_reg1 = AllocTemp();
2021fd3346740dfb7f47be9922312b68a4227fada96buzbee      int t_reg2 = AllocTemp();
2031fd3346740dfb7f47be9922312b68a4227fada96buzbee      LoadConstant(t_reg1, true_val);
2041fd3346740dfb7f47be9922312b68a4227fada96buzbee      LoadConstant(t_reg2, false_val);
2051fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpRegImm(kOpCmp, rl_src.low_reg, 0);
2061fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpIT(kCondEq, "E");
2071fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpRegCopy(rl_result.low_reg, t_reg1);
2081fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpRegCopy(rl_result.low_reg, t_reg2);
2097934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom      GenBarrier();  // Add a scheduling barrier to keep the IT shadow intact
210f662a7c625b1067f61b23c04459eba9b12bc027ebuzbee    }
211f662a7c625b1067f61b23c04459eba9b12bc027ebuzbee  } else {
212f662a7c625b1067f61b23c04459eba9b12bc027ebuzbee    // MOVE case
2131fd3346740dfb7f47be9922312b68a4227fada96buzbee    RegLocation rl_true = mir_graph_->reg_location_[mir->ssa_rep->uses[1]];
2141fd3346740dfb7f47be9922312b68a4227fada96buzbee    RegLocation rl_false = mir_graph_->reg_location_[mir->ssa_rep->uses[2]];
2151fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_true = LoadValue(rl_true, kCoreReg);
2161fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_false = LoadValue(rl_false, kCoreReg);
2171fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_result = EvalLoc(rl_dest, kCoreReg, true);
2181fd3346740dfb7f47be9922312b68a4227fada96buzbee    OpRegImm(kOpCmp, rl_src.low_reg, 0);
219252254b130067cd7a5071865e793966871ae0246buzbee    if (rl_result.low_reg == rl_true.low_reg) {  // Is the "true" case already in place?
220252254b130067cd7a5071865e793966871ae0246buzbee      OpIT(kCondNe, "");
221252254b130067cd7a5071865e793966871ae0246buzbee      OpRegCopy(rl_result.low_reg, rl_false.low_reg);
222252254b130067cd7a5071865e793966871ae0246buzbee    } else if (rl_result.low_reg == rl_false.low_reg) {  // False case in place?
223252254b130067cd7a5071865e793966871ae0246buzbee      OpIT(kCondEq, "");
224252254b130067cd7a5071865e793966871ae0246buzbee      OpRegCopy(rl_result.low_reg, rl_true.low_reg);
225252254b130067cd7a5071865e793966871ae0246buzbee    } else {  // Normal - select between the two.
226252254b130067cd7a5071865e793966871ae0246buzbee      OpIT(kCondEq, "E");
227252254b130067cd7a5071865e793966871ae0246buzbee      OpRegCopy(rl_result.low_reg, rl_true.low_reg);
228252254b130067cd7a5071865e793966871ae0246buzbee      OpRegCopy(rl_result.low_reg, rl_false.low_reg);
229252254b130067cd7a5071865e793966871ae0246buzbee    }
2307934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom    GenBarrier();  // Add a scheduling barrier to keep the IT shadow intact
231f662a7c625b1067f61b23c04459eba9b12bc027ebuzbee  }
2321fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValue(rl_dest, rl_result);
233f662a7c625b1067f61b23c04459eba9b12bc027ebuzbee}
2344ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
2352ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid ArmMir2Lir::GenFusedLongCmpBranch(BasicBlock* bb, MIR* mir) {
2361fd3346740dfb7f47be9922312b68a4227fada96buzbee  RegLocation rl_src1 = mir_graph_->GetSrcWide(mir, 0);
2371fd3346740dfb7f47be9922312b68a4227fada96buzbee  RegLocation rl_src2 = mir_graph_->GetSrcWide(mir, 2);
2384ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  // Normalize such that if either operand is constant, src2 will be constant.
2394ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  ConditionCode ccode = static_cast<ConditionCode>(mir->dalvikInsn.arg[0]);
2404ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  if (rl_src1.is_const) {
2414ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    RegLocation rl_temp = rl_src1;
2424ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    rl_src1 = rl_src2;
2434ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    rl_src2 = rl_temp;
2444ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    ccode = FlipComparisonOrder(ccode);
2454ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  }
2464ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  if (rl_src2.is_const) {
2471fd3346740dfb7f47be9922312b68a4227fada96buzbee    RegLocation rl_temp = UpdateLocWide(rl_src2);
2484ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    // Do special compare/branch against simple const operand if not already in registers.
2491fd3346740dfb7f47be9922312b68a4227fada96buzbee    int64_t val = mir_graph_->ConstantValueWide(rl_src2);
2504ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    if ((rl_temp.location != kLocPhysReg) &&
2514ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee        ((ModifiedImmediate(Low32Bits(val)) >= 0) && (ModifiedImmediate(High32Bits(val)) >= 0))) {
2521fd3346740dfb7f47be9922312b68a4227fada96buzbee      GenFusedLongCmpImmBranch(bb, rl_src1, val, ccode);
2534ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      return;
2544ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    }
2554ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  }
2560d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  LIR* taken = &block_label_list_[bb->taken];
2570d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  LIR* not_taken = &block_label_list_[bb->fall_through];
2581fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src1 = LoadValueWide(rl_src1, kCoreReg);
2591fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src2 = LoadValueWide(rl_src2, kCoreReg);
2601fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpRegReg(kOpCmp, rl_src1.high_reg, rl_src2.high_reg);
261df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom  switch (ccode) {
262efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    case kCondEq:
2631fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCondBranch(kCondNe, not_taken);
264efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      break;
265efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    case kCondNe:
2661fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCondBranch(kCondNe, taken);
267efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      break;
268efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    case kCondLt:
2691fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCondBranch(kCondLt, taken);
2701fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCondBranch(kCondGt, not_taken);
271efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      ccode = kCondCc;
272efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      break;
273efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    case kCondLe:
2741fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCondBranch(kCondLt, taken);
2751fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCondBranch(kCondGt, not_taken);
276efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      ccode = kCondLs;
277efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      break;
278efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    case kCondGt:
2791fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCondBranch(kCondGt, taken);
2801fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCondBranch(kCondLt, not_taken);
281efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      ccode = kCondHi;
282efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      break;
283efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    case kCondGe:
2841fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCondBranch(kCondGt, taken);
2851fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCondBranch(kCondLt, not_taken);
286efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      ccode = kCondCs;
287efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      break;
288efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    default:
289cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      LOG(FATAL) << "Unexpected ccode: " << ccode;
290efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
2911fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpRegReg(kOpCmp, rl_src1.low_reg, rl_src2.low_reg);
2921fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpCondBranch(ccode, taken);
293efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
294efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
295efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/*
296efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Generate a register comparison to an immediate and branch.  Caller
297efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * is responsible for setting branch target field.
298efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */
2991fd3346740dfb7f47be9922312b68a4227fada96buzbeeLIR* ArmMir2Lir::OpCmpImmBranch(ConditionCode cond, int reg, int check_value,
3002ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                                LIR* target) {
301efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  LIR* branch;
302fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  int mod_imm;
303fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  ArmConditionCode arm_cond = ArmConditionEncoding(cond);
304b48819db07f9a0992a72173380c24249d7fc648abuzbee  /*
305b48819db07f9a0992a72173380c24249d7fc648abuzbee   * A common use of OpCmpImmBranch is for null checks, and using the Thumb 16-bit
306b48819db07f9a0992a72173380c24249d7fc648abuzbee   * compare-and-branch if zero is ideal if it will reach.  However, because null checks
307b48819db07f9a0992a72173380c24249d7fc648abuzbee   * branch forward to a launch pad, they will frequently not reach - and thus have to
308b48819db07f9a0992a72173380c24249d7fc648abuzbee   * be converted to a long form during assembly (which will trigger another assembly
309b48819db07f9a0992a72173380c24249d7fc648abuzbee   * pass).  Here we estimate the branch distance for checks, and if large directly
310b48819db07f9a0992a72173380c24249d7fc648abuzbee   * generate the long form in an attempt to avoid an extra assembly pass.
311b48819db07f9a0992a72173380c24249d7fc648abuzbee   * TODO: consider interspersing launchpads in code following unconditional branches.
312b48819db07f9a0992a72173380c24249d7fc648abuzbee   */
313b48819db07f9a0992a72173380c24249d7fc648abuzbee  bool skip = ((target != NULL) && (target->opcode == kPseudoThrowTarget));
314b48819db07f9a0992a72173380c24249d7fc648abuzbee  skip &= ((cu_->code_item->insns_size_in_code_units_ - current_dalvik_offset_) > 64);
315b48819db07f9a0992a72173380c24249d7fc648abuzbee  if (!skip && (ARM_LOWREG(reg)) && (check_value == 0) &&
316fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee     ((arm_cond == kArmCondEq) || (arm_cond == kArmCondNe))) {
3171fd3346740dfb7f47be9922312b68a4227fada96buzbee    branch = NewLIR2((arm_cond == kArmCondEq) ? kThumb2Cbz : kThumb2Cbnz,
318efc6369224b036a1fb77849f7ae65b3492c832c0buzbee                     reg, 0);
319efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  } else {
320fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    mod_imm = ModifiedImmediate(check_value);
321fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (ARM_LOWREG(reg) && ((check_value & 0xff) == check_value)) {
3221fd3346740dfb7f47be9922312b68a4227fada96buzbee      NewLIR2(kThumbCmpRI8, reg, check_value);
323fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    } else if (mod_imm >= 0) {
3241fd3346740dfb7f47be9922312b68a4227fada96buzbee      NewLIR2(kThumb2CmpRI12, reg, mod_imm);
325efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    } else {
3261fd3346740dfb7f47be9922312b68a4227fada96buzbee      int t_reg = AllocTemp();
3271fd3346740dfb7f47be9922312b68a4227fada96buzbee      LoadConstant(t_reg, check_value);
3281fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpRegReg(kOpCmp, reg, t_reg);
329efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    }
3301fd3346740dfb7f47be9922312b68a4227fada96buzbee    branch = NewLIR2(kThumbBCond, 0, arm_cond);
331efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
332efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  branch->target = target;
333efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return branch;
334efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
33502031b185b4653e6c72e21f7a51238b903f6d638buzbee
3362ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromLIR* ArmMir2Lir::OpRegCopyNoInsert(int r_dest, int r_src) {
337efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  LIR* res;
338efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  int opcode;
339fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (ARM_FPREG(r_dest) || ARM_FPREG(r_src))
3401fd3346740dfb7f47be9922312b68a4227fada96buzbee    return OpFpRegCopy(r_dest, r_src);
341fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (ARM_LOWREG(r_dest) && ARM_LOWREG(r_src))
342efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    opcode = kThumbMovRR;
343fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  else if (!ARM_LOWREG(r_dest) && !ARM_LOWREG(r_src))
344efc6369224b036a1fb77849f7ae65b3492c832c0buzbee     opcode = kThumbMovRR_H2H;
345fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  else if (ARM_LOWREG(r_dest))
346efc6369224b036a1fb77849f7ae65b3492c832c0buzbee     opcode = kThumbMovRR_H2L;
347efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  else
348efc6369224b036a1fb77849f7ae65b3492c832c0buzbee     opcode = kThumbMovRR_L2H;
3491fd3346740dfb7f47be9922312b68a4227fada96buzbee  res = RawLIR(current_dalvik_offset_, opcode, r_dest, r_src);
3501fd3346740dfb7f47be9922312b68a4227fada96buzbee  if (!(cu_->disable_opt & (1 << kSafeOptimizations)) && r_dest == r_src) {
351fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    res->flags.is_nop = true;
352efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
353efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return res;
354efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
355efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
3562ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromLIR* ArmMir2Lir::OpRegCopy(int r_dest, int r_src) {
3571fd3346740dfb7f47be9922312b68a4227fada96buzbee  LIR* res = OpRegCopyNoInsert(r_dest, r_src);
3581fd3346740dfb7f47be9922312b68a4227fada96buzbee  AppendLIR(res);
359efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return res;
360efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
361efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
3621fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::OpRegCopyWide(int dest_lo, int dest_hi, int src_lo,
3632ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                               int src_hi) {
364fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  bool dest_fp = ARM_FPREG(dest_lo) && ARM_FPREG(dest_hi);
365fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  bool src_fp = ARM_FPREG(src_lo) && ARM_FPREG(src_hi);
366fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  DCHECK_EQ(ARM_FPREG(src_lo), ARM_FPREG(src_hi));
367fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  DCHECK_EQ(ARM_FPREG(dest_lo), ARM_FPREG(dest_hi));
368fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (dest_fp) {
369fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (src_fp) {
3701fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpRegCopy(S2d(dest_lo, dest_hi), S2d(src_lo, src_hi));
371efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    } else {
3721fd3346740dfb7f47be9922312b68a4227fada96buzbee      NewLIR3(kThumb2Fmdrr, S2d(dest_lo, dest_hi), src_lo, src_hi);
373efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    }
374efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  } else {
375fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (src_fp) {
3761fd3346740dfb7f47be9922312b68a4227fada96buzbee      NewLIR3(kThumb2Fmrrd, dest_lo, dest_hi, S2d(src_lo, src_hi));
377efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    } else {
378efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      // Handle overlap
379fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (src_hi == dest_lo) {
3801fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegCopy(dest_hi, src_hi);
3811fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegCopy(dest_lo, src_lo);
382efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      } else {
3831fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegCopy(dest_lo, src_lo);
3841fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegCopy(dest_hi, src_hi);
385efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      }
386efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    }
387efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
388efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
389efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
390efc6369224b036a1fb77849f7ae65b3492c832c0buzbee// Table of magic divisors
391efc6369224b036a1fb77849f7ae65b3492c832c0buzbeestruct MagicTable {
392efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  uint32_t magic;
393efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  uint32_t shift;
394efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  DividePattern pattern;
395efc6369224b036a1fb77849f7ae65b3492c832c0buzbee};
396efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
397fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeestatic const MagicTable magic_table[] = {
398efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0, 0, DivideNone},        // 0
399efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0, 0, DivideNone},        // 1
400efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0, 0, DivideNone},        // 2
401efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0x55555556, 0, Divide3},  // 3
402efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0, 0, DivideNone},        // 4
403efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0x66666667, 1, Divide5},  // 5
404efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0x2AAAAAAB, 0, Divide3},  // 6
405efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0x92492493, 2, Divide7},  // 7
406efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0, 0, DivideNone},        // 8
407efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0x38E38E39, 1, Divide5},  // 9
408efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0x66666667, 2, Divide5},  // 10
409efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0x2E8BA2E9, 1, Divide5},  // 11
410efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0x2AAAAAAB, 1, Divide5},  // 12
411efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0x4EC4EC4F, 2, Divide5},  // 13
412efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0x92492493, 3, Divide7},  // 14
413efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0x88888889, 3, Divide7},  // 15
414efc6369224b036a1fb77849f7ae65b3492c832c0buzbee};
415efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
416efc6369224b036a1fb77849f7ae65b3492c832c0buzbee// Integer division by constant via reciprocal multiply (Hacker's Delight, 10-4)
41711b63d13f0a3be0f74390b66b58614a37f9aa6c1buzbeebool ArmMir2Lir::SmallLiteralDivRem(Instruction::Code dalvik_opcode, bool is_div,
4182ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                                    RegLocation rl_src, RegLocation rl_dest, int lit) {
419fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if ((lit < 0) || (lit >= static_cast<int>(sizeof(magic_table)/sizeof(magic_table[0])))) {
420efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    return false;
421efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
422fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  DividePattern pattern = magic_table[lit].pattern;
423efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  if (pattern == DivideNone) {
424efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    return false;
425efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
426efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  // Tuning: add rem patterns
42711b63d13f0a3be0f74390b66b58614a37f9aa6c1buzbee  if (!is_div) {
428efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    return false;
429efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
430efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
4311fd3346740dfb7f47be9922312b68a4227fada96buzbee  int r_magic = AllocTemp();
4321fd3346740dfb7f47be9922312b68a4227fada96buzbee  LoadConstant(r_magic, magic_table[lit].magic);
4331fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src = LoadValue(rl_src, kCoreReg);
4341fd3346740dfb7f47be9922312b68a4227fada96buzbee  RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
4351fd3346740dfb7f47be9922312b68a4227fada96buzbee  int r_hi = AllocTemp();
4361fd3346740dfb7f47be9922312b68a4227fada96buzbee  int r_lo = AllocTemp();
4371fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR4(kThumb2Smull, r_lo, r_hi, r_magic, rl_src.low_reg);
438df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom  switch (pattern) {
439efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    case Divide3:
4401fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpRegRegRegShift(kOpSub, rl_result.low_reg, r_hi,
441fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee               rl_src.low_reg, EncodeShift(kArmAsr, 31));
442efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      break;
443efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    case Divide5:
4441fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpRegRegImm(kOpAsr, r_lo, rl_src.low_reg, 31);
4451fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpRegRegRegShift(kOpRsub, rl_result.low_reg, r_lo, r_hi,
446fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee               EncodeShift(kArmAsr, magic_table[lit].shift));
447efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      break;
448efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    case Divide7:
4491fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpRegReg(kOpAdd, r_hi, rl_src.low_reg);
4501fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpRegRegImm(kOpAsr, r_lo, rl_src.low_reg, 31);
4511fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpRegRegRegShift(kOpRsub, rl_result.low_reg, r_lo, r_hi,
452fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee               EncodeShift(kArmAsr, magic_table[lit].shift));
453efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      break;
454efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    default:
455cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      LOG(FATAL) << "Unexpected pattern: " << pattern;
456efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
4571fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValue(rl_dest, rl_result);
458efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return true;
459efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
460efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
4611fd3346740dfb7f47be9922312b68a4227fada96buzbeeLIR* ArmMir2Lir::GenRegMemCheck(ConditionCode c_code,
4622ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                    int reg1, int base, int offset, ThrowKind kind) {
46352a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee  LOG(FATAL) << "Unexpected use of GenRegMemCheck for Arm";
464efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return NULL;
465efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
466efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
4671fd3346740dfb7f47be9922312b68a4227fada96buzbeeRegLocation ArmMir2Lir::GenDivRemLit(RegLocation rl_dest, int reg1, int lit,
4682ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                                     bool is_div) {
46952a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee  LOG(FATAL) << "Unexpected use of GenDivRemLit for Arm";
470fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  return rl_dest;
471efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
472efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
4731fd3346740dfb7f47be9922312b68a4227fada96buzbeeRegLocation ArmMir2Lir::GenDivRem(RegLocation rl_dest, int reg1, int reg2,
4742ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                                  bool is_div) {
47552a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee  LOG(FATAL) << "Unexpected use of GenDivRem for Arm";
476fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  return rl_dest;
477efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
478efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
4792ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrombool ArmMir2Lir::GenInlinedMinMaxInt(CallInfo* info, bool is_min) {
4801fd3346740dfb7f47be9922312b68a4227fada96buzbee  DCHECK_EQ(cu_->instruction_set, kThumb2);
481fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_src1 = info->args[0];
482fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_src2 = info->args[1];
4831fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src1 = LoadValue(rl_src1, kCoreReg);
4841fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src2 = LoadValue(rl_src2, kCoreReg);
4851fd3346740dfb7f47be9922312b68a4227fada96buzbee  RegLocation rl_dest = InlineTarget(info);
4861fd3346740dfb7f47be9922312b68a4227fada96buzbee  RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
4871fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpRegReg(kOpCmp, rl_src1.low_reg, rl_src2.low_reg);
4881fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpIT((is_min) ? kCondGt : kCondLt, "E");
4891fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpRegReg(kOpMov, rl_result.low_reg, rl_src2.low_reg);
4901fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpRegReg(kOpMov, rl_result.low_reg, rl_src1.low_reg);
4911fd3346740dfb7f47be9922312b68a4227fada96buzbee  GenBarrier();
4921fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValue(rl_dest, rl_result);
493efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return true;
494efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
495efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
4962ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid ArmMir2Lir::OpLea(int rBase, int reg1, int reg2, int scale, int offset) {
49752a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee  LOG(FATAL) << "Unexpected use of OpLea for Arm";
498efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
499efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
500468532ea115657709bc32ee498e701a4c71762d4Ian Rogersvoid ArmMir2Lir::OpTlsCmp(ThreadOffset offset, int val) {
50152a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee  LOG(FATAL) << "Unexpected use of OpTlsCmp for Arm";
502efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
503efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
5041fd3346740dfb7f47be9922312b68a4227fada96buzbeebool ArmMir2Lir::GenInlinedCas32(CallInfo* info, bool need_write_barrier) {
5051fd3346740dfb7f47be9922312b68a4227fada96buzbee  DCHECK_EQ(cu_->instruction_set, kThumb2);
506fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  // Unused - RegLocation rl_src_unsafe = info->args[0];
507fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_src_obj= info->args[1];  // Object - known non-null
508fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_src_offset= info->args[2];  // long low
509fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  rl_src_offset.wide = 0;  // ignore high half in info->args[3]
510fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_src_expected= info->args[4];  // int or Object
511fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_src_new_value= info->args[5];  // int or Object
5121fd3346740dfb7f47be9922312b68a4227fada96buzbee  RegLocation rl_dest = InlineTarget(info);  // boolean place for result
513efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
514efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
5151bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee  // Release store semantics, get the barrier out of the way.  TODO: revisit
5161fd3346740dfb7f47be9922312b68a4227fada96buzbee  GenMemBarrier(kStoreLoad);
517efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
5181fd3346740dfb7f47be9922312b68a4227fada96buzbee  RegLocation rl_object = LoadValue(rl_src_obj, kCoreReg);
5191fd3346740dfb7f47be9922312b68a4227fada96buzbee  RegLocation rl_new_value = LoadValue(rl_src_new_value, kCoreReg);
520efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
5211fd3346740dfb7f47be9922312b68a4227fada96buzbee  if (need_write_barrier && !mir_graph_->IsConstantNullRef(rl_new_value)) {
522efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    // Mark card for object assuming new value is stored.
5231fd3346740dfb7f47be9922312b68a4227fada96buzbee    MarkGCCard(rl_new_value.low_reg, rl_object.low_reg);
524efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
525efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
5261fd3346740dfb7f47be9922312b68a4227fada96buzbee  RegLocation rl_offset = LoadValue(rl_src_offset, kCoreReg);
527efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
5281fd3346740dfb7f47be9922312b68a4227fada96buzbee  int r_ptr = AllocTemp();
5291fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpRegRegReg(kOpAdd, r_ptr, rl_object.low_reg, rl_offset.low_reg);
530efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
531fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  // Free now unneeded rl_object and rl_offset to give more temps.
5321fd3346740dfb7f47be9922312b68a4227fada96buzbee  ClobberSReg(rl_object.s_reg_low);
5331fd3346740dfb7f47be9922312b68a4227fada96buzbee  FreeTemp(rl_object.low_reg);
5341fd3346740dfb7f47be9922312b68a4227fada96buzbee  ClobberSReg(rl_offset.s_reg_low);
5351fd3346740dfb7f47be9922312b68a4227fada96buzbee  FreeTemp(rl_offset.low_reg);
536efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
5372de2aa1a96dfa5bebc004f29b5dbfafd37039ceeJeff Hao  RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
5382de2aa1a96dfa5bebc004f29b5dbfafd37039ceeJeff Hao  LoadConstant(rl_result.low_reg, 0);  // r_result := 0
539efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
5402de2aa1a96dfa5bebc004f29b5dbfafd37039ceeJeff Hao  // while ([r_ptr] == rExpected && r_result == 0) {
541fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  //   [r_ptr] <- r_new_value && r_result := success ? 0 : 1
542fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  //   r_result ^= 1
543efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  // }
5442de2aa1a96dfa5bebc004f29b5dbfafd37039ceeJeff Hao  int r_old_value = AllocTemp();
5452de2aa1a96dfa5bebc004f29b5dbfafd37039ceeJeff Hao  LIR* target = NewLIR0(kPseudoTargetLabel);
5462de2aa1a96dfa5bebc004f29b5dbfafd37039ceeJeff Hao  NewLIR3(kThumb2Ldrex, r_old_value, r_ptr, 0);
5472de2aa1a96dfa5bebc004f29b5dbfafd37039ceeJeff Hao
5482de2aa1a96dfa5bebc004f29b5dbfafd37039ceeJeff Hao  RegLocation rl_expected = LoadValue(rl_src_expected, kCoreReg);
5491fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpRegReg(kOpCmp, r_old_value, rl_expected.low_reg);
5501fd3346740dfb7f47be9922312b68a4227fada96buzbee  FreeTemp(r_old_value);  // Now unneeded.
5512de2aa1a96dfa5bebc004f29b5dbfafd37039ceeJeff Hao  OpIT(kCondEq, "TT");
5522de2aa1a96dfa5bebc004f29b5dbfafd37039ceeJeff Hao  NewLIR4(kThumb2Strex /* eq */, rl_result.low_reg, rl_new_value.low_reg, r_ptr, 0);
5531fd3346740dfb7f47be9922312b68a4227fada96buzbee  FreeTemp(r_ptr);  // Now unneeded.
5542de2aa1a96dfa5bebc004f29b5dbfafd37039ceeJeff Hao  OpRegImm(kOpXor /* eq */, rl_result.low_reg, 1);
5552de2aa1a96dfa5bebc004f29b5dbfafd37039ceeJeff Hao  OpRegImm(kOpCmp /* eq */, rl_result.low_reg, 0);
5562de2aa1a96dfa5bebc004f29b5dbfafd37039ceeJeff Hao  OpCondBranch(kCondEq, target);
557efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
5581fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValue(rl_dest, rl_result);
559efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
560efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return true;
561efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
562efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
5632ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromLIR* ArmMir2Lir::OpPcRelLoad(int reg, LIR* target) {
5641fd3346740dfb7f47be9922312b68a4227fada96buzbee  return RawLIR(current_dalvik_offset_, kThumb2LdrPcRel12, reg, 0, 0, 0, 0, target);
565efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
566efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
5672ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromLIR* ArmMir2Lir::OpVldm(int rBase, int count) {
5681fd3346740dfb7f47be9922312b68a4227fada96buzbee  return NewLIR3(kThumb2Vldms, rBase, fr0, count);
569efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
570efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
5712ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromLIR* ArmMir2Lir::OpVstm(int rBase, int count) {
5721fd3346740dfb7f47be9922312b68a4227fada96buzbee  return NewLIR3(kThumb2Vstms, rBase, fr0, count);
573efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
574efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
5751fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::GenMultiplyByTwoBitMultiplier(RegLocation rl_src,
57602031b185b4653e6c72e21f7a51238b903f6d638buzbee                                               RegLocation rl_result, int lit,
5772ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                                               int first_bit, int second_bit) {
5781fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpRegRegRegShift(kOpAdd, rl_result.low_reg, rl_src.low_reg, rl_src.low_reg,
579fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                   EncodeShift(kArmLsl, second_bit - first_bit));
580fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (first_bit != 0) {
5811fd3346740dfb7f47be9922312b68a4227fada96buzbee    OpRegRegImm(kOpLsl, rl_result.low_reg, rl_result.low_reg, first_bit);
582efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
583efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
584efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
5852ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid ArmMir2Lir::GenDivZeroCheck(int reg_lo, int reg_hi) {
5861fd3346740dfb7f47be9922312b68a4227fada96buzbee  int t_reg = AllocTemp();
5871fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR4(kThumb2OrrRRRs, t_reg, reg_lo, reg_hi, 0);
5881fd3346740dfb7f47be9922312b68a4227fada96buzbee  FreeTemp(t_reg);
5891fd3346740dfb7f47be9922312b68a4227fada96buzbee  GenCheck(kCondEq, kThrowDivZero);
590efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
591efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
592efc6369224b036a1fb77849f7ae65b3492c832c0buzbee// Test suspend flag, return target of taken suspend branch
5932ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromLIR* ArmMir2Lir::OpTestSuspend(LIR* target) {
5941fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR2(kThumbSubRI8, rARM_SUSPEND, 1);
5951fd3346740dfb7f47be9922312b68a4227fada96buzbee  return OpCondBranch((target == NULL) ? kCondEq : kCondNe, target);
596efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
597efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
598efc6369224b036a1fb77849f7ae65b3492c832c0buzbee// Decrement register and branch on condition
5992ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromLIR* ArmMir2Lir::OpDecAndBranch(ConditionCode c_code, int reg, LIR* target) {
600efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  // Combine sub & test using sub setflags encoding here
6011fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR3(kThumb2SubsRRI12, reg, reg, 1);
6021fd3346740dfb7f47be9922312b68a4227fada96buzbee  return OpCondBranch(c_code, target);
603efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
604efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
6052ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid ArmMir2Lir::GenMemBarrier(MemBarrierKind barrier_kind) {
606efc6369224b036a1fb77849f7ae65b3492c832c0buzbee#if ANDROID_SMP != 0
607fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  int dmb_flavor;
6081bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee  // TODO: revisit Arm barrier kinds
609fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  switch (barrier_kind) {
610fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    case kLoadStore: dmb_flavor = kSY; break;
611fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    case kLoadLoad: dmb_flavor = kSY; break;
612fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    case kStoreStore: dmb_flavor = kST; break;
613fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    case kStoreLoad: dmb_flavor = kSY; break;
6141bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee    default:
615fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      LOG(FATAL) << "Unexpected MemBarrierKind: " << barrier_kind;
616fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      dmb_flavor = kSY;  // quiet gcc.
6171bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee      break;
6181bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee  }
6191fd3346740dfb7f47be9922312b68a4227fada96buzbee  LIR* dmb = NewLIR1(kThumb2Dmb, dmb_flavor);
620b48819db07f9a0992a72173380c24249d7fc648abuzbee  dmb->u.m.def_mask = ENCODE_ALL;
621efc6369224b036a1fb77849f7ae65b3492c832c0buzbee#endif
622efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
623efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
6242ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid ArmMir2Lir::GenNegLong(RegLocation rl_dest, RegLocation rl_src) {
6251fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src = LoadValueWide(rl_src, kCoreReg);
6261fd3346740dfb7f47be9922312b68a4227fada96buzbee  RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
6271fd3346740dfb7f47be9922312b68a4227fada96buzbee  int z_reg = AllocTemp();
6281fd3346740dfb7f47be9922312b68a4227fada96buzbee  LoadConstantNoClobber(z_reg, 0);
629efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  // Check for destructive overlap
630fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (rl_result.low_reg == rl_src.high_reg) {
6311fd3346740dfb7f47be9922312b68a4227fada96buzbee    int t_reg = AllocTemp();
6321fd3346740dfb7f47be9922312b68a4227fada96buzbee    OpRegRegReg(kOpSub, rl_result.low_reg, z_reg, rl_src.low_reg);
6331fd3346740dfb7f47be9922312b68a4227fada96buzbee    OpRegRegReg(kOpSbc, rl_result.high_reg, z_reg, t_reg);
6341fd3346740dfb7f47be9922312b68a4227fada96buzbee    FreeTemp(t_reg);
635efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  } else {
6361fd3346740dfb7f47be9922312b68a4227fada96buzbee    OpRegRegReg(kOpSub, rl_result.low_reg, z_reg, rl_src.low_reg);
6371fd3346740dfb7f47be9922312b68a4227fada96buzbee    OpRegRegReg(kOpSbc, rl_result.high_reg, z_reg, rl_src.high_reg);
638efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
6391fd3346740dfb7f47be9922312b68a4227fada96buzbee  FreeTemp(z_reg);
6401fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValueWide(rl_dest, rl_result);
641efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
642efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
6434ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
6444ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee /*
6454ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  * Check to see if a result pair has a misaligned overlap with an operand pair.  This
6464ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  * is not usual for dx to generate, but it is legal (for now).  In a future rev of
6474ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  * dex, we'll want to make this case illegal.
6484ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  */
6492ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrombool ArmMir2Lir::BadOverlap(RegLocation rl_src, RegLocation rl_dest) {
6504ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  DCHECK(rl_src.wide);
6514ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  DCHECK(rl_dest.wide);
6521fd3346740dfb7f47be9922312b68a4227fada96buzbee  return (abs(mir_graph_->SRegToVReg(rl_src.s_reg_low) - mir_graph_->SRegToVReg(rl_dest.s_reg_low)) == 1);
6534ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee}
6544ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
6551fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::GenMulLong(RegLocation rl_dest, RegLocation rl_src1,
6562ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                            RegLocation rl_src2) {
6574ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    /*
6584ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee     * To pull off inline multiply, we have a worst-case requirement of 8 temporary
6594ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee     * registers.  Normally for Arm, we get 5.  We can get to 6 by including
6604ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee     * lr in the temp set.  The only problematic case is all operands and result are
6614ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee     * distinct, and none have been promoted.  In that case, we can succeed by aggressively
6624ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee     * freeing operand temp registers after they are no longer needed.  All other cases
6634ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee     * can proceed normally.  We'll just punt on the case of the result having a misaligned
6644ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee     * overlap with either operand and send that case to a runtime handler.
6654ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee     */
6664ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    RegLocation rl_result;
6671fd3346740dfb7f47be9922312b68a4227fada96buzbee    if (BadOverlap(rl_src1, rl_dest) || (BadOverlap(rl_src2, rl_dest))) {
668468532ea115657709bc32ee498e701a4c71762d4Ian Rogers      ThreadOffset func_offset = QUICK_ENTRYPOINT_OFFSET(pLmul);
6691fd3346740dfb7f47be9922312b68a4227fada96buzbee      FlushAllRegs();
6701fd3346740dfb7f47be9922312b68a4227fada96buzbee      CallRuntimeHelperRegLocationRegLocation(func_offset, rl_src1, rl_src2, false);
6711fd3346740dfb7f47be9922312b68a4227fada96buzbee      rl_result = GetReturnWide(false);
6721fd3346740dfb7f47be9922312b68a4227fada96buzbee      StoreValueWide(rl_dest, rl_result);
6734ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      return;
6744ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    }
6754ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    // Temporarily add LR to the temp pool, and assign it to tmp1
6761fd3346740dfb7f47be9922312b68a4227fada96buzbee    MarkTemp(rARM_LR);
6771fd3346740dfb7f47be9922312b68a4227fada96buzbee    FreeTemp(rARM_LR);
6784ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    int tmp1 = rARM_LR;
6791fd3346740dfb7f47be9922312b68a4227fada96buzbee    LockTemp(rARM_LR);
6804ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
6811fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src1 = LoadValueWide(rl_src1, kCoreReg);
6821fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src2 = LoadValueWide(rl_src2, kCoreReg);
6834ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
6844ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    bool special_case = true;
6854ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    // If operands are the same, or any pair has been promoted we're not the special case.
6864ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    if ((rl_src1.s_reg_low == rl_src2.s_reg_low) ||
6871fd3346740dfb7f47be9922312b68a4227fada96buzbee        (!IsTemp(rl_src1.low_reg) && !IsTemp(rl_src1.high_reg)) ||
6881fd3346740dfb7f47be9922312b68a4227fada96buzbee        (!IsTemp(rl_src2.low_reg) && !IsTemp(rl_src2.high_reg))) {
6894ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      special_case = false;
6904ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    }
6914ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    // Tuning: if rl_dest has been promoted and is *not* either operand, could use directly.
6921fd3346740dfb7f47be9922312b68a4227fada96buzbee    int res_lo = AllocTemp();
6934ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    int res_hi;
6944ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    if (rl_src1.low_reg == rl_src2.low_reg) {
6951fd3346740dfb7f47be9922312b68a4227fada96buzbee      res_hi = AllocTemp();
6961fd3346740dfb7f47be9922312b68a4227fada96buzbee      NewLIR3(kThumb2MulRRR, tmp1, rl_src1.low_reg, rl_src1.high_reg);
6971fd3346740dfb7f47be9922312b68a4227fada96buzbee      NewLIR4(kThumb2Umull, res_lo, res_hi, rl_src1.low_reg, rl_src1.low_reg);
6981fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpRegRegRegShift(kOpAdd, res_hi, res_hi, tmp1, EncodeShift(kArmLsl, 1));
6994ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    } else {
7004ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      // In the special case, all temps are now allocated
7011fd3346740dfb7f47be9922312b68a4227fada96buzbee      NewLIR3(kThumb2MulRRR, tmp1, rl_src2.low_reg, rl_src1.high_reg);
7024ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      if (special_case) {
7034ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee        DCHECK_NE(rl_src1.low_reg, rl_src2.low_reg);
7044ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee        DCHECK_NE(rl_src1.high_reg, rl_src2.high_reg);
7051fd3346740dfb7f47be9922312b68a4227fada96buzbee        FreeTemp(rl_src1.high_reg);
7064ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      }
7071fd3346740dfb7f47be9922312b68a4227fada96buzbee      res_hi = AllocTemp();
7084ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
7091fd3346740dfb7f47be9922312b68a4227fada96buzbee      NewLIR4(kThumb2Umull, res_lo, res_hi, rl_src2.low_reg, rl_src1.low_reg);
7101fd3346740dfb7f47be9922312b68a4227fada96buzbee      NewLIR4(kThumb2Mla, tmp1, rl_src1.low_reg, rl_src2.high_reg, tmp1);
7111fd3346740dfb7f47be9922312b68a4227fada96buzbee      NewLIR4(kThumb2AddRRR, res_hi, tmp1, res_hi, 0);
7124ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      if (special_case) {
7131fd3346740dfb7f47be9922312b68a4227fada96buzbee        FreeTemp(rl_src1.low_reg);
7141fd3346740dfb7f47be9922312b68a4227fada96buzbee        Clobber(rl_src1.low_reg);
7151fd3346740dfb7f47be9922312b68a4227fada96buzbee        Clobber(rl_src1.high_reg);
7164ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      }
7174ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    }
7181fd3346740dfb7f47be9922312b68a4227fada96buzbee    FreeTemp(tmp1);
7197934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom    rl_result = GetReturnWide(false);  // Just using as a template.
7204ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    rl_result.low_reg = res_lo;
7214ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    rl_result.high_reg = res_hi;
7221fd3346740dfb7f47be9922312b68a4227fada96buzbee    StoreValueWide(rl_dest, rl_result);
7234ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    // Now, restore lr to its non-temp status.
7241fd3346740dfb7f47be9922312b68a4227fada96buzbee    Clobber(rARM_LR);
7251fd3346740dfb7f47be9922312b68a4227fada96buzbee    UnmarkTemp(rARM_LR);
7264ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee}
7274ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
7281fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::GenAddLong(RegLocation rl_dest, RegLocation rl_src1,
7292ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                            RegLocation rl_src2) {
73052a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee  LOG(FATAL) << "Unexpected use of GenAddLong for Arm";
731efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
732efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
7331fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::GenSubLong(RegLocation rl_dest, RegLocation rl_src1,
7342ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                            RegLocation rl_src2) {
73552a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee  LOG(FATAL) << "Unexpected use of GenSubLong for Arm";
736efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
737efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
7381fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::GenAndLong(RegLocation rl_dest, RegLocation rl_src1,
7392ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                            RegLocation rl_src2) {
74052a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee  LOG(FATAL) << "Unexpected use of GenAndLong for Arm";
741efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
742efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
7431fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::GenOrLong(RegLocation rl_dest, RegLocation rl_src1,
7442ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                           RegLocation rl_src2) {
74552a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee  LOG(FATAL) << "Unexpected use of GenOrLong for Arm";
746efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
747efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
7481fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::GenXorLong(RegLocation rl_dest, RegLocation rl_src1,
7492ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                            RegLocation rl_src2) {
750efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  LOG(FATAL) << "Unexpected use of genXoLong for Arm";
751efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
752efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
753e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee/*
754e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee * Generate array load
755e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee */
7561fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::GenArrayGet(int opt_flags, OpSize size, RegLocation rl_array,
757a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers                             RegLocation rl_index, RegLocation rl_dest, int scale) {
758e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  RegisterClass reg_class = oat_reg_class_by_size(size);
7592dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  int len_offset = mirror::Array::LengthOffset().Int32Value();
760e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  int data_offset;
761e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  RegLocation rl_result;
7624ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  bool constant_index = rl_index.is_const;
7631fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_array = LoadValue(rl_array, kCoreReg);
7644ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  if (!constant_index) {
7651fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_index = LoadValue(rl_index, kCoreReg);
7664ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  }
767e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee
768e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  if (rl_dest.wide) {
7692dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers    data_offset = mirror::Array::DataOffset(sizeof(int64_t)).Int32Value();
770e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  } else {
7712dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers    data_offset = mirror::Array::DataOffset(sizeof(int32_t)).Int32Value();
772e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  }
773e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee
7744ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  // If index is constant, just fold it into the data offset
7754ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  if (constant_index) {
7761fd3346740dfb7f47be9922312b68a4227fada96buzbee    data_offset += mir_graph_->ConstantValue(rl_index) << scale;
7774ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  }
7784ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
779e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  /* null object? */
7801fd3346740dfb7f47be9922312b68a4227fada96buzbee  GenNullCheck(rl_array.s_reg_low, rl_array.low_reg, opt_flags);
781e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee
782e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  bool needs_range_check = (!(opt_flags & MIR_IGNORE_RANGE_CHECK));
783e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  int reg_len = INVALID_REG;
784e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  if (needs_range_check) {
7851fd3346740dfb7f47be9922312b68a4227fada96buzbee    reg_len = AllocTemp();
786e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    /* Get len */
7871fd3346740dfb7f47be9922312b68a4227fada96buzbee    LoadWordDisp(rl_array.low_reg, len_offset, reg_len);
788e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  }
7894ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  if (rl_dest.wide || rl_dest.fp || constant_index) {
7904ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    int reg_ptr;
7914ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    if (constant_index) {
7924ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      reg_ptr = rl_array.low_reg;  // NOTE: must not alter reg_ptr in constant case.
7934ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    } else {
7944ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      // No special indexed operation, lea + load w/ displacement
7951fd3346740dfb7f47be9922312b68a4227fada96buzbee      reg_ptr = AllocTemp();
7961fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpRegRegRegShift(kOpAdd, reg_ptr, rl_array.low_reg, rl_index.low_reg,
7974ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee                       EncodeShift(kArmLsl, scale));
7981fd3346740dfb7f47be9922312b68a4227fada96buzbee      FreeTemp(rl_index.low_reg);
7994ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    }
8001fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_result = EvalLoc(rl_dest, reg_class, true);
801e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee
802e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    if (needs_range_check) {
8034ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      if (constant_index) {
8041fd3346740dfb7f47be9922312b68a4227fada96buzbee        GenImmedCheck(kCondLs, reg_len, mir_graph_->ConstantValue(rl_index), kThrowConstantArrayBounds);
8054ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      } else {
8061fd3346740dfb7f47be9922312b68a4227fada96buzbee        GenRegRegCheck(kCondLs, reg_len, rl_index.low_reg, kThrowArrayBounds);
8074ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      }
8081fd3346740dfb7f47be9922312b68a4227fada96buzbee      FreeTemp(reg_len);
809e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    }
810e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    if (rl_dest.wide) {
8111fd3346740dfb7f47be9922312b68a4227fada96buzbee      LoadBaseDispWide(reg_ptr, data_offset, rl_result.low_reg, rl_result.high_reg, INVALID_SREG);
8124ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      if (!constant_index) {
8131fd3346740dfb7f47be9922312b68a4227fada96buzbee        FreeTemp(reg_ptr);
8144ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      }
8151fd3346740dfb7f47be9922312b68a4227fada96buzbee      StoreValueWide(rl_dest, rl_result);
816e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    } else {
8171fd3346740dfb7f47be9922312b68a4227fada96buzbee      LoadBaseDisp(reg_ptr, data_offset, rl_result.low_reg, size, INVALID_SREG);
8184ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      if (!constant_index) {
8191fd3346740dfb7f47be9922312b68a4227fada96buzbee        FreeTemp(reg_ptr);
8204ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      }
8211fd3346740dfb7f47be9922312b68a4227fada96buzbee      StoreValue(rl_dest, rl_result);
822e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    }
823e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  } else {
824e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    // Offset base, then use indexed load
8251fd3346740dfb7f47be9922312b68a4227fada96buzbee    int reg_ptr = AllocTemp();
8261fd3346740dfb7f47be9922312b68a4227fada96buzbee    OpRegRegImm(kOpAdd, reg_ptr, rl_array.low_reg, data_offset);
8271fd3346740dfb7f47be9922312b68a4227fada96buzbee    FreeTemp(rl_array.low_reg);
8281fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_result = EvalLoc(rl_dest, reg_class, true);
829e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee
830e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    if (needs_range_check) {
831e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee      // TODO: change kCondCS to a more meaningful name, is the sense of
832e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee      // carry-set/clear flipped?
8331fd3346740dfb7f47be9922312b68a4227fada96buzbee      GenRegRegCheck(kCondCs, rl_index.low_reg, reg_len, kThrowArrayBounds);
8341fd3346740dfb7f47be9922312b68a4227fada96buzbee      FreeTemp(reg_len);
835e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    }
8361fd3346740dfb7f47be9922312b68a4227fada96buzbee    LoadBaseIndexed(reg_ptr, rl_index.low_reg, rl_result.low_reg, scale, size);
8371fd3346740dfb7f47be9922312b68a4227fada96buzbee    FreeTemp(reg_ptr);
8381fd3346740dfb7f47be9922312b68a4227fada96buzbee    StoreValue(rl_dest, rl_result);
839e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  }
840e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee}
841e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee
842e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee/*
843e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee * Generate array store
844e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee *
845e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee */
8461fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::GenArrayPut(int opt_flags, OpSize size, RegLocation rl_array,
847a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers                             RegLocation rl_index, RegLocation rl_src, int scale, bool card_mark) {
848e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  RegisterClass reg_class = oat_reg_class_by_size(size);
8492dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  int len_offset = mirror::Array::LengthOffset().Int32Value();
8504ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  bool constant_index = rl_index.is_const;
851e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee
852a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers  int data_offset;
853a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers  if (size == kLong || size == kDouble) {
8542dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers    data_offset = mirror::Array::DataOffset(sizeof(int64_t)).Int32Value();
855e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  } else {
8562dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers    data_offset = mirror::Array::DataOffset(sizeof(int32_t)).Int32Value();
857e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  }
858e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee
8594ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  // If index is constant, just fold it into the data offset.
8604ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  if (constant_index) {
8611fd3346740dfb7f47be9922312b68a4227fada96buzbee    data_offset += mir_graph_->ConstantValue(rl_index) << scale;
8624ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  }
8634ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
8641fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_array = LoadValue(rl_array, kCoreReg);
8654ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  if (!constant_index) {
8661fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_index = LoadValue(rl_index, kCoreReg);
8674ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  }
8684ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
8694ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  int reg_ptr;
8704ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  if (constant_index) {
8714ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    reg_ptr = rl_array.low_reg;
8721fd3346740dfb7f47be9922312b68a4227fada96buzbee  } else if (IsTemp(rl_array.low_reg)) {
8731fd3346740dfb7f47be9922312b68a4227fada96buzbee    Clobber(rl_array.low_reg);
874e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    reg_ptr = rl_array.low_reg;
875e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  } else {
8761fd3346740dfb7f47be9922312b68a4227fada96buzbee    reg_ptr = AllocTemp();
877e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  }
878e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee
879e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  /* null object? */
8801fd3346740dfb7f47be9922312b68a4227fada96buzbee  GenNullCheck(rl_array.s_reg_low, rl_array.low_reg, opt_flags);
881e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee
882e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  bool needs_range_check = (!(opt_flags & MIR_IGNORE_RANGE_CHECK));
883e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  int reg_len = INVALID_REG;
884e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  if (needs_range_check) {
8851fd3346740dfb7f47be9922312b68a4227fada96buzbee    reg_len = AllocTemp();
8867934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom    // NOTE: max live temps(4) here.
887e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    /* Get len */
8881fd3346740dfb7f47be9922312b68a4227fada96buzbee    LoadWordDisp(rl_array.low_reg, len_offset, reg_len);
889e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  }
890e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  /* at this point, reg_ptr points to array, 2 live temps */
8914ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  if (rl_src.wide || rl_src.fp || constant_index) {
892e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    if (rl_src.wide) {
8931fd3346740dfb7f47be9922312b68a4227fada96buzbee      rl_src = LoadValueWide(rl_src, reg_class);
894e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    } else {
8951fd3346740dfb7f47be9922312b68a4227fada96buzbee      rl_src = LoadValue(rl_src, reg_class);
896e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    }
8974ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    if (!constant_index) {
8981fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpRegRegRegShift(kOpAdd, reg_ptr, rl_array.low_reg, rl_index.low_reg,
8994ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee                       EncodeShift(kArmLsl, scale));
9004ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    }
901e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    if (needs_range_check) {
9024ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      if (constant_index) {
9031fd3346740dfb7f47be9922312b68a4227fada96buzbee        GenImmedCheck(kCondLs, reg_len, mir_graph_->ConstantValue(rl_index), kThrowConstantArrayBounds);
9044ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      } else {
9051fd3346740dfb7f47be9922312b68a4227fada96buzbee        GenRegRegCheck(kCondLs, reg_len, rl_index.low_reg, kThrowArrayBounds);
9064ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      }
9071fd3346740dfb7f47be9922312b68a4227fada96buzbee      FreeTemp(reg_len);
908e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    }
9094ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
910e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    if (rl_src.wide) {
9111fd3346740dfb7f47be9922312b68a4227fada96buzbee      StoreBaseDispWide(reg_ptr, data_offset, rl_src.low_reg, rl_src.high_reg);
912e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    } else {
9131fd3346740dfb7f47be9922312b68a4227fada96buzbee      StoreBaseDisp(reg_ptr, data_offset, rl_src.low_reg, size);
914e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    }
915e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  } else {
916e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    /* reg_ptr -> array data */
9171fd3346740dfb7f47be9922312b68a4227fada96buzbee    OpRegRegImm(kOpAdd, reg_ptr, rl_array.low_reg, data_offset);
9181fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src = LoadValue(rl_src, reg_class);
919e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    if (needs_range_check) {
9201fd3346740dfb7f47be9922312b68a4227fada96buzbee      GenRegRegCheck(kCondCs, rl_index.low_reg, reg_len, kThrowArrayBounds);
9211fd3346740dfb7f47be9922312b68a4227fada96buzbee      FreeTemp(reg_len);
922e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    }
9231fd3346740dfb7f47be9922312b68a4227fada96buzbee    StoreBaseIndexed(reg_ptr, rl_index.low_reg, rl_src.low_reg,
924e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee                     scale, size);
925e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  }
9264ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  if (!constant_index) {
9271fd3346740dfb7f47be9922312b68a4227fada96buzbee    FreeTemp(reg_ptr);
9284ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  }
929a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers  if (card_mark) {
930a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers    MarkGCCard(rl_src.low_reg, rl_array.low_reg);
9316a791b26577a61fd14f4836c795d616869bd2957buzbee  }
932e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee}
933e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee
934a9a8254c920ce8e22210abfc16c9842ce0aea28fIan Rogers
9351fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::GenShiftImmOpLong(Instruction::Code opcode,
9362ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                                   RegLocation rl_dest, RegLocation rl_src, RegLocation rl_shift) {
9371fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src = LoadValueWide(rl_src, kCoreReg);
9384ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  // Per spec, we only care about low 6 bits of shift amount.
9391fd3346740dfb7f47be9922312b68a4227fada96buzbee  int shift_amount = mir_graph_->ConstantValue(rl_shift) & 0x3f;
9404ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  if (shift_amount == 0) {
9411fd3346740dfb7f47be9922312b68a4227fada96buzbee    StoreValueWide(rl_dest, rl_src);
942a5954be0aac5edd892fb31a209960543d00e4500buzbee    return;
9434ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  }
9441fd3346740dfb7f47be9922312b68a4227fada96buzbee  if (BadOverlap(rl_src, rl_dest)) {
9451fd3346740dfb7f47be9922312b68a4227fada96buzbee    GenShiftOpLong(opcode, rl_dest, rl_src, rl_shift);
946a5954be0aac5edd892fb31a209960543d00e4500buzbee    return;
9474ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  }
9481fd3346740dfb7f47be9922312b68a4227fada96buzbee  RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
949df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom  switch (opcode) {
9504ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::SHL_LONG:
9514ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::SHL_LONG_2ADDR:
9524ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      if (shift_amount == 1) {
9531fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegReg(kOpAdd, rl_result.low_reg, rl_src.low_reg, rl_src.low_reg);
9541fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegReg(kOpAdc, rl_result.high_reg, rl_src.high_reg, rl_src.high_reg);
9554ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      } else if (shift_amount == 32) {
9561fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegCopy(rl_result.high_reg, rl_src.low_reg);
9571fd3346740dfb7f47be9922312b68a4227fada96buzbee        LoadConstant(rl_result.low_reg, 0);
9584ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      } else if (shift_amount > 31) {
9591fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegImm(kOpLsl, rl_result.high_reg, rl_src.low_reg, shift_amount - 32);
9601fd3346740dfb7f47be9922312b68a4227fada96buzbee        LoadConstant(rl_result.low_reg, 0);
9614ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      } else {
9621fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegImm(kOpLsl, rl_result.high_reg, rl_src.high_reg, shift_amount);
9631fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegRegShift(kOpOr, rl_result.high_reg, rl_result.high_reg, rl_src.low_reg,
9644ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee                         EncodeShift(kArmLsr, 32 - shift_amount));
9651fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegImm(kOpLsl, rl_result.low_reg, rl_src.low_reg, shift_amount);
9664ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      }
9674ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      break;
9684ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::SHR_LONG:
9694ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::SHR_LONG_2ADDR:
9704ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      if (shift_amount == 32) {
9711fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegCopy(rl_result.low_reg, rl_src.high_reg);
9721fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegImm(kOpAsr, rl_result.high_reg, rl_src.high_reg, 31);
9734ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      } else if (shift_amount > 31) {
9741fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegImm(kOpAsr, rl_result.low_reg, rl_src.high_reg, shift_amount - 32);
9751fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegImm(kOpAsr, rl_result.high_reg, rl_src.high_reg, 31);
9764ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      } else {
9771fd3346740dfb7f47be9922312b68a4227fada96buzbee        int t_reg = AllocTemp();
9781fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegImm(kOpLsr, t_reg, rl_src.low_reg, shift_amount);
9791fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegRegShift(kOpOr, rl_result.low_reg, t_reg, rl_src.high_reg,
9804ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee                         EncodeShift(kArmLsl, 32 - shift_amount));
9811fd3346740dfb7f47be9922312b68a4227fada96buzbee        FreeTemp(t_reg);
9821fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegImm(kOpAsr, rl_result.high_reg, rl_src.high_reg, shift_amount);
9834ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      }
9844ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      break;
9854ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::USHR_LONG:
9864ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::USHR_LONG_2ADDR:
9874ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      if (shift_amount == 32) {
9881fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegCopy(rl_result.low_reg, rl_src.high_reg);
9891fd3346740dfb7f47be9922312b68a4227fada96buzbee        LoadConstant(rl_result.high_reg, 0);
9904ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      } else if (shift_amount > 31) {
9911fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegImm(kOpLsr, rl_result.low_reg, rl_src.high_reg, shift_amount - 32);
9921fd3346740dfb7f47be9922312b68a4227fada96buzbee        LoadConstant(rl_result.high_reg, 0);
9934ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      } else {
9941fd3346740dfb7f47be9922312b68a4227fada96buzbee        int t_reg = AllocTemp();
9951fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegImm(kOpLsr, t_reg, rl_src.low_reg, shift_amount);
9961fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegRegShift(kOpOr, rl_result.low_reg, t_reg, rl_src.high_reg,
9974ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee                         EncodeShift(kArmLsl, 32 - shift_amount));
9981fd3346740dfb7f47be9922312b68a4227fada96buzbee        FreeTemp(t_reg);
9991fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegImm(kOpLsr, rl_result.high_reg, rl_src.high_reg, shift_amount);
10004ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      }
10014ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      break;
10024ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    default:
10034ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      LOG(FATAL) << "Unexpected case";
10044ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  }
10051fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValueWide(rl_dest, rl_result);
10064ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee}
10074ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
10081fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::GenArithImmOpLong(Instruction::Code opcode,
10092ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                                   RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) {
10104ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  if ((opcode == Instruction::SUB_LONG_2ADDR) || (opcode == Instruction::SUB_LONG)) {
10114ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    if (!rl_src2.is_const) {
10124ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      // Don't bother with special handling for subtract from immediate.
10131fd3346740dfb7f47be9922312b68a4227fada96buzbee      GenArithOpLong(opcode, rl_dest, rl_src1, rl_src2);
1014a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
10154ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    }
10164ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  } else {
10174ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    // Normalize
10184ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    if (!rl_src2.is_const) {
10194ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      DCHECK(rl_src1.is_const);
10204ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      RegLocation rl_temp = rl_src1;
10214ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      rl_src1 = rl_src2;
10224ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      rl_src2 = rl_temp;
10234ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    }
10244ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  }
10251fd3346740dfb7f47be9922312b68a4227fada96buzbee  if (BadOverlap(rl_src1, rl_dest)) {
10261fd3346740dfb7f47be9922312b68a4227fada96buzbee    GenArithOpLong(opcode, rl_dest, rl_src1, rl_src2);
1027a5954be0aac5edd892fb31a209960543d00e4500buzbee    return;
10284ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  }
10294ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  DCHECK(rl_src2.is_const);
10301fd3346740dfb7f47be9922312b68a4227fada96buzbee  int64_t val = mir_graph_->ConstantValueWide(rl_src2);
10314ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  uint32_t val_lo = Low32Bits(val);
10324ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  uint32_t val_hi = High32Bits(val);
10334ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  int32_t mod_imm_lo = ModifiedImmediate(val_lo);
10344ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  int32_t mod_imm_hi = ModifiedImmediate(val_hi);
10354ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
10364ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  // Only a subset of add/sub immediate instructions set carry - so bail if we don't fit
1037df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom  switch (opcode) {
10384ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::ADD_LONG:
10394ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::ADD_LONG_2ADDR:
10404ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::SUB_LONG:
10414ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::SUB_LONG_2ADDR:
10424ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      if ((mod_imm_lo < 0) || (mod_imm_hi < 0)) {
10431fd3346740dfb7f47be9922312b68a4227fada96buzbee        GenArithOpLong(opcode, rl_dest, rl_src1, rl_src2);
1044a5954be0aac5edd892fb31a209960543d00e4500buzbee        return;
10454ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      }
10464ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      break;
10474ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    default:
10484ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      break;
10494ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  }
10501fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src1 = LoadValueWide(rl_src1, kCoreReg);
10511fd3346740dfb7f47be9922312b68a4227fada96buzbee  RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
10524ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  // NOTE: once we've done the EvalLoc on dest, we can no longer bail.
10534ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  switch (opcode) {
10544ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::ADD_LONG:
10554ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::ADD_LONG_2ADDR:
10561fd3346740dfb7f47be9922312b68a4227fada96buzbee      NewLIR3(kThumb2AddRRI8, rl_result.low_reg, rl_src1.low_reg, mod_imm_lo);
10571fd3346740dfb7f47be9922312b68a4227fada96buzbee      NewLIR3(kThumb2AdcRRI8, rl_result.high_reg, rl_src1.high_reg, mod_imm_hi);
10584ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      break;
10594ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::OR_LONG:
10604ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::OR_LONG_2ADDR:
10614ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      if ((val_lo != 0) || (rl_result.low_reg != rl_src1.low_reg)) {
10621fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegImm(kOpOr, rl_result.low_reg, rl_src1.low_reg, val_lo);
10634ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      }
10644ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      if ((val_hi != 0) || (rl_result.high_reg != rl_src1.high_reg)) {
10651fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegImm(kOpOr, rl_result.high_reg, rl_src1.high_reg, val_hi);
10664ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      }
10674ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      break;
10684ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::XOR_LONG:
10694ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::XOR_LONG_2ADDR:
10701fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpRegRegImm(kOpXor, rl_result.low_reg, rl_src1.low_reg, val_lo);
10711fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpRegRegImm(kOpXor, rl_result.high_reg, rl_src1.high_reg, val_hi);
10724ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      break;
10734ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::AND_LONG:
10744ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::AND_LONG_2ADDR:
10754ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      if ((val_lo != 0xffffffff) || (rl_result.low_reg != rl_src1.low_reg)) {
10761fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegImm(kOpAnd, rl_result.low_reg, rl_src1.low_reg, val_lo);
10774ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      }
10784ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      if ((val_hi != 0xffffffff) || (rl_result.high_reg != rl_src1.high_reg)) {
10791fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegImm(kOpAnd, rl_result.high_reg, rl_src1.high_reg, val_hi);
10804ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      }
10814ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      break;
10824ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::SUB_LONG_2ADDR:
10834ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::SUB_LONG:
10841fd3346740dfb7f47be9922312b68a4227fada96buzbee      NewLIR3(kThumb2SubRRI8, rl_result.low_reg, rl_src1.low_reg, mod_imm_lo);
10851fd3346740dfb7f47be9922312b68a4227fada96buzbee      NewLIR3(kThumb2SbcRRI8, rl_result.high_reg, rl_src1.high_reg, mod_imm_hi);
10864ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      break;
10874ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    default:
10884ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      LOG(FATAL) << "Unexpected opcode " << opcode;
10894ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  }
10901fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValueWide(rl_dest, rl_result);
10914ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee}
10924ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
1093efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}  // namespace art
1094