int_arm.cc revision df62950e7a32031b82360c407d46a37b94188fbb
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"
2233e9566255c426e7a2c8fca5b8a1b6a94a5d352cIan Rogers#include "mirror/array.h"
23641ce0371c2f0dc95d26be02d8366124c8b66653Brian Carlstrom#include "oat/runtime/oat_support_entrypoints.h"
24efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
25efc6369224b036a1fb77849f7ae65b3492c832c0buzbeenamespace art {
26efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
271fd3346740dfb7f47be9922312b68a4227fada96buzbeeLIR* ArmMir2Lir::OpCmpBranch(ConditionCode cond, int src1,
282ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom         int src2, LIR* target) {
291fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpRegReg(kOpCmp, src1, src2);
301fd3346740dfb7f47be9922312b68a4227fada96buzbee  return OpCondBranch(cond, target);
31efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
32efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
33efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/*
34efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Generate a Thumb2 IT instruction, which can nullify up to
35efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * four subsequent instructions based on a condition and its
36efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * inverse.  The condition applies to the first instruction, which
37efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * is executed if the condition is met.  The string "guide" consists
38efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * of 0 to 3 chars, and applies to the 2nd through 4th instruction.
39efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * A "T" means the instruction is executed if the condition is
40efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * met, and an "E" means the instruction is executed if the condition
41efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * is not met.
42efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */
432ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromLIR* ArmMir2Lir::OpIT(ConditionCode ccode, const char* guide) {
44efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  int mask;
45efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  int mask3 = 0;
46efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  int mask2 = 0;
47efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  int mask1 = 0;
4802031b185b4653e6c72e21f7a51238b903f6d638buzbee  ArmConditionCode code = ArmConditionEncoding(ccode);
4902031b185b4653e6c72e21f7a51238b903f6d638buzbee  int cond_bit = code & 1;
5002031b185b4653e6c72e21f7a51238b903f6d638buzbee  int alt_bit = cond_bit ^ 1;
51efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
52efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  //Note: case fallthroughs intentional
53efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  switch (strlen(guide)) {
54efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    case 3:
55fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      mask1 = (guide[2] == 'T') ? cond_bit : alt_bit;
56efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    case 2:
57fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      mask2 = (guide[1] == 'T') ? cond_bit : alt_bit;
58efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    case 1:
59fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      mask3 = (guide[0] == 'T') ? cond_bit : alt_bit;
60efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      break;
61efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    case 0:
62efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      break;
63efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    default:
6452a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee      LOG(FATAL) << "OAT: bad case in OpIT";
65efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
66efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  mask = (mask3 << 3) | (mask2 << 2) | (mask1 << 1) |
67efc6369224b036a1fb77849f7ae65b3492c832c0buzbee       (1 << (3 - strlen(guide)));
681fd3346740dfb7f47be9922312b68a4227fada96buzbee  return NewLIR2(kThumb2It, code, mask);
69efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
70efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
71efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/*
72efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * 64-bit 3way compare function.
73efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *     mov   rX, #-1
74efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *     cmp   op1hi, op2hi
75efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *     blt   done
76efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *     bgt   flip
77efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *     sub   rX, op1lo, op2lo (treat as unsigned)
78efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *     beq   done
79efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *     ite   hi
80efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *     mov(hi)   rX, #-1
81efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *     mov(!hi)  rX, #1
82efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * flip:
83efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *     neg   rX
84efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * done:
85efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */
861fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::GenCmpLong(RegLocation rl_dest, RegLocation rl_src1,
872ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                            RegLocation rl_src2) {
88efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  LIR* target1;
89efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  LIR* target2;
901fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src1 = LoadValueWide(rl_src1, kCoreReg);
911fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src2 = LoadValueWide(rl_src2, kCoreReg);
921fd3346740dfb7f47be9922312b68a4227fada96buzbee  int t_reg = AllocTemp();
931fd3346740dfb7f47be9922312b68a4227fada96buzbee  LoadConstant(t_reg, -1);
941fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpRegReg(kOpCmp, rl_src1.high_reg, rl_src2.high_reg);
951fd3346740dfb7f47be9922312b68a4227fada96buzbee  LIR* branch1 = OpCondBranch(kCondLt, NULL);
961fd3346740dfb7f47be9922312b68a4227fada96buzbee  LIR* branch2 = OpCondBranch(kCondGt, NULL);
971fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpRegRegReg(kOpSub, t_reg, rl_src1.low_reg, rl_src2.low_reg);
981fd3346740dfb7f47be9922312b68a4227fada96buzbee  LIR* branch3 = OpCondBranch(kCondEq, NULL);
991fd3346740dfb7f47be9922312b68a4227fada96buzbee
1001fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpIT(kCondHi, "E");
1011fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR2(kThumb2MovImmShift, t_reg, ModifiedImmediate(-1));
1021fd3346740dfb7f47be9922312b68a4227fada96buzbee  LoadConstant(t_reg, 1);
1031fd3346740dfb7f47be9922312b68a4227fada96buzbee  GenBarrier();
1041fd3346740dfb7f47be9922312b68a4227fada96buzbee
1051fd3346740dfb7f47be9922312b68a4227fada96buzbee  target2 = NewLIR0(kPseudoTargetLabel);
1061fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpRegReg(kOpNeg, t_reg, t_reg);
1071fd3346740dfb7f47be9922312b68a4227fada96buzbee
1081fd3346740dfb7f47be9922312b68a4227fada96buzbee  target1 = NewLIR0(kPseudoTargetLabel);
109fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee
110fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_temp = LocCReturn(); // Just using as template, will change
111fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  rl_temp.low_reg = t_reg;
1121fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValue(rl_dest, rl_temp);
1131fd3346740dfb7f47be9922312b68a4227fada96buzbee  FreeTemp(t_reg);
114efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
115cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee  branch1->target = target1;
116cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee  branch2->target = target2;
117efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  branch3->target = branch1->target;
118efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
119efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
1201fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::GenFusedLongCmpImmBranch(BasicBlock* bb, RegLocation rl_src1,
1212ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                                          int64_t val, ConditionCode ccode) {
1224ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  int32_t val_lo = Low32Bits(val);
1234ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  int32_t val_hi = High32Bits(val);
1244ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  DCHECK(ModifiedImmediate(val_lo) >= 0);
1254ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  DCHECK(ModifiedImmediate(val_hi) >= 0);
1261fd3346740dfb7f47be9922312b68a4227fada96buzbee  LIR* taken = &block_label_list_[bb->taken->id];
1271fd3346740dfb7f47be9922312b68a4227fada96buzbee  LIR* not_taken = &block_label_list_[bb->fall_through->id];
1281fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src1 = LoadValueWide(rl_src1, kCoreReg);
1294ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  int32_t low_reg = rl_src1.low_reg;
1304ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  int32_t high_reg = rl_src1.high_reg;
1314ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
132df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom  switch (ccode) {
1334ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case kCondEq:
1344ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case kCondNe:
135c7d1f91e024c5c560810376340aecb39d4e47fdcbuzbee      LIR* target;
136c7d1f91e024c5c560810376340aecb39d4e47fdcbuzbee      ConditionCode condition;
137c7d1f91e024c5c560810376340aecb39d4e47fdcbuzbee      if (ccode == kCondEq) {
138c7d1f91e024c5c560810376340aecb39d4e47fdcbuzbee        target = not_taken;
139c7d1f91e024c5c560810376340aecb39d4e47fdcbuzbee        condition = kCondEq;
140c7d1f91e024c5c560810376340aecb39d4e47fdcbuzbee      } else {
141c7d1f91e024c5c560810376340aecb39d4e47fdcbuzbee        target = taken;
142c7d1f91e024c5c560810376340aecb39d4e47fdcbuzbee        condition = kCondNe;
143c7d1f91e024c5c560810376340aecb39d4e47fdcbuzbee      }
144c7d1f91e024c5c560810376340aecb39d4e47fdcbuzbee      if (val == 0) {
1451fd3346740dfb7f47be9922312b68a4227fada96buzbee        int t_reg = AllocTemp();
1461fd3346740dfb7f47be9922312b68a4227fada96buzbee        NewLIR4(kThumb2OrrRRRs, t_reg, low_reg, high_reg, 0);
1471fd3346740dfb7f47be9922312b68a4227fada96buzbee        FreeTemp(t_reg);
1481fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpCondBranch(condition, taken);
149c7d1f91e024c5c560810376340aecb39d4e47fdcbuzbee        return;
150c7d1f91e024c5c560810376340aecb39d4e47fdcbuzbee      }
1511fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCmpImmBranch(kCondNe, high_reg, val_hi, target);
1524ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      break;
1534ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case kCondLt:
1541fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCmpImmBranch(kCondLt, high_reg, val_hi, taken);
1551fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCmpImmBranch(kCondGt, high_reg, val_hi, not_taken);
1564ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      ccode = kCondCc;
1574ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      break;
1584ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case kCondLe:
1591fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCmpImmBranch(kCondLt, high_reg, val_hi, taken);
1601fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCmpImmBranch(kCondGt, high_reg, val_hi, not_taken);
1614ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      ccode = kCondLs;
1624ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      break;
1634ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case kCondGt:
1641fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCmpImmBranch(kCondGt, high_reg, val_hi, taken);
1651fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCmpImmBranch(kCondLt, high_reg, val_hi, not_taken);
1664ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      ccode = kCondHi;
1674ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      break;
1684ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case kCondGe:
1691fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCmpImmBranch(kCondGt, high_reg, val_hi, taken);
1701fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCmpImmBranch(kCondLt, high_reg, val_hi, not_taken);
1714ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      ccode = kCondCs;
1724ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      break;
1734ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    default:
1744ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      LOG(FATAL) << "Unexpected ccode: " << ccode;
1754ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  }
1761fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpCmpImmBranch(ccode, low_reg, val_lo, taken);
1774ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee}
1784ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
1792ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid ArmMir2Lir::GenSelect(BasicBlock* bb, MIR* mir) {
180f662a7c625b1067f61b23c04459eba9b12bc027ebuzbee  RegLocation rl_result;
1811fd3346740dfb7f47be9922312b68a4227fada96buzbee  RegLocation rl_src = mir_graph_->GetSrc(mir, 0);
182a0e8bbd2f684f4187ef3d5835a73da8e8ce6dac8buzbee  // Temporary debugging code
183a0e8bbd2f684f4187ef3d5835a73da8e8ce6dac8buzbee  int dest_sreg = mir->ssa_rep->defs[0];
1841fd3346740dfb7f47be9922312b68a4227fada96buzbee  if ((dest_sreg < 0) || (dest_sreg >= mir_graph_->GetNumSSARegs())) {
185a0e8bbd2f684f4187ef3d5835a73da8e8ce6dac8buzbee    LOG(INFO) << "Bad target sreg: " << dest_sreg << ", in "
186b1eba213afaf7fa6445de863ddc9680ab99762eaBrian Carlstrom              << PrettyMethod(cu_->method_idx, *cu_->dex_file);
187a0e8bbd2f684f4187ef3d5835a73da8e8ce6dac8buzbee    LOG(INFO) << "at dex offset 0x" << std::hex << mir->offset;
1881fd3346740dfb7f47be9922312b68a4227fada96buzbee    LOG(INFO) << "vreg = " << mir_graph_->SRegToVReg(dest_sreg);
189a0e8bbd2f684f4187ef3d5835a73da8e8ce6dac8buzbee    LOG(INFO) << "num uses = " << mir->ssa_rep->num_uses;
190a0e8bbd2f684f4187ef3d5835a73da8e8ce6dac8buzbee    if (mir->ssa_rep->num_uses == 1) {
191a0e8bbd2f684f4187ef3d5835a73da8e8ce6dac8buzbee      LOG(INFO) << "CONST case, vals = " << mir->dalvikInsn.vB << ", " << mir->dalvikInsn.vC;
192a0e8bbd2f684f4187ef3d5835a73da8e8ce6dac8buzbee    } else {
193a0e8bbd2f684f4187ef3d5835a73da8e8ce6dac8buzbee      LOG(INFO) << "MOVE case, operands = " << mir->ssa_rep->uses[1] << ", "
194a0e8bbd2f684f4187ef3d5835a73da8e8ce6dac8buzbee                << mir->ssa_rep->uses[2];
195a0e8bbd2f684f4187ef3d5835a73da8e8ce6dac8buzbee    }
196a0e8bbd2f684f4187ef3d5835a73da8e8ce6dac8buzbee    CHECK(false) << "Invalid target sreg on Select.";
197a0e8bbd2f684f4187ef3d5835a73da8e8ce6dac8buzbee  }
198a0e8bbd2f684f4187ef3d5835a73da8e8ce6dac8buzbee  // End temporary debugging code
1991fd3346740dfb7f47be9922312b68a4227fada96buzbee  RegLocation rl_dest = mir_graph_->GetDest(mir);
2001fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src = LoadValue(rl_src, kCoreReg);
201f662a7c625b1067f61b23c04459eba9b12bc027ebuzbee  if (mir->ssa_rep->num_uses == 1) {
202f662a7c625b1067f61b23c04459eba9b12bc027ebuzbee    // CONST case
203f662a7c625b1067f61b23c04459eba9b12bc027ebuzbee    int true_val = mir->dalvikInsn.vB;
204f662a7c625b1067f61b23c04459eba9b12bc027ebuzbee    int false_val = mir->dalvikInsn.vC;
2051fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_result = EvalLoc(rl_dest, kCoreReg, true);
206f662a7c625b1067f61b23c04459eba9b12bc027ebuzbee    if ((true_val == 1) && (false_val == 0)) {
2071fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpRegRegImm(kOpRsub, rl_result.low_reg, rl_src.low_reg, 1);
2081fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpIT(kCondCc, "");
2091fd3346740dfb7f47be9922312b68a4227fada96buzbee      LoadConstant(rl_result.low_reg, 0);
2101fd3346740dfb7f47be9922312b68a4227fada96buzbee      GenBarrier(); // Add a scheduling barrier to keep the IT shadow intact
211f662a7c625b1067f61b23c04459eba9b12bc027ebuzbee    } else if (InexpensiveConstantInt(true_val) && InexpensiveConstantInt(false_val)) {
2121fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpRegImm(kOpCmp, rl_src.low_reg, 0);
2131fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpIT(kCondEq, "E");
2141fd3346740dfb7f47be9922312b68a4227fada96buzbee      LoadConstant(rl_result.low_reg, true_val);
2151fd3346740dfb7f47be9922312b68a4227fada96buzbee      LoadConstant(rl_result.low_reg, false_val);
2161fd3346740dfb7f47be9922312b68a4227fada96buzbee      GenBarrier(); // Add a scheduling barrier to keep the IT shadow intact
217f662a7c625b1067f61b23c04459eba9b12bc027ebuzbee    } else {
218f662a7c625b1067f61b23c04459eba9b12bc027ebuzbee      // Unlikely case - could be tuned.
2191fd3346740dfb7f47be9922312b68a4227fada96buzbee      int t_reg1 = AllocTemp();
2201fd3346740dfb7f47be9922312b68a4227fada96buzbee      int t_reg2 = AllocTemp();
2211fd3346740dfb7f47be9922312b68a4227fada96buzbee      LoadConstant(t_reg1, true_val);
2221fd3346740dfb7f47be9922312b68a4227fada96buzbee      LoadConstant(t_reg2, false_val);
2231fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpRegImm(kOpCmp, rl_src.low_reg, 0);
2241fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpIT(kCondEq, "E");
2251fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpRegCopy(rl_result.low_reg, t_reg1);
2261fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpRegCopy(rl_result.low_reg, t_reg2);
2271fd3346740dfb7f47be9922312b68a4227fada96buzbee      GenBarrier(); // Add a scheduling barrier to keep the IT shadow intact
228f662a7c625b1067f61b23c04459eba9b12bc027ebuzbee    }
229f662a7c625b1067f61b23c04459eba9b12bc027ebuzbee  } else {
230f662a7c625b1067f61b23c04459eba9b12bc027ebuzbee    // MOVE case
2311fd3346740dfb7f47be9922312b68a4227fada96buzbee    RegLocation rl_true = mir_graph_->reg_location_[mir->ssa_rep->uses[1]];
2321fd3346740dfb7f47be9922312b68a4227fada96buzbee    RegLocation rl_false = mir_graph_->reg_location_[mir->ssa_rep->uses[2]];
2331fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_true = LoadValue(rl_true, kCoreReg);
2341fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_false = LoadValue(rl_false, kCoreReg);
2351fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_result = EvalLoc(rl_dest, kCoreReg, true);
2361fd3346740dfb7f47be9922312b68a4227fada96buzbee    OpRegImm(kOpCmp, rl_src.low_reg, 0);
2371fd3346740dfb7f47be9922312b68a4227fada96buzbee    OpIT(kCondEq, "E");
2381fd3346740dfb7f47be9922312b68a4227fada96buzbee    LIR* l1 = OpRegCopy(rl_result.low_reg, rl_true.low_reg);
239f662a7c625b1067f61b23c04459eba9b12bc027ebuzbee    l1->flags.is_nop = false;  // Make sure this instruction isn't optimized away
2401fd3346740dfb7f47be9922312b68a4227fada96buzbee    LIR* l2 = OpRegCopy(rl_result.low_reg, rl_false.low_reg);
241f662a7c625b1067f61b23c04459eba9b12bc027ebuzbee    l2->flags.is_nop = false;  // Make sure this instruction isn't optimized away
2421fd3346740dfb7f47be9922312b68a4227fada96buzbee    GenBarrier(); // Add a scheduling barrier to keep the IT shadow intact
243f662a7c625b1067f61b23c04459eba9b12bc027ebuzbee  }
2441fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValue(rl_dest, rl_result);
245f662a7c625b1067f61b23c04459eba9b12bc027ebuzbee}
2464ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
2472ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid ArmMir2Lir::GenFusedLongCmpBranch(BasicBlock* bb, MIR* mir) {
2481fd3346740dfb7f47be9922312b68a4227fada96buzbee  RegLocation rl_src1 = mir_graph_->GetSrcWide(mir, 0);
2491fd3346740dfb7f47be9922312b68a4227fada96buzbee  RegLocation rl_src2 = mir_graph_->GetSrcWide(mir, 2);
2504ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  // Normalize such that if either operand is constant, src2 will be constant.
2514ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  ConditionCode ccode = static_cast<ConditionCode>(mir->dalvikInsn.arg[0]);
2524ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  if (rl_src1.is_const) {
2534ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    RegLocation rl_temp = rl_src1;
2544ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    rl_src1 = rl_src2;
2554ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    rl_src2 = rl_temp;
2564ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    ccode = FlipComparisonOrder(ccode);
2574ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  }
2584ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  if (rl_src2.is_const) {
2591fd3346740dfb7f47be9922312b68a4227fada96buzbee    RegLocation rl_temp = UpdateLocWide(rl_src2);
2604ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    // Do special compare/branch against simple const operand if not already in registers.
2611fd3346740dfb7f47be9922312b68a4227fada96buzbee    int64_t val = mir_graph_->ConstantValueWide(rl_src2);
2624ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    if ((rl_temp.location != kLocPhysReg) &&
2634ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee        ((ModifiedImmediate(Low32Bits(val)) >= 0) && (ModifiedImmediate(High32Bits(val)) >= 0))) {
2641fd3346740dfb7f47be9922312b68a4227fada96buzbee      GenFusedLongCmpImmBranch(bb, rl_src1, val, ccode);
2654ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      return;
2664ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    }
2674ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  }
2681fd3346740dfb7f47be9922312b68a4227fada96buzbee  LIR* taken = &block_label_list_[bb->taken->id];
2691fd3346740dfb7f47be9922312b68a4227fada96buzbee  LIR* not_taken = &block_label_list_[bb->fall_through->id];
2701fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src1 = LoadValueWide(rl_src1, kCoreReg);
2711fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src2 = LoadValueWide(rl_src2, kCoreReg);
2721fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpRegReg(kOpCmp, rl_src1.high_reg, rl_src2.high_reg);
273df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom  switch (ccode) {
274efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    case kCondEq:
2751fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCondBranch(kCondNe, not_taken);
276efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      break;
277efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    case kCondNe:
2781fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCondBranch(kCondNe, taken);
279efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      break;
280efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    case kCondLt:
2811fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCondBranch(kCondLt, taken);
2821fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCondBranch(kCondGt, not_taken);
283efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      ccode = kCondCc;
284efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      break;
285efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    case kCondLe:
2861fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCondBranch(kCondLt, taken);
2871fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCondBranch(kCondGt, not_taken);
288efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      ccode = kCondLs;
289efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      break;
290efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    case kCondGt:
2911fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCondBranch(kCondGt, taken);
2921fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCondBranch(kCondLt, not_taken);
293efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      ccode = kCondHi;
294efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      break;
295efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    case kCondGe:
2961fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCondBranch(kCondGt, taken);
2971fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCondBranch(kCondLt, not_taken);
298efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      ccode = kCondCs;
299efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      break;
300efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    default:
301cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      LOG(FATAL) << "Unexpected ccode: " << ccode;
302efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
3031fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpRegReg(kOpCmp, rl_src1.low_reg, rl_src2.low_reg);
3041fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpCondBranch(ccode, taken);
305efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
306efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
307efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/*
308efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Generate a register comparison to an immediate and branch.  Caller
309efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * is responsible for setting branch target field.
310efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */
3111fd3346740dfb7f47be9922312b68a4227fada96buzbeeLIR* ArmMir2Lir::OpCmpImmBranch(ConditionCode cond, int reg, int check_value,
3122ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                                LIR* target) {
313efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  LIR* branch;
314fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  int mod_imm;
315fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  ArmConditionCode arm_cond = ArmConditionEncoding(cond);
316fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if ((ARM_LOWREG(reg)) && (check_value == 0) &&
317fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee     ((arm_cond == kArmCondEq) || (arm_cond == kArmCondNe))) {
3181fd3346740dfb7f47be9922312b68a4227fada96buzbee    branch = NewLIR2((arm_cond == kArmCondEq) ? kThumb2Cbz : kThumb2Cbnz,
319efc6369224b036a1fb77849f7ae65b3492c832c0buzbee                     reg, 0);
320efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  } else {
321fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    mod_imm = ModifiedImmediate(check_value);
322fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (ARM_LOWREG(reg) && ((check_value & 0xff) == check_value)) {
3231fd3346740dfb7f47be9922312b68a4227fada96buzbee      NewLIR2(kThumbCmpRI8, reg, check_value);
324fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    } else if (mod_imm >= 0) {
3251fd3346740dfb7f47be9922312b68a4227fada96buzbee      NewLIR2(kThumb2CmpRI12, reg, mod_imm);
326efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    } else {
3271fd3346740dfb7f47be9922312b68a4227fada96buzbee      int t_reg = AllocTemp();
3281fd3346740dfb7f47be9922312b68a4227fada96buzbee      LoadConstant(t_reg, check_value);
3291fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpRegReg(kOpCmp, reg, t_reg);
330efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    }
3311fd3346740dfb7f47be9922312b68a4227fada96buzbee    branch = NewLIR2(kThumbBCond, 0, arm_cond);
332efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
333efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  branch->target = target;
334efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return branch;
335efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
33602031b185b4653e6c72e21f7a51238b903f6d638buzbee
3372ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromLIR* ArmMir2Lir::OpRegCopyNoInsert(int r_dest, int r_src) {
338efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  LIR* res;
339efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  int opcode;
340fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (ARM_FPREG(r_dest) || ARM_FPREG(r_src))
3411fd3346740dfb7f47be9922312b68a4227fada96buzbee    return OpFpRegCopy(r_dest, r_src);
342fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (ARM_LOWREG(r_dest) && ARM_LOWREG(r_src))
343efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    opcode = kThumbMovRR;
344fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  else if (!ARM_LOWREG(r_dest) && !ARM_LOWREG(r_src))
345efc6369224b036a1fb77849f7ae65b3492c832c0buzbee     opcode = kThumbMovRR_H2H;
346fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  else if (ARM_LOWREG(r_dest))
347efc6369224b036a1fb77849f7ae65b3492c832c0buzbee     opcode = kThumbMovRR_H2L;
348efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  else
349efc6369224b036a1fb77849f7ae65b3492c832c0buzbee     opcode = kThumbMovRR_L2H;
3501fd3346740dfb7f47be9922312b68a4227fada96buzbee  res = RawLIR(current_dalvik_offset_, opcode, r_dest, r_src);
3511fd3346740dfb7f47be9922312b68a4227fada96buzbee  if (!(cu_->disable_opt & (1 << kSafeOptimizations)) && r_dest == r_src) {
352fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    res->flags.is_nop = true;
353efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
354efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return res;
355efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
356efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
3572ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromLIR* ArmMir2Lir::OpRegCopy(int r_dest, int r_src) {
3581fd3346740dfb7f47be9922312b68a4227fada96buzbee  LIR* res = OpRegCopyNoInsert(r_dest, r_src);
3591fd3346740dfb7f47be9922312b68a4227fada96buzbee  AppendLIR(res);
360efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return res;
361efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
362efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
3631fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::OpRegCopyWide(int dest_lo, int dest_hi, int src_lo,
3642ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                               int src_hi) {
365fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  bool dest_fp = ARM_FPREG(dest_lo) && ARM_FPREG(dest_hi);
366fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  bool src_fp = ARM_FPREG(src_lo) && ARM_FPREG(src_hi);
367fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  DCHECK_EQ(ARM_FPREG(src_lo), ARM_FPREG(src_hi));
368fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  DCHECK_EQ(ARM_FPREG(dest_lo), ARM_FPREG(dest_hi));
369fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (dest_fp) {
370fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (src_fp) {
3711fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpRegCopy(S2d(dest_lo, dest_hi), S2d(src_lo, src_hi));
372efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    } else {
3731fd3346740dfb7f47be9922312b68a4227fada96buzbee      NewLIR3(kThumb2Fmdrr, S2d(dest_lo, dest_hi), src_lo, src_hi);
374efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    }
375efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  } else {
376fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (src_fp) {
3771fd3346740dfb7f47be9922312b68a4227fada96buzbee      NewLIR3(kThumb2Fmrrd, dest_lo, dest_hi, S2d(src_lo, src_hi));
378efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    } else {
379efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      // Handle overlap
380fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (src_hi == dest_lo) {
3811fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegCopy(dest_hi, src_hi);
3821fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegCopy(dest_lo, src_lo);
383efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      } else {
3841fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegCopy(dest_lo, src_lo);
3851fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegCopy(dest_hi, src_hi);
386efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      }
387efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    }
388efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
389efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
390efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
391efc6369224b036a1fb77849f7ae65b3492c832c0buzbee// Table of magic divisors
392efc6369224b036a1fb77849f7ae65b3492c832c0buzbeestruct MagicTable {
393efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  uint32_t magic;
394efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  uint32_t shift;
395efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  DividePattern pattern;
396efc6369224b036a1fb77849f7ae65b3492c832c0buzbee};
397efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
398fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeestatic const MagicTable magic_table[] = {
399efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0, 0, DivideNone},        // 0
400efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0, 0, DivideNone},        // 1
401efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0, 0, DivideNone},        // 2
402efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0x55555556, 0, Divide3},  // 3
403efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0, 0, DivideNone},        // 4
404efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0x66666667, 1, Divide5},  // 5
405efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0x2AAAAAAB, 0, Divide3},  // 6
406efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0x92492493, 2, Divide7},  // 7
407efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0, 0, DivideNone},        // 8
408efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0x38E38E39, 1, Divide5},  // 9
409efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0x66666667, 2, Divide5},  // 10
410efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0x2E8BA2E9, 1, Divide5},  // 11
411efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0x2AAAAAAB, 1, Divide5},  // 12
412efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0x4EC4EC4F, 2, Divide5},  // 13
413efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0x92492493, 3, Divide7},  // 14
414efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0x88888889, 3, Divide7},  // 15
415efc6369224b036a1fb77849f7ae65b3492c832c0buzbee};
416efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
417efc6369224b036a1fb77849f7ae65b3492c832c0buzbee// Integer division by constant via reciprocal multiply (Hacker's Delight, 10-4)
4181fd3346740dfb7f47be9922312b68a4227fada96buzbeebool ArmMir2Lir::SmallLiteralDivide(Instruction::Code dalvik_opcode,
4192ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                                    RegLocation rl_src, RegLocation rl_dest, int lit) {
420fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if ((lit < 0) || (lit >= static_cast<int>(sizeof(magic_table)/sizeof(magic_table[0])))) {
421efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    return false;
422efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
423fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  DividePattern pattern = magic_table[lit].pattern;
424efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  if (pattern == DivideNone) {
425efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    return false;
426efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
427efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  // Tuning: add rem patterns
428fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (dalvik_opcode != Instruction::DIV_INT_LIT8) {
429efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    return false;
430efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
431efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
4321fd3346740dfb7f47be9922312b68a4227fada96buzbee  int r_magic = AllocTemp();
4331fd3346740dfb7f47be9922312b68a4227fada96buzbee  LoadConstant(r_magic, magic_table[lit].magic);
4341fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src = LoadValue(rl_src, kCoreReg);
4351fd3346740dfb7f47be9922312b68a4227fada96buzbee  RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
4361fd3346740dfb7f47be9922312b68a4227fada96buzbee  int r_hi = AllocTemp();
4371fd3346740dfb7f47be9922312b68a4227fada96buzbee  int r_lo = AllocTemp();
4381fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR4(kThumb2Smull, r_lo, r_hi, r_magic, rl_src.low_reg);
439df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom  switch (pattern) {
440efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    case Divide3:
4411fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpRegRegRegShift(kOpSub, rl_result.low_reg, r_hi,
442fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee               rl_src.low_reg, EncodeShift(kArmAsr, 31));
443efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      break;
444efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    case Divide5:
4451fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpRegRegImm(kOpAsr, r_lo, rl_src.low_reg, 31);
4461fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpRegRegRegShift(kOpRsub, rl_result.low_reg, r_lo, r_hi,
447fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee               EncodeShift(kArmAsr, magic_table[lit].shift));
448efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      break;
449efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    case Divide7:
4501fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpRegReg(kOpAdd, r_hi, rl_src.low_reg);
4511fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpRegRegImm(kOpAsr, r_lo, rl_src.low_reg, 31);
4521fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpRegRegRegShift(kOpRsub, rl_result.low_reg, r_lo, r_hi,
453fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee               EncodeShift(kArmAsr, magic_table[lit].shift));
454efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      break;
455efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    default:
456cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      LOG(FATAL) << "Unexpected pattern: " << pattern;
457efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
4581fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValue(rl_dest, rl_result);
459efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return true;
460efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
461efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
4621fd3346740dfb7f47be9922312b68a4227fada96buzbeeLIR* ArmMir2Lir::GenRegMemCheck(ConditionCode c_code,
4632ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                    int reg1, int base, int offset, ThrowKind kind) {
46452a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee  LOG(FATAL) << "Unexpected use of GenRegMemCheck for Arm";
465efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return NULL;
466efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
467efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
4681fd3346740dfb7f47be9922312b68a4227fada96buzbeeRegLocation ArmMir2Lir::GenDivRemLit(RegLocation rl_dest, int reg1, int lit,
4692ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                                     bool is_div) {
47052a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee  LOG(FATAL) << "Unexpected use of GenDivRemLit for Arm";
471fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  return rl_dest;
472efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
473efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
4741fd3346740dfb7f47be9922312b68a4227fada96buzbeeRegLocation ArmMir2Lir::GenDivRem(RegLocation rl_dest, int reg1, int reg2,
4752ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                                  bool is_div) {
47652a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee  LOG(FATAL) << "Unexpected use of GenDivRem for Arm";
477fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  return rl_dest;
478efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
479efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
4802ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrombool ArmMir2Lir::GenInlinedMinMaxInt(CallInfo* info, bool is_min) {
4811fd3346740dfb7f47be9922312b68a4227fada96buzbee  DCHECK_EQ(cu_->instruction_set, kThumb2);
482fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_src1 = info->args[0];
483fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_src2 = info->args[1];
4841fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src1 = LoadValue(rl_src1, kCoreReg);
4851fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src2 = LoadValue(rl_src2, kCoreReg);
4861fd3346740dfb7f47be9922312b68a4227fada96buzbee  RegLocation rl_dest = InlineTarget(info);
4871fd3346740dfb7f47be9922312b68a4227fada96buzbee  RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
4881fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpRegReg(kOpCmp, rl_src1.low_reg, rl_src2.low_reg);
4891fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpIT((is_min) ? kCondGt : kCondLt, "E");
4901fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpRegReg(kOpMov, rl_result.low_reg, rl_src2.low_reg);
4911fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpRegReg(kOpMov, rl_result.low_reg, rl_src1.low_reg);
4921fd3346740dfb7f47be9922312b68a4227fada96buzbee  GenBarrier();
4931fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValue(rl_dest, rl_result);
494efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return true;
495efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
496efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
4972ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid ArmMir2Lir::OpLea(int rBase, int reg1, int reg2, int scale, int offset) {
49852a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee  LOG(FATAL) << "Unexpected use of OpLea for Arm";
499efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
500efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
5012ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid ArmMir2Lir::OpTlsCmp(int offset, int val) {
50252a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee  LOG(FATAL) << "Unexpected use of OpTlsCmp for Arm";
503efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
504efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
5051fd3346740dfb7f47be9922312b68a4227fada96buzbeebool ArmMir2Lir::GenInlinedCas32(CallInfo* info, bool need_write_barrier) {
5061fd3346740dfb7f47be9922312b68a4227fada96buzbee  DCHECK_EQ(cu_->instruction_set, kThumb2);
507fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  // Unused - RegLocation rl_src_unsafe = info->args[0];
508fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_src_obj= info->args[1];  // Object - known non-null
509fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_src_offset= info->args[2];  // long low
510fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  rl_src_offset.wide = 0;  // ignore high half in info->args[3]
511fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_src_expected= info->args[4];  // int or Object
512fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_src_new_value= info->args[5];  // int or Object
5131fd3346740dfb7f47be9922312b68a4227fada96buzbee  RegLocation rl_dest = InlineTarget(info);  // boolean place for result
514efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
515efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
5161bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee  // Release store semantics, get the barrier out of the way.  TODO: revisit
5171fd3346740dfb7f47be9922312b68a4227fada96buzbee  GenMemBarrier(kStoreLoad);
518efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
5191fd3346740dfb7f47be9922312b68a4227fada96buzbee  RegLocation rl_object = LoadValue(rl_src_obj, kCoreReg);
5201fd3346740dfb7f47be9922312b68a4227fada96buzbee  RegLocation rl_new_value = LoadValue(rl_src_new_value, kCoreReg);
521efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
5221fd3346740dfb7f47be9922312b68a4227fada96buzbee  if (need_write_barrier && !mir_graph_->IsConstantNullRef(rl_new_value)) {
523efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    // Mark card for object assuming new value is stored.
5241fd3346740dfb7f47be9922312b68a4227fada96buzbee    MarkGCCard(rl_new_value.low_reg, rl_object.low_reg);
525efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
526efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
5271fd3346740dfb7f47be9922312b68a4227fada96buzbee  RegLocation rl_offset = LoadValue(rl_src_offset, kCoreReg);
528efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
5291fd3346740dfb7f47be9922312b68a4227fada96buzbee  int r_ptr = AllocTemp();
5301fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpRegRegReg(kOpAdd, r_ptr, rl_object.low_reg, rl_offset.low_reg);
531efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
532fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  // Free now unneeded rl_object and rl_offset to give more temps.
5331fd3346740dfb7f47be9922312b68a4227fada96buzbee  ClobberSReg(rl_object.s_reg_low);
5341fd3346740dfb7f47be9922312b68a4227fada96buzbee  FreeTemp(rl_object.low_reg);
5351fd3346740dfb7f47be9922312b68a4227fada96buzbee  ClobberSReg(rl_offset.s_reg_low);
5361fd3346740dfb7f47be9922312b68a4227fada96buzbee  FreeTemp(rl_offset.low_reg);
537efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
5381fd3346740dfb7f47be9922312b68a4227fada96buzbee  int r_old_value = AllocTemp();
5391fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR3(kThumb2Ldrex, r_old_value, r_ptr, 0);  // r_old_value := [r_ptr]
540efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
5411fd3346740dfb7f47be9922312b68a4227fada96buzbee  RegLocation rl_expected = LoadValue(rl_src_expected, kCoreReg);
542efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
543fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  // if (r_old_value == rExpected) {
544fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  //   [r_ptr] <- r_new_value && r_result := success ? 0 : 1
545fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  //   r_result ^= 1
546efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  // } else {
547fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  //   r_result := 0
548efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  // }
5491fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpRegReg(kOpCmp, r_old_value, rl_expected.low_reg);
5501fd3346740dfb7f47be9922312b68a4227fada96buzbee  FreeTemp(r_old_value);  // Now unneeded.
5511fd3346740dfb7f47be9922312b68a4227fada96buzbee  RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
5521fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpIT(kCondEq, "TE");
5531fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR4(kThumb2Strex, rl_result.low_reg, rl_new_value.low_reg, r_ptr, 0);
5541fd3346740dfb7f47be9922312b68a4227fada96buzbee  FreeTemp(r_ptr);  // Now unneeded.
5551fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpRegImm(kOpXor, rl_result.low_reg, 1);
5561fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpRegReg(kOpXor, rl_result.low_reg, rl_result.low_reg);
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);
620fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  dmb->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))) {
6684ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      int func_offset = 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);
7191fd3346740dfb7f47be9922312b68a4227fada96buzbee    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,
7572ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                          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,
8472ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                          RegLocation rl_index, RegLocation rl_src, int scale) {
848e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  RegisterClass reg_class = oat_reg_class_by_size(size);
8492dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  int len_offset = mirror::Array::LengthOffset().Int32Value();
850e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  int data_offset;
8514ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  bool constant_index = rl_index.is_const;
852e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee
8534ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  if (rl_src.wide) {
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();
886e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    //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  }
929e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee}
930e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee
931e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee/*
932e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee * Generate array store
933e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee *
934e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee */
9351fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::GenArrayObjPut(int opt_flags, RegLocation rl_array,
9362ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                             RegLocation rl_index, RegLocation rl_src, int scale) {
9372dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  int len_offset = mirror::Array::LengthOffset().Int32Value();
9382dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  int data_offset = mirror::Array::DataOffset(sizeof(mirror::Object*)).Int32Value();
939e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee
9401fd3346740dfb7f47be9922312b68a4227fada96buzbee  FlushAllRegs();  // Use explicit registers
9411fd3346740dfb7f47be9922312b68a4227fada96buzbee  LockCallTemps();
942e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee
943e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  int r_value = TargetReg(kArg0);  // Register holding value
944e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  int r_array_class = TargetReg(kArg1);  // Register holding array's Class
945e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  int r_array = TargetReg(kArg2);  // Register holding array
946e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  int r_index = TargetReg(kArg3);  // Register holding index into array
947e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee
9481fd3346740dfb7f47be9922312b68a4227fada96buzbee  LoadValueDirectFixed(rl_array, r_array);  // Grab array
9491fd3346740dfb7f47be9922312b68a4227fada96buzbee  LoadValueDirectFixed(rl_src, r_value);  // Grab value
9501fd3346740dfb7f47be9922312b68a4227fada96buzbee  LoadValueDirectFixed(rl_index, r_index);  // Grab index
951e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee
9521fd3346740dfb7f47be9922312b68a4227fada96buzbee  GenNullCheck(rl_array.s_reg_low, r_array, opt_flags);  // NPE?
953e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee
954e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  // Store of null?
9551fd3346740dfb7f47be9922312b68a4227fada96buzbee  LIR* null_value_check = OpCmpImmBranch(kCondEq, r_value, 0, NULL);
956e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee
957e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  // Get the array's class.
9581fd3346740dfb7f47be9922312b68a4227fada96buzbee  LoadWordDisp(r_array, mirror::Object::ClassOffset().Int32Value(), r_array_class);
9591fd3346740dfb7f47be9922312b68a4227fada96buzbee  CallRuntimeHelperRegReg(ENTRYPOINT_OFFSET(pCanPutArrayElementFromCode), r_value,
960e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee                          r_array_class, true);
961e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  // Redo LoadValues in case they didn't survive the call.
9621fd3346740dfb7f47be9922312b68a4227fada96buzbee  LoadValueDirectFixed(rl_array, r_array);  // Reload array
9631fd3346740dfb7f47be9922312b68a4227fada96buzbee  LoadValueDirectFixed(rl_index, r_index);  // Reload index
9641fd3346740dfb7f47be9922312b68a4227fada96buzbee  LoadValueDirectFixed(rl_src, r_value);  // Reload value
965e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  r_array_class = INVALID_REG;
966e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee
967e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  // Branch here if value to be stored == null
9681fd3346740dfb7f47be9922312b68a4227fada96buzbee  LIR* target = NewLIR0(kPseudoTargetLabel);
969e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  null_value_check->target = target;
970e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee
971e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  bool needs_range_check = (!(opt_flags & MIR_IGNORE_RANGE_CHECK));
972e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  int reg_len = INVALID_REG;
973e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  if (needs_range_check) {
974e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    reg_len = TargetReg(kArg1);
9751fd3346740dfb7f47be9922312b68a4227fada96buzbee    LoadWordDisp(r_array, len_offset, reg_len);  // Get len
976e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  }
977e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  /* r_ptr -> array data */
9781fd3346740dfb7f47be9922312b68a4227fada96buzbee  int r_ptr = AllocTemp();
9791fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpRegRegImm(kOpAdd, r_ptr, r_array, data_offset);
980e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  if (needs_range_check) {
9811fd3346740dfb7f47be9922312b68a4227fada96buzbee    GenRegRegCheck(kCondCs, r_index, reg_len, kThrowArrayBounds);
982e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  }
9831fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreBaseIndexed(r_ptr, r_index, r_value, scale, kWord);
9841fd3346740dfb7f47be9922312b68a4227fada96buzbee  FreeTemp(r_ptr);
9851fd3346740dfb7f47be9922312b68a4227fada96buzbee  FreeTemp(r_index);
9861fd3346740dfb7f47be9922312b68a4227fada96buzbee  if (!mir_graph_->IsConstantNullRef(rl_src)) {
9871fd3346740dfb7f47be9922312b68a4227fada96buzbee    MarkGCCard(r_value, r_array);
9886a791b26577a61fd14f4836c795d616869bd2957buzbee  }
989e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee}
990e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee
9911fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::GenShiftImmOpLong(Instruction::Code opcode,
9922ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                                   RegLocation rl_dest, RegLocation rl_src, RegLocation rl_shift) {
9931fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src = LoadValueWide(rl_src, kCoreReg);
9944ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  // Per spec, we only care about low 6 bits of shift amount.
9951fd3346740dfb7f47be9922312b68a4227fada96buzbee  int shift_amount = mir_graph_->ConstantValue(rl_shift) & 0x3f;
9964ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  if (shift_amount == 0) {
9971fd3346740dfb7f47be9922312b68a4227fada96buzbee    StoreValueWide(rl_dest, rl_src);
998a5954be0aac5edd892fb31a209960543d00e4500buzbee    return;
9994ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  }
10001fd3346740dfb7f47be9922312b68a4227fada96buzbee  if (BadOverlap(rl_src, rl_dest)) {
10011fd3346740dfb7f47be9922312b68a4227fada96buzbee    GenShiftOpLong(opcode, rl_dest, rl_src, rl_shift);
1002a5954be0aac5edd892fb31a209960543d00e4500buzbee    return;
10034ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  }
10041fd3346740dfb7f47be9922312b68a4227fada96buzbee  RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
1005df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom  switch (opcode) {
10064ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::SHL_LONG:
10074ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::SHL_LONG_2ADDR:
10084ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      if (shift_amount == 1) {
10091fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegReg(kOpAdd, rl_result.low_reg, rl_src.low_reg, rl_src.low_reg);
10101fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegReg(kOpAdc, rl_result.high_reg, rl_src.high_reg, rl_src.high_reg);
10114ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      } else if (shift_amount == 32) {
10121fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegCopy(rl_result.high_reg, rl_src.low_reg);
10131fd3346740dfb7f47be9922312b68a4227fada96buzbee        LoadConstant(rl_result.low_reg, 0);
10144ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      } else if (shift_amount > 31) {
10151fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegImm(kOpLsl, rl_result.high_reg, rl_src.low_reg, shift_amount - 32);
10161fd3346740dfb7f47be9922312b68a4227fada96buzbee        LoadConstant(rl_result.low_reg, 0);
10174ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      } else {
10181fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegImm(kOpLsl, rl_result.high_reg, rl_src.high_reg, shift_amount);
10191fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegRegShift(kOpOr, rl_result.high_reg, rl_result.high_reg, rl_src.low_reg,
10204ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee                         EncodeShift(kArmLsr, 32 - shift_amount));
10211fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegImm(kOpLsl, rl_result.low_reg, rl_src.low_reg, shift_amount);
10224ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      }
10234ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      break;
10244ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::SHR_LONG:
10254ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::SHR_LONG_2ADDR:
10264ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      if (shift_amount == 32) {
10271fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegCopy(rl_result.low_reg, rl_src.high_reg);
10281fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegImm(kOpAsr, rl_result.high_reg, rl_src.high_reg, 31);
10294ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      } else if (shift_amount > 31) {
10301fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegImm(kOpAsr, rl_result.low_reg, rl_src.high_reg, shift_amount - 32);
10311fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegImm(kOpAsr, rl_result.high_reg, rl_src.high_reg, 31);
10324ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      } else {
10331fd3346740dfb7f47be9922312b68a4227fada96buzbee        int t_reg = AllocTemp();
10341fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegImm(kOpLsr, t_reg, rl_src.low_reg, shift_amount);
10351fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegRegShift(kOpOr, rl_result.low_reg, t_reg, rl_src.high_reg,
10364ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee                         EncodeShift(kArmLsl, 32 - shift_amount));
10371fd3346740dfb7f47be9922312b68a4227fada96buzbee        FreeTemp(t_reg);
10381fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegImm(kOpAsr, rl_result.high_reg, rl_src.high_reg, shift_amount);
10394ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      }
10404ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      break;
10414ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::USHR_LONG:
10424ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::USHR_LONG_2ADDR:
10434ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      if (shift_amount == 32) {
10441fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegCopy(rl_result.low_reg, rl_src.high_reg);
10451fd3346740dfb7f47be9922312b68a4227fada96buzbee        LoadConstant(rl_result.high_reg, 0);
10464ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      } else if (shift_amount > 31) {
10471fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegImm(kOpLsr, rl_result.low_reg, rl_src.high_reg, shift_amount - 32);
10481fd3346740dfb7f47be9922312b68a4227fada96buzbee        LoadConstant(rl_result.high_reg, 0);
10494ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      } else {
10501fd3346740dfb7f47be9922312b68a4227fada96buzbee        int t_reg = AllocTemp();
10511fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegImm(kOpLsr, t_reg, rl_src.low_reg, shift_amount);
10521fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegRegShift(kOpOr, rl_result.low_reg, t_reg, rl_src.high_reg,
10534ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee                         EncodeShift(kArmLsl, 32 - shift_amount));
10541fd3346740dfb7f47be9922312b68a4227fada96buzbee        FreeTemp(t_reg);
10551fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegImm(kOpLsr, rl_result.high_reg, rl_src.high_reg, shift_amount);
10564ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      }
10574ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      break;
10584ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    default:
10594ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      LOG(FATAL) << "Unexpected case";
10604ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  }
10611fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValueWide(rl_dest, rl_result);
10624ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee}
10634ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
10641fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::GenArithImmOpLong(Instruction::Code opcode,
10652ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                                   RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) {
10664ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  if ((opcode == Instruction::SUB_LONG_2ADDR) || (opcode == Instruction::SUB_LONG)) {
10674ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    if (!rl_src2.is_const) {
10684ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      // Don't bother with special handling for subtract from immediate.
10691fd3346740dfb7f47be9922312b68a4227fada96buzbee      GenArithOpLong(opcode, rl_dest, rl_src1, rl_src2);
1070a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
10714ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    }
10724ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  } else {
10734ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    // Normalize
10744ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    if (!rl_src2.is_const) {
10754ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      DCHECK(rl_src1.is_const);
10764ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      RegLocation rl_temp = rl_src1;
10774ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      rl_src1 = rl_src2;
10784ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      rl_src2 = rl_temp;
10794ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    }
10804ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  }
10811fd3346740dfb7f47be9922312b68a4227fada96buzbee  if (BadOverlap(rl_src1, rl_dest)) {
10821fd3346740dfb7f47be9922312b68a4227fada96buzbee    GenArithOpLong(opcode, rl_dest, rl_src1, rl_src2);
1083a5954be0aac5edd892fb31a209960543d00e4500buzbee    return;
10844ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  }
10854ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  DCHECK(rl_src2.is_const);
10861fd3346740dfb7f47be9922312b68a4227fada96buzbee  int64_t val = mir_graph_->ConstantValueWide(rl_src2);
10874ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  uint32_t val_lo = Low32Bits(val);
10884ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  uint32_t val_hi = High32Bits(val);
10894ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  int32_t mod_imm_lo = ModifiedImmediate(val_lo);
10904ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  int32_t mod_imm_hi = ModifiedImmediate(val_hi);
10914ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
10924ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  // Only a subset of add/sub immediate instructions set carry - so bail if we don't fit
1093df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom  switch (opcode) {
10944ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::ADD_LONG:
10954ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::ADD_LONG_2ADDR:
10964ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::SUB_LONG:
10974ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::SUB_LONG_2ADDR:
10984ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      if ((mod_imm_lo < 0) || (mod_imm_hi < 0)) {
10991fd3346740dfb7f47be9922312b68a4227fada96buzbee        GenArithOpLong(opcode, rl_dest, rl_src1, rl_src2);
1100a5954be0aac5edd892fb31a209960543d00e4500buzbee        return;
11014ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      }
11024ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      break;
11034ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    default:
11044ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      break;
11054ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  }
11061fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src1 = LoadValueWide(rl_src1, kCoreReg);
11071fd3346740dfb7f47be9922312b68a4227fada96buzbee  RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
11084ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  // NOTE: once we've done the EvalLoc on dest, we can no longer bail.
11094ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  switch (opcode) {
11104ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::ADD_LONG:
11114ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::ADD_LONG_2ADDR:
11121fd3346740dfb7f47be9922312b68a4227fada96buzbee      NewLIR3(kThumb2AddRRI8, rl_result.low_reg, rl_src1.low_reg, mod_imm_lo);
11131fd3346740dfb7f47be9922312b68a4227fada96buzbee      NewLIR3(kThumb2AdcRRI8, rl_result.high_reg, rl_src1.high_reg, mod_imm_hi);
11144ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      break;
11154ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::OR_LONG:
11164ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::OR_LONG_2ADDR:
11174ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      if ((val_lo != 0) || (rl_result.low_reg != rl_src1.low_reg)) {
11181fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegImm(kOpOr, rl_result.low_reg, rl_src1.low_reg, val_lo);
11194ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      }
11204ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      if ((val_hi != 0) || (rl_result.high_reg != rl_src1.high_reg)) {
11211fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegImm(kOpOr, rl_result.high_reg, rl_src1.high_reg, val_hi);
11224ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      }
11234ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      break;
11244ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::XOR_LONG:
11254ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::XOR_LONG_2ADDR:
11261fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpRegRegImm(kOpXor, rl_result.low_reg, rl_src1.low_reg, val_lo);
11271fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpRegRegImm(kOpXor, rl_result.high_reg, rl_src1.high_reg, val_hi);
11284ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      break;
11294ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::AND_LONG:
11304ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::AND_LONG_2ADDR:
11314ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      if ((val_lo != 0xffffffff) || (rl_result.low_reg != rl_src1.low_reg)) {
11321fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegImm(kOpAnd, rl_result.low_reg, rl_src1.low_reg, val_lo);
11334ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      }
11344ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      if ((val_hi != 0xffffffff) || (rl_result.high_reg != rl_src1.high_reg)) {
11351fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegImm(kOpAnd, rl_result.high_reg, rl_src1.high_reg, val_hi);
11364ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      }
11374ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      break;
11384ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::SUB_LONG_2ADDR:
11394ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::SUB_LONG:
11401fd3346740dfb7f47be9922312b68a4227fada96buzbee      NewLIR3(kThumb2SubRRI8, rl_result.low_reg, rl_src1.low_reg, mod_imm_lo);
11411fd3346740dfb7f47be9922312b68a4227fada96buzbee      NewLIR3(kThumb2SbcRRI8, rl_result.high_reg, rl_src1.high_reg, mod_imm_hi);
11424ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      break;
11434ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    default:
11444ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      LOG(FATAL) << "Unexpected opcode " << opcode;
11454ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  }
11461fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValueWide(rl_dest, rl_result);
11474ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee}
11484ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
1149efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}  // namespace art
1150