int_arm.cc revision d9c4fc94fa618617f94e1de9af5f034549100753
1efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/*
2efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Copyright (C) 2011 The Android Open Source Project
3efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *
4efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Licensed under the Apache License, Version 2.0 (the "License");
5efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * you may not use this file except in compliance with the License.
6efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * You may obtain a copy of the License at
7efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *
8efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *      http://www.apache.org/licenses/LICENSE-2.0
9efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *
10efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Unless required by applicable law or agreed to in writing, software
11efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * distributed under the License is distributed on an "AS IS" BASIS,
12efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * See the License for the specific language governing permissions and
14efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * limitations under the License.
15efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */
16efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
17efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* This file contains codegen for the Thumb2 ISA. */
18efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
191bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee#include "arm_lir.h"
2002031b185b4653e6c72e21f7a51238b903f6d638buzbee#include "codegen_arm.h"
217940e44f4517de5e2634a7e07d58d0fb26160513Brian Carlstrom#include "dex/quick/mir_to_lir-inl.h"
22166db04e259ca51838c311891598664deeed85adIan Rogers#include "entrypoints/quick/quick_entrypoints.h"
2333e9566255c426e7a2c8fca5b8a1b6a94a5d352cIan Rogers#include "mirror/array.h"
24efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
25efc6369224b036a1fb77849f7ae65b3492c832c0buzbeenamespace art {
26efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
27d9c4fc94fa618617f94e1de9af5f034549100753Ian RogersLIR* ArmMir2Lir::OpCmpBranch(ConditionCode cond, int src1, int src2, LIR* target) {
281fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpRegReg(kOpCmp, src1, src2);
291fd3346740dfb7f47be9922312b68a4227fada96buzbee  return OpCondBranch(cond, target);
30efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
31efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
32efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/*
33efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Generate a Thumb2 IT instruction, which can nullify up to
34efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * four subsequent instructions based on a condition and its
35efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * inverse.  The condition applies to the first instruction, which
36efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * is executed if the condition is met.  The string "guide" consists
37efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * of 0 to 3 chars, and applies to the 2nd through 4th instruction.
38efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * A "T" means the instruction is executed if the condition is
39efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * met, and an "E" means the instruction is executed if the condition
40efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * is not met.
41efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */
422ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromLIR* ArmMir2Lir::OpIT(ConditionCode ccode, const char* guide) {
43efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  int mask;
44efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  int mask3 = 0;
45efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  int mask2 = 0;
46efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  int mask1 = 0;
4702031b185b4653e6c72e21f7a51238b903f6d638buzbee  ArmConditionCode code = ArmConditionEncoding(ccode);
4802031b185b4653e6c72e21f7a51238b903f6d638buzbee  int cond_bit = code & 1;
4902031b185b4653e6c72e21f7a51238b903f6d638buzbee  int alt_bit = cond_bit ^ 1;
50efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
517934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom  // Note: case fallthroughs intentional
52efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  switch (strlen(guide)) {
53efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    case 3:
54fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      mask1 = (guide[2] == 'T') ? cond_bit : alt_bit;
55efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    case 2:
56fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      mask2 = (guide[1] == 'T') ? cond_bit : alt_bit;
57efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    case 1:
58fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      mask3 = (guide[0] == 'T') ? cond_bit : alt_bit;
59efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      break;
60efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    case 0:
61efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      break;
62efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    default:
6352a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee      LOG(FATAL) << "OAT: bad case in OpIT";
64efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
65efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  mask = (mask3 << 3) | (mask2 << 2) | (mask1 << 1) |
66efc6369224b036a1fb77849f7ae65b3492c832c0buzbee       (1 << (3 - strlen(guide)));
671fd3346740dfb7f47be9922312b68a4227fada96buzbee  return NewLIR2(kThumb2It, code, mask);
68efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
69efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
70efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/*
71efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * 64-bit 3way compare function.
72efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *     mov   rX, #-1
73efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *     cmp   op1hi, op2hi
74efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *     blt   done
75efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *     bgt   flip
76efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *     sub   rX, op1lo, op2lo (treat as unsigned)
77efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *     beq   done
78efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *     ite   hi
79efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *     mov(hi)   rX, #-1
80efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *     mov(!hi)  rX, #1
81efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * flip:
82efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *     neg   rX
83efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * done:
84efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */
851fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::GenCmpLong(RegLocation rl_dest, RegLocation rl_src1,
862ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                            RegLocation rl_src2) {
87efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  LIR* target1;
88efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  LIR* target2;
891fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src1 = LoadValueWide(rl_src1, kCoreReg);
901fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src2 = LoadValueWide(rl_src2, kCoreReg);
911fd3346740dfb7f47be9922312b68a4227fada96buzbee  int t_reg = AllocTemp();
921fd3346740dfb7f47be9922312b68a4227fada96buzbee  LoadConstant(t_reg, -1);
931fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpRegReg(kOpCmp, rl_src1.high_reg, rl_src2.high_reg);
941fd3346740dfb7f47be9922312b68a4227fada96buzbee  LIR* branch1 = OpCondBranch(kCondLt, NULL);
951fd3346740dfb7f47be9922312b68a4227fada96buzbee  LIR* branch2 = OpCondBranch(kCondGt, NULL);
961fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpRegRegReg(kOpSub, t_reg, rl_src1.low_reg, rl_src2.low_reg);
971fd3346740dfb7f47be9922312b68a4227fada96buzbee  LIR* branch3 = OpCondBranch(kCondEq, NULL);
981fd3346740dfb7f47be9922312b68a4227fada96buzbee
991fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpIT(kCondHi, "E");
1001fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR2(kThumb2MovImmShift, t_reg, ModifiedImmediate(-1));
1011fd3346740dfb7f47be9922312b68a4227fada96buzbee  LoadConstant(t_reg, 1);
1021fd3346740dfb7f47be9922312b68a4227fada96buzbee  GenBarrier();
1031fd3346740dfb7f47be9922312b68a4227fada96buzbee
1041fd3346740dfb7f47be9922312b68a4227fada96buzbee  target2 = NewLIR0(kPseudoTargetLabel);
1051fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpRegReg(kOpNeg, t_reg, t_reg);
1061fd3346740dfb7f47be9922312b68a4227fada96buzbee
1071fd3346740dfb7f47be9922312b68a4227fada96buzbee  target1 = NewLIR0(kPseudoTargetLabel);
108fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee
1097934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom  RegLocation rl_temp = LocCReturn();  // Just using as template, will change
110fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  rl_temp.low_reg = t_reg;
1111fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValue(rl_dest, rl_temp);
1121fd3346740dfb7f47be9922312b68a4227fada96buzbee  FreeTemp(t_reg);
113efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
114cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee  branch1->target = target1;
115cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee  branch2->target = target2;
116efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  branch3->target = branch1->target;
117efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
118efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
1191fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::GenFusedLongCmpImmBranch(BasicBlock* bb, RegLocation rl_src1,
1202ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                                          int64_t val, ConditionCode ccode) {
1214ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  int32_t val_lo = Low32Bits(val);
1224ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  int32_t val_hi = High32Bits(val);
1234274889d48ef82369bf2c1ca70d84689b4f9e93aBrian Carlstrom  DCHECK_GE(ModifiedImmediate(val_lo), 0);
1244274889d48ef82369bf2c1ca70d84689b4f9e93aBrian Carlstrom  DCHECK_GE(ModifiedImmediate(val_hi), 0);
1251fd3346740dfb7f47be9922312b68a4227fada96buzbee  LIR* taken = &block_label_list_[bb->taken->id];
1261fd3346740dfb7f47be9922312b68a4227fada96buzbee  LIR* not_taken = &block_label_list_[bb->fall_through->id];
1271fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src1 = LoadValueWide(rl_src1, kCoreReg);
1284ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  int32_t low_reg = rl_src1.low_reg;
1294ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  int32_t high_reg = rl_src1.high_reg;
1304ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
131df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom  switch (ccode) {
1324ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case kCondEq:
1334ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case kCondNe:
134c7d1f91e024c5c560810376340aecb39d4e47fdcbuzbee      LIR* target;
135c7d1f91e024c5c560810376340aecb39d4e47fdcbuzbee      ConditionCode condition;
136c7d1f91e024c5c560810376340aecb39d4e47fdcbuzbee      if (ccode == kCondEq) {
137c7d1f91e024c5c560810376340aecb39d4e47fdcbuzbee        target = not_taken;
138c7d1f91e024c5c560810376340aecb39d4e47fdcbuzbee        condition = kCondEq;
139c7d1f91e024c5c560810376340aecb39d4e47fdcbuzbee      } else {
140c7d1f91e024c5c560810376340aecb39d4e47fdcbuzbee        target = taken;
141c7d1f91e024c5c560810376340aecb39d4e47fdcbuzbee        condition = kCondNe;
142c7d1f91e024c5c560810376340aecb39d4e47fdcbuzbee      }
143c7d1f91e024c5c560810376340aecb39d4e47fdcbuzbee      if (val == 0) {
1441fd3346740dfb7f47be9922312b68a4227fada96buzbee        int t_reg = AllocTemp();
1451fd3346740dfb7f47be9922312b68a4227fada96buzbee        NewLIR4(kThumb2OrrRRRs, t_reg, low_reg, high_reg, 0);
1461fd3346740dfb7f47be9922312b68a4227fada96buzbee        FreeTemp(t_reg);
1471fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpCondBranch(condition, taken);
148c7d1f91e024c5c560810376340aecb39d4e47fdcbuzbee        return;
149c7d1f91e024c5c560810376340aecb39d4e47fdcbuzbee      }
1501fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCmpImmBranch(kCondNe, high_reg, val_hi, target);
1514ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      break;
1524ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case kCondLt:
1531fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCmpImmBranch(kCondLt, high_reg, val_hi, taken);
1541fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCmpImmBranch(kCondGt, high_reg, val_hi, not_taken);
1554ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      ccode = kCondCc;
1564ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      break;
1574ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case kCondLe:
1581fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCmpImmBranch(kCondLt, high_reg, val_hi, taken);
1591fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCmpImmBranch(kCondGt, high_reg, val_hi, not_taken);
1604ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      ccode = kCondLs;
1614ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      break;
1624ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case kCondGt:
1631fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCmpImmBranch(kCondGt, high_reg, val_hi, taken);
1641fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCmpImmBranch(kCondLt, high_reg, val_hi, not_taken);
1654ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      ccode = kCondHi;
1664ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      break;
1674ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case kCondGe:
1681fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCmpImmBranch(kCondGt, high_reg, val_hi, taken);
1691fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCmpImmBranch(kCondLt, high_reg, val_hi, not_taken);
1704ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      ccode = kCondCs;
1714ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      break;
1724ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    default:
1734ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      LOG(FATAL) << "Unexpected ccode: " << ccode;
1744ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  }
1751fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpCmpImmBranch(ccode, low_reg, val_lo, taken);
1764ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee}
1774ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
1782ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid ArmMir2Lir::GenSelect(BasicBlock* bb, MIR* mir) {
179f662a7c625b1067f61b23c04459eba9b12bc027ebuzbee  RegLocation rl_result;
1801fd3346740dfb7f47be9922312b68a4227fada96buzbee  RegLocation rl_src = mir_graph_->GetSrc(mir, 0);
181a0e8bbd2f684f4187ef3d5835a73da8e8ce6dac8buzbee  // Temporary debugging code
182a0e8bbd2f684f4187ef3d5835a73da8e8ce6dac8buzbee  int dest_sreg = mir->ssa_rep->defs[0];
1831fd3346740dfb7f47be9922312b68a4227fada96buzbee  if ((dest_sreg < 0) || (dest_sreg >= mir_graph_->GetNumSSARegs())) {
184a0e8bbd2f684f4187ef3d5835a73da8e8ce6dac8buzbee    LOG(INFO) << "Bad target sreg: " << dest_sreg << ", in "
185b1eba213afaf7fa6445de863ddc9680ab99762eaBrian Carlstrom              << PrettyMethod(cu_->method_idx, *cu_->dex_file);
186a0e8bbd2f684f4187ef3d5835a73da8e8ce6dac8buzbee    LOG(INFO) << "at dex offset 0x" << std::hex << mir->offset;
1871fd3346740dfb7f47be9922312b68a4227fada96buzbee    LOG(INFO) << "vreg = " << mir_graph_->SRegToVReg(dest_sreg);
188a0e8bbd2f684f4187ef3d5835a73da8e8ce6dac8buzbee    LOG(INFO) << "num uses = " << mir->ssa_rep->num_uses;
189a0e8bbd2f684f4187ef3d5835a73da8e8ce6dac8buzbee    if (mir->ssa_rep->num_uses == 1) {
190a0e8bbd2f684f4187ef3d5835a73da8e8ce6dac8buzbee      LOG(INFO) << "CONST case, vals = " << mir->dalvikInsn.vB << ", " << mir->dalvikInsn.vC;
191a0e8bbd2f684f4187ef3d5835a73da8e8ce6dac8buzbee    } else {
192a0e8bbd2f684f4187ef3d5835a73da8e8ce6dac8buzbee      LOG(INFO) << "MOVE case, operands = " << mir->ssa_rep->uses[1] << ", "
193a0e8bbd2f684f4187ef3d5835a73da8e8ce6dac8buzbee                << mir->ssa_rep->uses[2];
194a0e8bbd2f684f4187ef3d5835a73da8e8ce6dac8buzbee    }
195a0e8bbd2f684f4187ef3d5835a73da8e8ce6dac8buzbee    CHECK(false) << "Invalid target sreg on Select.";
196a0e8bbd2f684f4187ef3d5835a73da8e8ce6dac8buzbee  }
197a0e8bbd2f684f4187ef3d5835a73da8e8ce6dac8buzbee  // End temporary debugging code
1981fd3346740dfb7f47be9922312b68a4227fada96buzbee  RegLocation rl_dest = mir_graph_->GetDest(mir);
1991fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src = LoadValue(rl_src, kCoreReg);
200f662a7c625b1067f61b23c04459eba9b12bc027ebuzbee  if (mir->ssa_rep->num_uses == 1) {
201f662a7c625b1067f61b23c04459eba9b12bc027ebuzbee    // CONST case
202f662a7c625b1067f61b23c04459eba9b12bc027ebuzbee    int true_val = mir->dalvikInsn.vB;
203f662a7c625b1067f61b23c04459eba9b12bc027ebuzbee    int false_val = mir->dalvikInsn.vC;
2041fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_result = EvalLoc(rl_dest, kCoreReg, true);
205f662a7c625b1067f61b23c04459eba9b12bc027ebuzbee    if ((true_val == 1) && (false_val == 0)) {
2061fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpRegRegImm(kOpRsub, rl_result.low_reg, rl_src.low_reg, 1);
2071fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpIT(kCondCc, "");
2081fd3346740dfb7f47be9922312b68a4227fada96buzbee      LoadConstant(rl_result.low_reg, 0);
2097934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom      GenBarrier();  // Add a scheduling barrier to keep the IT shadow intact
210f662a7c625b1067f61b23c04459eba9b12bc027ebuzbee    } else if (InexpensiveConstantInt(true_val) && InexpensiveConstantInt(false_val)) {
2111fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpRegImm(kOpCmp, rl_src.low_reg, 0);
2121fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpIT(kCondEq, "E");
2131fd3346740dfb7f47be9922312b68a4227fada96buzbee      LoadConstant(rl_result.low_reg, true_val);
2141fd3346740dfb7f47be9922312b68a4227fada96buzbee      LoadConstant(rl_result.low_reg, false_val);
2157934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom      GenBarrier();  // Add a scheduling barrier to keep the IT shadow intact
216f662a7c625b1067f61b23c04459eba9b12bc027ebuzbee    } else {
217f662a7c625b1067f61b23c04459eba9b12bc027ebuzbee      // Unlikely case - could be tuned.
2181fd3346740dfb7f47be9922312b68a4227fada96buzbee      int t_reg1 = AllocTemp();
2191fd3346740dfb7f47be9922312b68a4227fada96buzbee      int t_reg2 = AllocTemp();
2201fd3346740dfb7f47be9922312b68a4227fada96buzbee      LoadConstant(t_reg1, true_val);
2211fd3346740dfb7f47be9922312b68a4227fada96buzbee      LoadConstant(t_reg2, false_val);
2221fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpRegImm(kOpCmp, rl_src.low_reg, 0);
2231fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpIT(kCondEq, "E");
2241fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpRegCopy(rl_result.low_reg, t_reg1);
2251fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpRegCopy(rl_result.low_reg, t_reg2);
2267934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom      GenBarrier();  // Add a scheduling barrier to keep the IT shadow intact
227f662a7c625b1067f61b23c04459eba9b12bc027ebuzbee    }
228f662a7c625b1067f61b23c04459eba9b12bc027ebuzbee  } else {
229f662a7c625b1067f61b23c04459eba9b12bc027ebuzbee    // MOVE case
2301fd3346740dfb7f47be9922312b68a4227fada96buzbee    RegLocation rl_true = mir_graph_->reg_location_[mir->ssa_rep->uses[1]];
2311fd3346740dfb7f47be9922312b68a4227fada96buzbee    RegLocation rl_false = mir_graph_->reg_location_[mir->ssa_rep->uses[2]];
2321fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_true = LoadValue(rl_true, kCoreReg);
2331fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_false = LoadValue(rl_false, kCoreReg);
2341fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_result = EvalLoc(rl_dest, kCoreReg, true);
2351fd3346740dfb7f47be9922312b68a4227fada96buzbee    OpRegImm(kOpCmp, rl_src.low_reg, 0);
236252254b130067cd7a5071865e793966871ae0246buzbee    if (rl_result.low_reg == rl_true.low_reg) {  // Is the "true" case already in place?
237252254b130067cd7a5071865e793966871ae0246buzbee      OpIT(kCondNe, "");
238252254b130067cd7a5071865e793966871ae0246buzbee      OpRegCopy(rl_result.low_reg, rl_false.low_reg);
239252254b130067cd7a5071865e793966871ae0246buzbee    } else if (rl_result.low_reg == rl_false.low_reg) {  // False case in place?
240252254b130067cd7a5071865e793966871ae0246buzbee      OpIT(kCondEq, "");
241252254b130067cd7a5071865e793966871ae0246buzbee      OpRegCopy(rl_result.low_reg, rl_true.low_reg);
242252254b130067cd7a5071865e793966871ae0246buzbee    } else {  // Normal - select between the two.
243252254b130067cd7a5071865e793966871ae0246buzbee      OpIT(kCondEq, "E");
244252254b130067cd7a5071865e793966871ae0246buzbee      OpRegCopy(rl_result.low_reg, rl_true.low_reg);
245252254b130067cd7a5071865e793966871ae0246buzbee      OpRegCopy(rl_result.low_reg, rl_false.low_reg);
246252254b130067cd7a5071865e793966871ae0246buzbee    }
2477934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom    GenBarrier();  // Add a scheduling barrier to keep the IT shadow intact
248f662a7c625b1067f61b23c04459eba9b12bc027ebuzbee  }
2491fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValue(rl_dest, rl_result);
250f662a7c625b1067f61b23c04459eba9b12bc027ebuzbee}
2514ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
2522ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid ArmMir2Lir::GenFusedLongCmpBranch(BasicBlock* bb, MIR* mir) {
2531fd3346740dfb7f47be9922312b68a4227fada96buzbee  RegLocation rl_src1 = mir_graph_->GetSrcWide(mir, 0);
2541fd3346740dfb7f47be9922312b68a4227fada96buzbee  RegLocation rl_src2 = mir_graph_->GetSrcWide(mir, 2);
2554ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  // Normalize such that if either operand is constant, src2 will be constant.
2564ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  ConditionCode ccode = static_cast<ConditionCode>(mir->dalvikInsn.arg[0]);
2574ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  if (rl_src1.is_const) {
2584ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    RegLocation rl_temp = rl_src1;
2594ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    rl_src1 = rl_src2;
2604ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    rl_src2 = rl_temp;
2614ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    ccode = FlipComparisonOrder(ccode);
2624ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  }
2634ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  if (rl_src2.is_const) {
2641fd3346740dfb7f47be9922312b68a4227fada96buzbee    RegLocation rl_temp = UpdateLocWide(rl_src2);
2654ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    // Do special compare/branch against simple const operand if not already in registers.
2661fd3346740dfb7f47be9922312b68a4227fada96buzbee    int64_t val = mir_graph_->ConstantValueWide(rl_src2);
2674ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    if ((rl_temp.location != kLocPhysReg) &&
2684ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee        ((ModifiedImmediate(Low32Bits(val)) >= 0) && (ModifiedImmediate(High32Bits(val)) >= 0))) {
2691fd3346740dfb7f47be9922312b68a4227fada96buzbee      GenFusedLongCmpImmBranch(bb, rl_src1, val, ccode);
2704ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      return;
2714ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    }
2724ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  }
2731fd3346740dfb7f47be9922312b68a4227fada96buzbee  LIR* taken = &block_label_list_[bb->taken->id];
2741fd3346740dfb7f47be9922312b68a4227fada96buzbee  LIR* not_taken = &block_label_list_[bb->fall_through->id];
2751fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src1 = LoadValueWide(rl_src1, kCoreReg);
2761fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src2 = LoadValueWide(rl_src2, kCoreReg);
2771fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpRegReg(kOpCmp, rl_src1.high_reg, rl_src2.high_reg);
278df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom  switch (ccode) {
279efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    case kCondEq:
2801fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCondBranch(kCondNe, not_taken);
281efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      break;
282efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    case kCondNe:
2831fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCondBranch(kCondNe, taken);
284efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      break;
285efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    case kCondLt:
2861fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCondBranch(kCondLt, taken);
2871fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCondBranch(kCondGt, not_taken);
288efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      ccode = kCondCc;
289efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      break;
290efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    case kCondLe:
2911fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCondBranch(kCondLt, taken);
2921fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCondBranch(kCondGt, not_taken);
293efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      ccode = kCondLs;
294efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      break;
295efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    case kCondGt:
2961fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCondBranch(kCondGt, taken);
2971fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCondBranch(kCondLt, not_taken);
298efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      ccode = kCondHi;
299efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      break;
300efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    case kCondGe:
3011fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCondBranch(kCondGt, taken);
3021fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpCondBranch(kCondLt, not_taken);
303efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      ccode = kCondCs;
304efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      break;
305efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    default:
306cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      LOG(FATAL) << "Unexpected ccode: " << ccode;
307efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
3081fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpRegReg(kOpCmp, rl_src1.low_reg, rl_src2.low_reg);
3091fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpCondBranch(ccode, taken);
310efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
311efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
312efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/*
313efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Generate a register comparison to an immediate and branch.  Caller
314efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * is responsible for setting branch target field.
315efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */
3161fd3346740dfb7f47be9922312b68a4227fada96buzbeeLIR* ArmMir2Lir::OpCmpImmBranch(ConditionCode cond, int reg, int check_value,
3172ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                                LIR* target) {
318efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  LIR* branch;
319fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  int mod_imm;
320fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  ArmConditionCode arm_cond = ArmConditionEncoding(cond);
321fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if ((ARM_LOWREG(reg)) && (check_value == 0) &&
322fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee     ((arm_cond == kArmCondEq) || (arm_cond == kArmCondNe))) {
3231fd3346740dfb7f47be9922312b68a4227fada96buzbee    branch = NewLIR2((arm_cond == kArmCondEq) ? kThumb2Cbz : kThumb2Cbnz,
324efc6369224b036a1fb77849f7ae65b3492c832c0buzbee                     reg, 0);
325efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  } else {
326fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    mod_imm = ModifiedImmediate(check_value);
327fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (ARM_LOWREG(reg) && ((check_value & 0xff) == check_value)) {
3281fd3346740dfb7f47be9922312b68a4227fada96buzbee      NewLIR2(kThumbCmpRI8, reg, check_value);
329fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    } else if (mod_imm >= 0) {
3301fd3346740dfb7f47be9922312b68a4227fada96buzbee      NewLIR2(kThumb2CmpRI12, reg, mod_imm);
331efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    } else {
3321fd3346740dfb7f47be9922312b68a4227fada96buzbee      int t_reg = AllocTemp();
3331fd3346740dfb7f47be9922312b68a4227fada96buzbee      LoadConstant(t_reg, check_value);
3341fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpRegReg(kOpCmp, reg, t_reg);
335efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    }
3361fd3346740dfb7f47be9922312b68a4227fada96buzbee    branch = NewLIR2(kThumbBCond, 0, arm_cond);
337efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
338efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  branch->target = target;
339efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return branch;
340efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
34102031b185b4653e6c72e21f7a51238b903f6d638buzbee
3422ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromLIR* ArmMir2Lir::OpRegCopyNoInsert(int r_dest, int r_src) {
343efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  LIR* res;
344efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  int opcode;
345fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (ARM_FPREG(r_dest) || ARM_FPREG(r_src))
3461fd3346740dfb7f47be9922312b68a4227fada96buzbee    return OpFpRegCopy(r_dest, r_src);
347fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (ARM_LOWREG(r_dest) && ARM_LOWREG(r_src))
348efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    opcode = kThumbMovRR;
349fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  else if (!ARM_LOWREG(r_dest) && !ARM_LOWREG(r_src))
350efc6369224b036a1fb77849f7ae65b3492c832c0buzbee     opcode = kThumbMovRR_H2H;
351fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  else if (ARM_LOWREG(r_dest))
352efc6369224b036a1fb77849f7ae65b3492c832c0buzbee     opcode = kThumbMovRR_H2L;
353efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  else
354efc6369224b036a1fb77849f7ae65b3492c832c0buzbee     opcode = kThumbMovRR_L2H;
3551fd3346740dfb7f47be9922312b68a4227fada96buzbee  res = RawLIR(current_dalvik_offset_, opcode, r_dest, r_src);
3561fd3346740dfb7f47be9922312b68a4227fada96buzbee  if (!(cu_->disable_opt & (1 << kSafeOptimizations)) && r_dest == r_src) {
357fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    res->flags.is_nop = true;
358efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
359efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return res;
360efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
361efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
3622ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromLIR* ArmMir2Lir::OpRegCopy(int r_dest, int r_src) {
3631fd3346740dfb7f47be9922312b68a4227fada96buzbee  LIR* res = OpRegCopyNoInsert(r_dest, r_src);
3641fd3346740dfb7f47be9922312b68a4227fada96buzbee  AppendLIR(res);
365efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return res;
366efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
367efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
3681fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::OpRegCopyWide(int dest_lo, int dest_hi, int src_lo,
3692ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                               int src_hi) {
370fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  bool dest_fp = ARM_FPREG(dest_lo) && ARM_FPREG(dest_hi);
371fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  bool src_fp = ARM_FPREG(src_lo) && ARM_FPREG(src_hi);
372fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  DCHECK_EQ(ARM_FPREG(src_lo), ARM_FPREG(src_hi));
373fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  DCHECK_EQ(ARM_FPREG(dest_lo), ARM_FPREG(dest_hi));
374fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (dest_fp) {
375fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (src_fp) {
3761fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpRegCopy(S2d(dest_lo, dest_hi), S2d(src_lo, src_hi));
377efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    } else {
3781fd3346740dfb7f47be9922312b68a4227fada96buzbee      NewLIR3(kThumb2Fmdrr, S2d(dest_lo, dest_hi), src_lo, src_hi);
379efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    }
380efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  } else {
381fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (src_fp) {
3821fd3346740dfb7f47be9922312b68a4227fada96buzbee      NewLIR3(kThumb2Fmrrd, dest_lo, dest_hi, S2d(src_lo, src_hi));
383efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    } else {
384efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      // Handle overlap
385fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (src_hi == dest_lo) {
3861fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegCopy(dest_hi, src_hi);
3871fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegCopy(dest_lo, src_lo);
388efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      } else {
3891fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegCopy(dest_lo, src_lo);
3901fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegCopy(dest_hi, src_hi);
391efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      }
392efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    }
393efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
394efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
395efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
396efc6369224b036a1fb77849f7ae65b3492c832c0buzbee// Table of magic divisors
397efc6369224b036a1fb77849f7ae65b3492c832c0buzbeestruct MagicTable {
398efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  uint32_t magic;
399efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  uint32_t shift;
400efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  DividePattern pattern;
401efc6369224b036a1fb77849f7ae65b3492c832c0buzbee};
402efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
403fa57c47f1b72916371a9c2d5c1389219bce655b4buzbeestatic const MagicTable magic_table[] = {
404efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0, 0, DivideNone},        // 0
405efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0, 0, DivideNone},        // 1
406efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0, 0, DivideNone},        // 2
407efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0x55555556, 0, Divide3},  // 3
408efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0, 0, DivideNone},        // 4
409efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0x66666667, 1, Divide5},  // 5
410efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0x2AAAAAAB, 0, Divide3},  // 6
411efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0x92492493, 2, Divide7},  // 7
412efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0, 0, DivideNone},        // 8
413efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0x38E38E39, 1, Divide5},  // 9
414efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0x66666667, 2, Divide5},  // 10
415efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0x2E8BA2E9, 1, Divide5},  // 11
416efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0x2AAAAAAB, 1, Divide5},  // 12
417efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0x4EC4EC4F, 2, Divide5},  // 13
418efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0x92492493, 3, Divide7},  // 14
419efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0x88888889, 3, Divide7},  // 15
420efc6369224b036a1fb77849f7ae65b3492c832c0buzbee};
421efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
422efc6369224b036a1fb77849f7ae65b3492c832c0buzbee// Integer division by constant via reciprocal multiply (Hacker's Delight, 10-4)
42311b63d13f0a3be0f74390b66b58614a37f9aa6c1buzbeebool ArmMir2Lir::SmallLiteralDivRem(Instruction::Code dalvik_opcode, bool is_div,
4242ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                                    RegLocation rl_src, RegLocation rl_dest, int lit) {
425fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if ((lit < 0) || (lit >= static_cast<int>(sizeof(magic_table)/sizeof(magic_table[0])))) {
426efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    return false;
427efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
428fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  DividePattern pattern = magic_table[lit].pattern;
429efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  if (pattern == DivideNone) {
430efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    return false;
431efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
432efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  // Tuning: add rem patterns
43311b63d13f0a3be0f74390b66b58614a37f9aa6c1buzbee  if (!is_div) {
434efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    return false;
435efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
436efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
4371fd3346740dfb7f47be9922312b68a4227fada96buzbee  int r_magic = AllocTemp();
4381fd3346740dfb7f47be9922312b68a4227fada96buzbee  LoadConstant(r_magic, magic_table[lit].magic);
4391fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src = LoadValue(rl_src, kCoreReg);
4401fd3346740dfb7f47be9922312b68a4227fada96buzbee  RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
4411fd3346740dfb7f47be9922312b68a4227fada96buzbee  int r_hi = AllocTemp();
4421fd3346740dfb7f47be9922312b68a4227fada96buzbee  int r_lo = AllocTemp();
4431fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR4(kThumb2Smull, r_lo, r_hi, r_magic, rl_src.low_reg);
444df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom  switch (pattern) {
445efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    case Divide3:
4461fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpRegRegRegShift(kOpSub, rl_result.low_reg, r_hi,
447fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee               rl_src.low_reg, EncodeShift(kArmAsr, 31));
448efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      break;
449efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    case Divide5:
4501fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpRegRegImm(kOpAsr, r_lo, rl_src.low_reg, 31);
4511fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpRegRegRegShift(kOpRsub, rl_result.low_reg, r_lo, r_hi,
452fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee               EncodeShift(kArmAsr, magic_table[lit].shift));
453efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      break;
454efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    case Divide7:
4551fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpRegReg(kOpAdd, r_hi, rl_src.low_reg);
4561fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpRegRegImm(kOpAsr, r_lo, rl_src.low_reg, 31);
4571fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpRegRegRegShift(kOpRsub, rl_result.low_reg, r_lo, r_hi,
458fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee               EncodeShift(kArmAsr, magic_table[lit].shift));
459efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      break;
460efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    default:
461cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      LOG(FATAL) << "Unexpected pattern: " << pattern;
462efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
4631fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValue(rl_dest, rl_result);
464efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return true;
465efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
466efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
4671fd3346740dfb7f47be9922312b68a4227fada96buzbeeLIR* ArmMir2Lir::GenRegMemCheck(ConditionCode c_code,
4682ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                    int reg1, int base, int offset, ThrowKind kind) {
46952a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee  LOG(FATAL) << "Unexpected use of GenRegMemCheck for Arm";
470efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return NULL;
471efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
472efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
4731fd3346740dfb7f47be9922312b68a4227fada96buzbeeRegLocation ArmMir2Lir::GenDivRemLit(RegLocation rl_dest, int reg1, int lit,
4742ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                                     bool is_div) {
47552a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee  LOG(FATAL) << "Unexpected use of GenDivRemLit for Arm";
476fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  return rl_dest;
477efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
478efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
4791fd3346740dfb7f47be9922312b68a4227fada96buzbeeRegLocation ArmMir2Lir::GenDivRem(RegLocation rl_dest, int reg1, int reg2,
4802ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                                  bool is_div) {
48152a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee  LOG(FATAL) << "Unexpected use of GenDivRem for Arm";
482fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  return rl_dest;
483efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
484efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
4852ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrombool ArmMir2Lir::GenInlinedMinMaxInt(CallInfo* info, bool is_min) {
4861fd3346740dfb7f47be9922312b68a4227fada96buzbee  DCHECK_EQ(cu_->instruction_set, kThumb2);
487fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_src1 = info->args[0];
488fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_src2 = info->args[1];
4891fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src1 = LoadValue(rl_src1, kCoreReg);
4901fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src2 = LoadValue(rl_src2, kCoreReg);
4911fd3346740dfb7f47be9922312b68a4227fada96buzbee  RegLocation rl_dest = InlineTarget(info);
4921fd3346740dfb7f47be9922312b68a4227fada96buzbee  RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
4931fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpRegReg(kOpCmp, rl_src1.low_reg, rl_src2.low_reg);
4941fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpIT((is_min) ? kCondGt : kCondLt, "E");
4951fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpRegReg(kOpMov, rl_result.low_reg, rl_src2.low_reg);
4961fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpRegReg(kOpMov, rl_result.low_reg, rl_src1.low_reg);
4971fd3346740dfb7f47be9922312b68a4227fada96buzbee  GenBarrier();
4981fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValue(rl_dest, rl_result);
499efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return true;
500efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
501efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
5022ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid ArmMir2Lir::OpLea(int rBase, int reg1, int reg2, int scale, int offset) {
50352a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee  LOG(FATAL) << "Unexpected use of OpLea for Arm";
504efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
505efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
506468532ea115657709bc32ee498e701a4c71762d4Ian Rogersvoid ArmMir2Lir::OpTlsCmp(ThreadOffset offset, int val) {
50752a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee  LOG(FATAL) << "Unexpected use of OpTlsCmp for Arm";
508efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
509efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
5101fd3346740dfb7f47be9922312b68a4227fada96buzbeebool ArmMir2Lir::GenInlinedCas32(CallInfo* info, bool need_write_barrier) {
5111fd3346740dfb7f47be9922312b68a4227fada96buzbee  DCHECK_EQ(cu_->instruction_set, kThumb2);
512fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  // Unused - RegLocation rl_src_unsafe = info->args[0];
513fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_src_obj= info->args[1];  // Object - known non-null
514fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_src_offset= info->args[2];  // long low
515fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  rl_src_offset.wide = 0;  // ignore high half in info->args[3]
516fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_src_expected= info->args[4];  // int or Object
517fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  RegLocation rl_src_new_value= info->args[5];  // int or Object
5181fd3346740dfb7f47be9922312b68a4227fada96buzbee  RegLocation rl_dest = InlineTarget(info);  // boolean place for result
519efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
520efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
5211bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee  // Release store semantics, get the barrier out of the way.  TODO: revisit
5221fd3346740dfb7f47be9922312b68a4227fada96buzbee  GenMemBarrier(kStoreLoad);
523efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
5241fd3346740dfb7f47be9922312b68a4227fada96buzbee  RegLocation rl_object = LoadValue(rl_src_obj, kCoreReg);
5251fd3346740dfb7f47be9922312b68a4227fada96buzbee  RegLocation rl_new_value = LoadValue(rl_src_new_value, kCoreReg);
526efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
5271fd3346740dfb7f47be9922312b68a4227fada96buzbee  if (need_write_barrier && !mir_graph_->IsConstantNullRef(rl_new_value)) {
528efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    // Mark card for object assuming new value is stored.
5291fd3346740dfb7f47be9922312b68a4227fada96buzbee    MarkGCCard(rl_new_value.low_reg, rl_object.low_reg);
530efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
531efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
5321fd3346740dfb7f47be9922312b68a4227fada96buzbee  RegLocation rl_offset = LoadValue(rl_src_offset, kCoreReg);
533efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
5341fd3346740dfb7f47be9922312b68a4227fada96buzbee  int r_ptr = AllocTemp();
5351fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpRegRegReg(kOpAdd, r_ptr, rl_object.low_reg, rl_offset.low_reg);
536efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
537fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  // Free now unneeded rl_object and rl_offset to give more temps.
5381fd3346740dfb7f47be9922312b68a4227fada96buzbee  ClobberSReg(rl_object.s_reg_low);
5391fd3346740dfb7f47be9922312b68a4227fada96buzbee  FreeTemp(rl_object.low_reg);
5401fd3346740dfb7f47be9922312b68a4227fada96buzbee  ClobberSReg(rl_offset.s_reg_low);
5411fd3346740dfb7f47be9922312b68a4227fada96buzbee  FreeTemp(rl_offset.low_reg);
542efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
5432de2aa1a96dfa5bebc004f29b5dbfafd37039ceeJeff Hao  RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
5442de2aa1a96dfa5bebc004f29b5dbfafd37039ceeJeff Hao  LoadConstant(rl_result.low_reg, 0);  // r_result := 0
545efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
5462de2aa1a96dfa5bebc004f29b5dbfafd37039ceeJeff Hao  // while ([r_ptr] == rExpected && r_result == 0) {
547fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  //   [r_ptr] <- r_new_value && r_result := success ? 0 : 1
548fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  //   r_result ^= 1
549efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  // }
5502de2aa1a96dfa5bebc004f29b5dbfafd37039ceeJeff Hao  int r_old_value = AllocTemp();
5512de2aa1a96dfa5bebc004f29b5dbfafd37039ceeJeff Hao  LIR* target = NewLIR0(kPseudoTargetLabel);
5522de2aa1a96dfa5bebc004f29b5dbfafd37039ceeJeff Hao  NewLIR3(kThumb2Ldrex, r_old_value, r_ptr, 0);
5532de2aa1a96dfa5bebc004f29b5dbfafd37039ceeJeff Hao
5542de2aa1a96dfa5bebc004f29b5dbfafd37039ceeJeff Hao  RegLocation rl_expected = LoadValue(rl_src_expected, kCoreReg);
5551fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpRegReg(kOpCmp, r_old_value, rl_expected.low_reg);
5561fd3346740dfb7f47be9922312b68a4227fada96buzbee  FreeTemp(r_old_value);  // Now unneeded.
5572de2aa1a96dfa5bebc004f29b5dbfafd37039ceeJeff Hao  OpIT(kCondEq, "TT");
5582de2aa1a96dfa5bebc004f29b5dbfafd37039ceeJeff Hao  NewLIR4(kThumb2Strex /* eq */, rl_result.low_reg, rl_new_value.low_reg, r_ptr, 0);
5591fd3346740dfb7f47be9922312b68a4227fada96buzbee  FreeTemp(r_ptr);  // Now unneeded.
5602de2aa1a96dfa5bebc004f29b5dbfafd37039ceeJeff Hao  OpRegImm(kOpXor /* eq */, rl_result.low_reg, 1);
5612de2aa1a96dfa5bebc004f29b5dbfafd37039ceeJeff Hao  OpRegImm(kOpCmp /* eq */, rl_result.low_reg, 0);
5622de2aa1a96dfa5bebc004f29b5dbfafd37039ceeJeff Hao  OpCondBranch(kCondEq, target);
563efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
5641fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValue(rl_dest, rl_result);
565efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
566efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return true;
567efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
568efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
5692ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromLIR* ArmMir2Lir::OpPcRelLoad(int reg, LIR* target) {
5701fd3346740dfb7f47be9922312b68a4227fada96buzbee  return RawLIR(current_dalvik_offset_, kThumb2LdrPcRel12, reg, 0, 0, 0, 0, target);
571efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
572efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
5732ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromLIR* ArmMir2Lir::OpVldm(int rBase, int count) {
5741fd3346740dfb7f47be9922312b68a4227fada96buzbee  return NewLIR3(kThumb2Vldms, rBase, fr0, count);
575efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
576efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
5772ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromLIR* ArmMir2Lir::OpVstm(int rBase, int count) {
5781fd3346740dfb7f47be9922312b68a4227fada96buzbee  return NewLIR3(kThumb2Vstms, rBase, fr0, count);
579efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
580efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
5811fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::GenMultiplyByTwoBitMultiplier(RegLocation rl_src,
58202031b185b4653e6c72e21f7a51238b903f6d638buzbee                                               RegLocation rl_result, int lit,
5832ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                                               int first_bit, int second_bit) {
5841fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpRegRegRegShift(kOpAdd, rl_result.low_reg, rl_src.low_reg, rl_src.low_reg,
585fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                   EncodeShift(kArmLsl, second_bit - first_bit));
586fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (first_bit != 0) {
5871fd3346740dfb7f47be9922312b68a4227fada96buzbee    OpRegRegImm(kOpLsl, rl_result.low_reg, rl_result.low_reg, first_bit);
588efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
589efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
590efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
5912ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid ArmMir2Lir::GenDivZeroCheck(int reg_lo, int reg_hi) {
5921fd3346740dfb7f47be9922312b68a4227fada96buzbee  int t_reg = AllocTemp();
5931fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR4(kThumb2OrrRRRs, t_reg, reg_lo, reg_hi, 0);
5941fd3346740dfb7f47be9922312b68a4227fada96buzbee  FreeTemp(t_reg);
5951fd3346740dfb7f47be9922312b68a4227fada96buzbee  GenCheck(kCondEq, kThrowDivZero);
596efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
597efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
598efc6369224b036a1fb77849f7ae65b3492c832c0buzbee// Test suspend flag, return target of taken suspend branch
5992ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromLIR* ArmMir2Lir::OpTestSuspend(LIR* target) {
6001fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR2(kThumbSubRI8, rARM_SUSPEND, 1);
6011fd3346740dfb7f47be9922312b68a4227fada96buzbee  return OpCondBranch((target == NULL) ? kCondEq : kCondNe, target);
602efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
603efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
604efc6369224b036a1fb77849f7ae65b3492c832c0buzbee// Decrement register and branch on condition
6052ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromLIR* ArmMir2Lir::OpDecAndBranch(ConditionCode c_code, int reg, LIR* target) {
606efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  // Combine sub & test using sub setflags encoding here
6071fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR3(kThumb2SubsRRI12, reg, reg, 1);
6081fd3346740dfb7f47be9922312b68a4227fada96buzbee  return OpCondBranch(c_code, target);
609efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
610efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
6112ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid ArmMir2Lir::GenMemBarrier(MemBarrierKind barrier_kind) {
612efc6369224b036a1fb77849f7ae65b3492c832c0buzbee#if ANDROID_SMP != 0
613fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  int dmb_flavor;
6141bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee  // TODO: revisit Arm barrier kinds
615fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  switch (barrier_kind) {
616fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    case kLoadStore: dmb_flavor = kSY; break;
617fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    case kLoadLoad: dmb_flavor = kSY; break;
618fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    case kStoreStore: dmb_flavor = kST; break;
619fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    case kStoreLoad: dmb_flavor = kSY; break;
6201bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee    default:
621fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      LOG(FATAL) << "Unexpected MemBarrierKind: " << barrier_kind;
622fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      dmb_flavor = kSY;  // quiet gcc.
6231bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee      break;
6241bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee  }
6251fd3346740dfb7f47be9922312b68a4227fada96buzbee  LIR* dmb = NewLIR1(kThumb2Dmb, dmb_flavor);
626fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  dmb->def_mask = ENCODE_ALL;
627efc6369224b036a1fb77849f7ae65b3492c832c0buzbee#endif
628efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
629efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
6302ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid ArmMir2Lir::GenNegLong(RegLocation rl_dest, RegLocation rl_src) {
6311fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src = LoadValueWide(rl_src, kCoreReg);
6321fd3346740dfb7f47be9922312b68a4227fada96buzbee  RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
6331fd3346740dfb7f47be9922312b68a4227fada96buzbee  int z_reg = AllocTemp();
6341fd3346740dfb7f47be9922312b68a4227fada96buzbee  LoadConstantNoClobber(z_reg, 0);
635efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  // Check for destructive overlap
636fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (rl_result.low_reg == rl_src.high_reg) {
6371fd3346740dfb7f47be9922312b68a4227fada96buzbee    int t_reg = AllocTemp();
6381fd3346740dfb7f47be9922312b68a4227fada96buzbee    OpRegRegReg(kOpSub, rl_result.low_reg, z_reg, rl_src.low_reg);
6391fd3346740dfb7f47be9922312b68a4227fada96buzbee    OpRegRegReg(kOpSbc, rl_result.high_reg, z_reg, t_reg);
6401fd3346740dfb7f47be9922312b68a4227fada96buzbee    FreeTemp(t_reg);
641efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  } else {
6421fd3346740dfb7f47be9922312b68a4227fada96buzbee    OpRegRegReg(kOpSub, rl_result.low_reg, z_reg, rl_src.low_reg);
6431fd3346740dfb7f47be9922312b68a4227fada96buzbee    OpRegRegReg(kOpSbc, rl_result.high_reg, z_reg, rl_src.high_reg);
644efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
6451fd3346740dfb7f47be9922312b68a4227fada96buzbee  FreeTemp(z_reg);
6461fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValueWide(rl_dest, rl_result);
647efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
648efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
6494ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
6504ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee /*
6514ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  * Check to see if a result pair has a misaligned overlap with an operand pair.  This
6524ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  * is not usual for dx to generate, but it is legal (for now).  In a future rev of
6534ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  * dex, we'll want to make this case illegal.
6544ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  */
6552ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrombool ArmMir2Lir::BadOverlap(RegLocation rl_src, RegLocation rl_dest) {
6564ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  DCHECK(rl_src.wide);
6574ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  DCHECK(rl_dest.wide);
6581fd3346740dfb7f47be9922312b68a4227fada96buzbee  return (abs(mir_graph_->SRegToVReg(rl_src.s_reg_low) - mir_graph_->SRegToVReg(rl_dest.s_reg_low)) == 1);
6594ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee}
6604ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
6611fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::GenMulLong(RegLocation rl_dest, RegLocation rl_src1,
6622ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                            RegLocation rl_src2) {
6634ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    /*
6644ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee     * To pull off inline multiply, we have a worst-case requirement of 8 temporary
6654ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee     * registers.  Normally for Arm, we get 5.  We can get to 6 by including
6664ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee     * lr in the temp set.  The only problematic case is all operands and result are
6674ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee     * distinct, and none have been promoted.  In that case, we can succeed by aggressively
6684ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee     * freeing operand temp registers after they are no longer needed.  All other cases
6694ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee     * can proceed normally.  We'll just punt on the case of the result having a misaligned
6704ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee     * overlap with either operand and send that case to a runtime handler.
6714ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee     */
6724ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    RegLocation rl_result;
6731fd3346740dfb7f47be9922312b68a4227fada96buzbee    if (BadOverlap(rl_src1, rl_dest) || (BadOverlap(rl_src2, rl_dest))) {
674468532ea115657709bc32ee498e701a4c71762d4Ian Rogers      ThreadOffset func_offset = QUICK_ENTRYPOINT_OFFSET(pLmul);
6751fd3346740dfb7f47be9922312b68a4227fada96buzbee      FlushAllRegs();
6761fd3346740dfb7f47be9922312b68a4227fada96buzbee      CallRuntimeHelperRegLocationRegLocation(func_offset, rl_src1, rl_src2, false);
6771fd3346740dfb7f47be9922312b68a4227fada96buzbee      rl_result = GetReturnWide(false);
6781fd3346740dfb7f47be9922312b68a4227fada96buzbee      StoreValueWide(rl_dest, rl_result);
6794ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      return;
6804ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    }
6814ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    // Temporarily add LR to the temp pool, and assign it to tmp1
6821fd3346740dfb7f47be9922312b68a4227fada96buzbee    MarkTemp(rARM_LR);
6831fd3346740dfb7f47be9922312b68a4227fada96buzbee    FreeTemp(rARM_LR);
6844ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    int tmp1 = rARM_LR;
6851fd3346740dfb7f47be9922312b68a4227fada96buzbee    LockTemp(rARM_LR);
6864ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
6871fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src1 = LoadValueWide(rl_src1, kCoreReg);
6881fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src2 = LoadValueWide(rl_src2, kCoreReg);
6894ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
6904ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    bool special_case = true;
6914ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    // If operands are the same, or any pair has been promoted we're not the special case.
6924ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    if ((rl_src1.s_reg_low == rl_src2.s_reg_low) ||
6931fd3346740dfb7f47be9922312b68a4227fada96buzbee        (!IsTemp(rl_src1.low_reg) && !IsTemp(rl_src1.high_reg)) ||
6941fd3346740dfb7f47be9922312b68a4227fada96buzbee        (!IsTemp(rl_src2.low_reg) && !IsTemp(rl_src2.high_reg))) {
6954ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      special_case = false;
6964ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    }
6974ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    // Tuning: if rl_dest has been promoted and is *not* either operand, could use directly.
6981fd3346740dfb7f47be9922312b68a4227fada96buzbee    int res_lo = AllocTemp();
6994ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    int res_hi;
7004ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    if (rl_src1.low_reg == rl_src2.low_reg) {
7011fd3346740dfb7f47be9922312b68a4227fada96buzbee      res_hi = AllocTemp();
7021fd3346740dfb7f47be9922312b68a4227fada96buzbee      NewLIR3(kThumb2MulRRR, tmp1, rl_src1.low_reg, rl_src1.high_reg);
7031fd3346740dfb7f47be9922312b68a4227fada96buzbee      NewLIR4(kThumb2Umull, res_lo, res_hi, rl_src1.low_reg, rl_src1.low_reg);
7041fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpRegRegRegShift(kOpAdd, res_hi, res_hi, tmp1, EncodeShift(kArmLsl, 1));
7054ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    } else {
7064ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      // In the special case, all temps are now allocated
7071fd3346740dfb7f47be9922312b68a4227fada96buzbee      NewLIR3(kThumb2MulRRR, tmp1, rl_src2.low_reg, rl_src1.high_reg);
7084ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      if (special_case) {
7094ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee        DCHECK_NE(rl_src1.low_reg, rl_src2.low_reg);
7104ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee        DCHECK_NE(rl_src1.high_reg, rl_src2.high_reg);
7111fd3346740dfb7f47be9922312b68a4227fada96buzbee        FreeTemp(rl_src1.high_reg);
7124ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      }
7131fd3346740dfb7f47be9922312b68a4227fada96buzbee      res_hi = AllocTemp();
7144ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
7151fd3346740dfb7f47be9922312b68a4227fada96buzbee      NewLIR4(kThumb2Umull, res_lo, res_hi, rl_src2.low_reg, rl_src1.low_reg);
7161fd3346740dfb7f47be9922312b68a4227fada96buzbee      NewLIR4(kThumb2Mla, tmp1, rl_src1.low_reg, rl_src2.high_reg, tmp1);
7171fd3346740dfb7f47be9922312b68a4227fada96buzbee      NewLIR4(kThumb2AddRRR, res_hi, tmp1, res_hi, 0);
7184ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      if (special_case) {
7191fd3346740dfb7f47be9922312b68a4227fada96buzbee        FreeTemp(rl_src1.low_reg);
7201fd3346740dfb7f47be9922312b68a4227fada96buzbee        Clobber(rl_src1.low_reg);
7211fd3346740dfb7f47be9922312b68a4227fada96buzbee        Clobber(rl_src1.high_reg);
7224ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      }
7234ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    }
7241fd3346740dfb7f47be9922312b68a4227fada96buzbee    FreeTemp(tmp1);
7257934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom    rl_result = GetReturnWide(false);  // Just using as a template.
7264ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    rl_result.low_reg = res_lo;
7274ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    rl_result.high_reg = res_hi;
7281fd3346740dfb7f47be9922312b68a4227fada96buzbee    StoreValueWide(rl_dest, rl_result);
7294ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    // Now, restore lr to its non-temp status.
7301fd3346740dfb7f47be9922312b68a4227fada96buzbee    Clobber(rARM_LR);
7311fd3346740dfb7f47be9922312b68a4227fada96buzbee    UnmarkTemp(rARM_LR);
7324ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee}
7334ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
7341fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::GenAddLong(RegLocation rl_dest, RegLocation rl_src1,
7352ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                            RegLocation rl_src2) {
73652a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee  LOG(FATAL) << "Unexpected use of GenAddLong for Arm";
737efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
738efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
7391fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::GenSubLong(RegLocation rl_dest, RegLocation rl_src1,
7402ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                            RegLocation rl_src2) {
74152a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee  LOG(FATAL) << "Unexpected use of GenSubLong for Arm";
742efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
743efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
7441fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::GenAndLong(RegLocation rl_dest, RegLocation rl_src1,
7452ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                            RegLocation rl_src2) {
74652a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee  LOG(FATAL) << "Unexpected use of GenAndLong for Arm";
747efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
748efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
7491fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::GenOrLong(RegLocation rl_dest, RegLocation rl_src1,
7502ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                           RegLocation rl_src2) {
75152a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee  LOG(FATAL) << "Unexpected use of GenOrLong for Arm";
752efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
753efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
7541fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::GenXorLong(RegLocation rl_dest, RegLocation rl_src1,
7552ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                            RegLocation rl_src2) {
756efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  LOG(FATAL) << "Unexpected use of genXoLong for Arm";
757efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
758efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
759e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee/*
760e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee * Generate array load
761e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee */
7621fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::GenArrayGet(int opt_flags, OpSize size, RegLocation rl_array,
7632ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                          RegLocation rl_index, RegLocation rl_dest, int scale) {
764e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  RegisterClass reg_class = oat_reg_class_by_size(size);
7652dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  int len_offset = mirror::Array::LengthOffset().Int32Value();
766e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  int data_offset;
767e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  RegLocation rl_result;
7684ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  bool constant_index = rl_index.is_const;
7691fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_array = LoadValue(rl_array, kCoreReg);
7704ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  if (!constant_index) {
7711fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_index = LoadValue(rl_index, kCoreReg);
7724ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  }
773e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee
774e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  if (rl_dest.wide) {
7752dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers    data_offset = mirror::Array::DataOffset(sizeof(int64_t)).Int32Value();
776e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  } else {
7772dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers    data_offset = mirror::Array::DataOffset(sizeof(int32_t)).Int32Value();
778e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  }
779e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee
7804ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  // If index is constant, just fold it into the data offset
7814ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  if (constant_index) {
7821fd3346740dfb7f47be9922312b68a4227fada96buzbee    data_offset += mir_graph_->ConstantValue(rl_index) << scale;
7834ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  }
7844ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
785e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  /* null object? */
7861fd3346740dfb7f47be9922312b68a4227fada96buzbee  GenNullCheck(rl_array.s_reg_low, rl_array.low_reg, opt_flags);
787e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee
788e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  bool needs_range_check = (!(opt_flags & MIR_IGNORE_RANGE_CHECK));
789e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  int reg_len = INVALID_REG;
790e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  if (needs_range_check) {
7911fd3346740dfb7f47be9922312b68a4227fada96buzbee    reg_len = AllocTemp();
792e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    /* Get len */
7931fd3346740dfb7f47be9922312b68a4227fada96buzbee    LoadWordDisp(rl_array.low_reg, len_offset, reg_len);
794e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  }
7954ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  if (rl_dest.wide || rl_dest.fp || constant_index) {
7964ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    int reg_ptr;
7974ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    if (constant_index) {
7984ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      reg_ptr = rl_array.low_reg;  // NOTE: must not alter reg_ptr in constant case.
7994ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    } else {
8004ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      // No special indexed operation, lea + load w/ displacement
8011fd3346740dfb7f47be9922312b68a4227fada96buzbee      reg_ptr = AllocTemp();
8021fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpRegRegRegShift(kOpAdd, reg_ptr, rl_array.low_reg, rl_index.low_reg,
8034ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee                       EncodeShift(kArmLsl, scale));
8041fd3346740dfb7f47be9922312b68a4227fada96buzbee      FreeTemp(rl_index.low_reg);
8054ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    }
8061fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_result = EvalLoc(rl_dest, reg_class, true);
807e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee
808e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    if (needs_range_check) {
8094ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      if (constant_index) {
8101fd3346740dfb7f47be9922312b68a4227fada96buzbee        GenImmedCheck(kCondLs, reg_len, mir_graph_->ConstantValue(rl_index), kThrowConstantArrayBounds);
8114ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      } else {
8121fd3346740dfb7f47be9922312b68a4227fada96buzbee        GenRegRegCheck(kCondLs, reg_len, rl_index.low_reg, kThrowArrayBounds);
8134ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      }
8141fd3346740dfb7f47be9922312b68a4227fada96buzbee      FreeTemp(reg_len);
815e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    }
816e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    if (rl_dest.wide) {
8171fd3346740dfb7f47be9922312b68a4227fada96buzbee      LoadBaseDispWide(reg_ptr, data_offset, rl_result.low_reg, rl_result.high_reg, INVALID_SREG);
8184ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      if (!constant_index) {
8191fd3346740dfb7f47be9922312b68a4227fada96buzbee        FreeTemp(reg_ptr);
8204ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      }
8211fd3346740dfb7f47be9922312b68a4227fada96buzbee      StoreValueWide(rl_dest, rl_result);
822e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    } else {
8231fd3346740dfb7f47be9922312b68a4227fada96buzbee      LoadBaseDisp(reg_ptr, data_offset, rl_result.low_reg, size, INVALID_SREG);
8244ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      if (!constant_index) {
8251fd3346740dfb7f47be9922312b68a4227fada96buzbee        FreeTemp(reg_ptr);
8264ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      }
8271fd3346740dfb7f47be9922312b68a4227fada96buzbee      StoreValue(rl_dest, rl_result);
828e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    }
829e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  } else {
830e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    // Offset base, then use indexed load
8311fd3346740dfb7f47be9922312b68a4227fada96buzbee    int reg_ptr = AllocTemp();
8321fd3346740dfb7f47be9922312b68a4227fada96buzbee    OpRegRegImm(kOpAdd, reg_ptr, rl_array.low_reg, data_offset);
8331fd3346740dfb7f47be9922312b68a4227fada96buzbee    FreeTemp(rl_array.low_reg);
8341fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_result = EvalLoc(rl_dest, reg_class, true);
835e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee
836e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    if (needs_range_check) {
837e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee      // TODO: change kCondCS to a more meaningful name, is the sense of
838e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee      // carry-set/clear flipped?
8391fd3346740dfb7f47be9922312b68a4227fada96buzbee      GenRegRegCheck(kCondCs, rl_index.low_reg, reg_len, kThrowArrayBounds);
8401fd3346740dfb7f47be9922312b68a4227fada96buzbee      FreeTemp(reg_len);
841e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    }
8421fd3346740dfb7f47be9922312b68a4227fada96buzbee    LoadBaseIndexed(reg_ptr, rl_index.low_reg, rl_result.low_reg, scale, size);
8431fd3346740dfb7f47be9922312b68a4227fada96buzbee    FreeTemp(reg_ptr);
8441fd3346740dfb7f47be9922312b68a4227fada96buzbee    StoreValue(rl_dest, rl_result);
845e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  }
846e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee}
847e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee
848e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee/*
849e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee * Generate array store
850e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee *
851e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee */
8521fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::GenArrayPut(int opt_flags, OpSize size, RegLocation rl_array,
8532ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                          RegLocation rl_index, RegLocation rl_src, int scale) {
854e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  RegisterClass reg_class = oat_reg_class_by_size(size);
8552dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  int len_offset = mirror::Array::LengthOffset().Int32Value();
856e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  int data_offset;
8574ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  bool constant_index = rl_index.is_const;
858e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee
8594ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  if (rl_src.wide) {
8602dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers    data_offset = mirror::Array::DataOffset(sizeof(int64_t)).Int32Value();
861e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  } else {
8622dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers    data_offset = mirror::Array::DataOffset(sizeof(int32_t)).Int32Value();
863e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  }
864e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee
8654ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  // If index is constant, just fold it into the data offset.
8664ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  if (constant_index) {
8671fd3346740dfb7f47be9922312b68a4227fada96buzbee    data_offset += mir_graph_->ConstantValue(rl_index) << scale;
8684ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  }
8694ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
8701fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_array = LoadValue(rl_array, kCoreReg);
8714ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  if (!constant_index) {
8721fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_index = LoadValue(rl_index, kCoreReg);
8734ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  }
8744ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
8754ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  int reg_ptr;
8764ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  if (constant_index) {
8774ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    reg_ptr = rl_array.low_reg;
8781fd3346740dfb7f47be9922312b68a4227fada96buzbee  } else if (IsTemp(rl_array.low_reg)) {
8791fd3346740dfb7f47be9922312b68a4227fada96buzbee    Clobber(rl_array.low_reg);
880e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    reg_ptr = rl_array.low_reg;
881e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  } else {
8821fd3346740dfb7f47be9922312b68a4227fada96buzbee    reg_ptr = AllocTemp();
883e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  }
884e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee
885e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  /* null object? */
8861fd3346740dfb7f47be9922312b68a4227fada96buzbee  GenNullCheck(rl_array.s_reg_low, rl_array.low_reg, opt_flags);
887e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee
888e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  bool needs_range_check = (!(opt_flags & MIR_IGNORE_RANGE_CHECK));
889e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  int reg_len = INVALID_REG;
890e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  if (needs_range_check) {
8911fd3346740dfb7f47be9922312b68a4227fada96buzbee    reg_len = AllocTemp();
8927934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom    // NOTE: max live temps(4) here.
893e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    /* Get len */
8941fd3346740dfb7f47be9922312b68a4227fada96buzbee    LoadWordDisp(rl_array.low_reg, len_offset, reg_len);
895e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  }
896e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  /* at this point, reg_ptr points to array, 2 live temps */
8974ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  if (rl_src.wide || rl_src.fp || constant_index) {
898e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    if (rl_src.wide) {
8991fd3346740dfb7f47be9922312b68a4227fada96buzbee      rl_src = LoadValueWide(rl_src, reg_class);
900e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    } else {
9011fd3346740dfb7f47be9922312b68a4227fada96buzbee      rl_src = LoadValue(rl_src, reg_class);
902e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    }
9034ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    if (!constant_index) {
9041fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpRegRegRegShift(kOpAdd, reg_ptr, rl_array.low_reg, rl_index.low_reg,
9054ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee                       EncodeShift(kArmLsl, scale));
9064ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    }
907e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    if (needs_range_check) {
9084ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      if (constant_index) {
9091fd3346740dfb7f47be9922312b68a4227fada96buzbee        GenImmedCheck(kCondLs, reg_len, mir_graph_->ConstantValue(rl_index), kThrowConstantArrayBounds);
9104ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      } else {
9111fd3346740dfb7f47be9922312b68a4227fada96buzbee        GenRegRegCheck(kCondLs, reg_len, rl_index.low_reg, kThrowArrayBounds);
9124ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      }
9131fd3346740dfb7f47be9922312b68a4227fada96buzbee      FreeTemp(reg_len);
914e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    }
9154ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
916e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    if (rl_src.wide) {
9171fd3346740dfb7f47be9922312b68a4227fada96buzbee      StoreBaseDispWide(reg_ptr, data_offset, rl_src.low_reg, rl_src.high_reg);
918e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    } else {
9191fd3346740dfb7f47be9922312b68a4227fada96buzbee      StoreBaseDisp(reg_ptr, data_offset, rl_src.low_reg, size);
920e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    }
921e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  } else {
922e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    /* reg_ptr -> array data */
9231fd3346740dfb7f47be9922312b68a4227fada96buzbee    OpRegRegImm(kOpAdd, reg_ptr, rl_array.low_reg, data_offset);
9241fd3346740dfb7f47be9922312b68a4227fada96buzbee    rl_src = LoadValue(rl_src, reg_class);
925e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    if (needs_range_check) {
9261fd3346740dfb7f47be9922312b68a4227fada96buzbee      GenRegRegCheck(kCondCs, rl_index.low_reg, reg_len, kThrowArrayBounds);
9271fd3346740dfb7f47be9922312b68a4227fada96buzbee      FreeTemp(reg_len);
928e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    }
9291fd3346740dfb7f47be9922312b68a4227fada96buzbee    StoreBaseIndexed(reg_ptr, rl_index.low_reg, rl_src.low_reg,
930e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee                     scale, size);
931e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  }
9324ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  if (!constant_index) {
9331fd3346740dfb7f47be9922312b68a4227fada96buzbee    FreeTemp(reg_ptr);
9344ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  }
935e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee}
936e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee
937e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee/*
938e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee * Generate array store
939e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee *
940e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee */
9411fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::GenArrayObjPut(int opt_flags, RegLocation rl_array,
9422ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                             RegLocation rl_index, RegLocation rl_src, int scale) {
9432dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  int len_offset = mirror::Array::LengthOffset().Int32Value();
9442dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  int data_offset = mirror::Array::DataOffset(sizeof(mirror::Object*)).Int32Value();
945e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee
9461fd3346740dfb7f47be9922312b68a4227fada96buzbee  FlushAllRegs();  // Use explicit registers
9471fd3346740dfb7f47be9922312b68a4227fada96buzbee  LockCallTemps();
948e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee
949e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  int r_value = TargetReg(kArg0);  // Register holding value
950e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  int r_array_class = TargetReg(kArg1);  // Register holding array's Class
951e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  int r_array = TargetReg(kArg2);  // Register holding array
952e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  int r_index = TargetReg(kArg3);  // Register holding index into array
953e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee
9541fd3346740dfb7f47be9922312b68a4227fada96buzbee  LoadValueDirectFixed(rl_array, r_array);  // Grab array
9551fd3346740dfb7f47be9922312b68a4227fada96buzbee  LoadValueDirectFixed(rl_src, r_value);  // Grab value
9561fd3346740dfb7f47be9922312b68a4227fada96buzbee  LoadValueDirectFixed(rl_index, r_index);  // Grab index
957e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee
9581fd3346740dfb7f47be9922312b68a4227fada96buzbee  GenNullCheck(rl_array.s_reg_low, r_array, opt_flags);  // NPE?
959e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee
960e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  // Store of null?
9611fd3346740dfb7f47be9922312b68a4227fada96buzbee  LIR* null_value_check = OpCmpImmBranch(kCondEq, r_value, 0, NULL);
962e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee
963e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  // Get the array's class.
9641fd3346740dfb7f47be9922312b68a4227fada96buzbee  LoadWordDisp(r_array, mirror::Object::ClassOffset().Int32Value(), r_array_class);
965468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  CallRuntimeHelperRegReg(QUICK_ENTRYPOINT_OFFSET(pCanPutArrayElement), r_value,
966e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee                          r_array_class, true);
967e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  // Redo LoadValues in case they didn't survive the call.
9681fd3346740dfb7f47be9922312b68a4227fada96buzbee  LoadValueDirectFixed(rl_array, r_array);  // Reload array
9691fd3346740dfb7f47be9922312b68a4227fada96buzbee  LoadValueDirectFixed(rl_index, r_index);  // Reload index
9701fd3346740dfb7f47be9922312b68a4227fada96buzbee  LoadValueDirectFixed(rl_src, r_value);  // Reload value
971e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  r_array_class = INVALID_REG;
972e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee
973e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  // Branch here if value to be stored == null
9741fd3346740dfb7f47be9922312b68a4227fada96buzbee  LIR* target = NewLIR0(kPseudoTargetLabel);
975e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  null_value_check->target = target;
976e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee
977e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  bool needs_range_check = (!(opt_flags & MIR_IGNORE_RANGE_CHECK));
978e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  int reg_len = INVALID_REG;
979e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  if (needs_range_check) {
980e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee    reg_len = TargetReg(kArg1);
9811fd3346740dfb7f47be9922312b68a4227fada96buzbee    LoadWordDisp(r_array, len_offset, reg_len);  // Get len
982e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  }
983e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  /* r_ptr -> array data */
9841fd3346740dfb7f47be9922312b68a4227fada96buzbee  int r_ptr = AllocTemp();
9851fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpRegRegImm(kOpAdd, r_ptr, r_array, data_offset);
986e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  if (needs_range_check) {
9871fd3346740dfb7f47be9922312b68a4227fada96buzbee    GenRegRegCheck(kCondCs, r_index, reg_len, kThrowArrayBounds);
988e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  }
9891fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreBaseIndexed(r_ptr, r_index, r_value, scale, kWord);
9901fd3346740dfb7f47be9922312b68a4227fada96buzbee  FreeTemp(r_ptr);
9911fd3346740dfb7f47be9922312b68a4227fada96buzbee  FreeTemp(r_index);
9921fd3346740dfb7f47be9922312b68a4227fada96buzbee  if (!mir_graph_->IsConstantNullRef(rl_src)) {
9931fd3346740dfb7f47be9922312b68a4227fada96buzbee    MarkGCCard(r_value, r_array);
9946a791b26577a61fd14f4836c795d616869bd2957buzbee  }
995e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee}
996e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee
9971fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::GenShiftImmOpLong(Instruction::Code opcode,
9982ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                                   RegLocation rl_dest, RegLocation rl_src, RegLocation rl_shift) {
9991fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src = LoadValueWide(rl_src, kCoreReg);
10004ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  // Per spec, we only care about low 6 bits of shift amount.
10011fd3346740dfb7f47be9922312b68a4227fada96buzbee  int shift_amount = mir_graph_->ConstantValue(rl_shift) & 0x3f;
10024ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  if (shift_amount == 0) {
10031fd3346740dfb7f47be9922312b68a4227fada96buzbee    StoreValueWide(rl_dest, rl_src);
1004a5954be0aac5edd892fb31a209960543d00e4500buzbee    return;
10054ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  }
10061fd3346740dfb7f47be9922312b68a4227fada96buzbee  if (BadOverlap(rl_src, rl_dest)) {
10071fd3346740dfb7f47be9922312b68a4227fada96buzbee    GenShiftOpLong(opcode, rl_dest, rl_src, rl_shift);
1008a5954be0aac5edd892fb31a209960543d00e4500buzbee    return;
10094ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  }
10101fd3346740dfb7f47be9922312b68a4227fada96buzbee  RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
1011df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom  switch (opcode) {
10124ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::SHL_LONG:
10134ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::SHL_LONG_2ADDR:
10144ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      if (shift_amount == 1) {
10151fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegReg(kOpAdd, rl_result.low_reg, rl_src.low_reg, rl_src.low_reg);
10161fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegReg(kOpAdc, rl_result.high_reg, rl_src.high_reg, rl_src.high_reg);
10174ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      } else if (shift_amount == 32) {
10181fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegCopy(rl_result.high_reg, rl_src.low_reg);
10191fd3346740dfb7f47be9922312b68a4227fada96buzbee        LoadConstant(rl_result.low_reg, 0);
10204ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      } else if (shift_amount > 31) {
10211fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegImm(kOpLsl, rl_result.high_reg, rl_src.low_reg, shift_amount - 32);
10221fd3346740dfb7f47be9922312b68a4227fada96buzbee        LoadConstant(rl_result.low_reg, 0);
10234ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      } else {
10241fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegImm(kOpLsl, rl_result.high_reg, rl_src.high_reg, shift_amount);
10251fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegRegShift(kOpOr, rl_result.high_reg, rl_result.high_reg, rl_src.low_reg,
10264ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee                         EncodeShift(kArmLsr, 32 - shift_amount));
10271fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegImm(kOpLsl, rl_result.low_reg, rl_src.low_reg, shift_amount);
10284ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      }
10294ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      break;
10304ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::SHR_LONG:
10314ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::SHR_LONG_2ADDR:
10324ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      if (shift_amount == 32) {
10331fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegCopy(rl_result.low_reg, rl_src.high_reg);
10341fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegImm(kOpAsr, rl_result.high_reg, rl_src.high_reg, 31);
10354ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      } else if (shift_amount > 31) {
10361fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegImm(kOpAsr, rl_result.low_reg, rl_src.high_reg, shift_amount - 32);
10371fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegImm(kOpAsr, rl_result.high_reg, rl_src.high_reg, 31);
10384ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      } else {
10391fd3346740dfb7f47be9922312b68a4227fada96buzbee        int t_reg = AllocTemp();
10401fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegImm(kOpLsr, t_reg, rl_src.low_reg, shift_amount);
10411fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegRegShift(kOpOr, rl_result.low_reg, t_reg, rl_src.high_reg,
10424ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee                         EncodeShift(kArmLsl, 32 - shift_amount));
10431fd3346740dfb7f47be9922312b68a4227fada96buzbee        FreeTemp(t_reg);
10441fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegImm(kOpAsr, rl_result.high_reg, rl_src.high_reg, shift_amount);
10454ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      }
10464ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      break;
10474ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::USHR_LONG:
10484ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::USHR_LONG_2ADDR:
10494ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      if (shift_amount == 32) {
10501fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegCopy(rl_result.low_reg, rl_src.high_reg);
10511fd3346740dfb7f47be9922312b68a4227fada96buzbee        LoadConstant(rl_result.high_reg, 0);
10524ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      } else if (shift_amount > 31) {
10531fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegImm(kOpLsr, rl_result.low_reg, rl_src.high_reg, shift_amount - 32);
10541fd3346740dfb7f47be9922312b68a4227fada96buzbee        LoadConstant(rl_result.high_reg, 0);
10554ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      } else {
10561fd3346740dfb7f47be9922312b68a4227fada96buzbee        int t_reg = AllocTemp();
10571fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegImm(kOpLsr, t_reg, rl_src.low_reg, shift_amount);
10581fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegRegShift(kOpOr, rl_result.low_reg, t_reg, rl_src.high_reg,
10594ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee                         EncodeShift(kArmLsl, 32 - shift_amount));
10601fd3346740dfb7f47be9922312b68a4227fada96buzbee        FreeTemp(t_reg);
10611fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegImm(kOpLsr, rl_result.high_reg, rl_src.high_reg, shift_amount);
10624ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      }
10634ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      break;
10644ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    default:
10654ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      LOG(FATAL) << "Unexpected case";
10664ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  }
10671fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValueWide(rl_dest, rl_result);
10684ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee}
10694ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
10701fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid ArmMir2Lir::GenArithImmOpLong(Instruction::Code opcode,
10712ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                                   RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) {
10724ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  if ((opcode == Instruction::SUB_LONG_2ADDR) || (opcode == Instruction::SUB_LONG)) {
10734ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    if (!rl_src2.is_const) {
10744ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      // Don't bother with special handling for subtract from immediate.
10751fd3346740dfb7f47be9922312b68a4227fada96buzbee      GenArithOpLong(opcode, rl_dest, rl_src1, rl_src2);
1076a5954be0aac5edd892fb31a209960543d00e4500buzbee      return;
10774ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    }
10784ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  } else {
10794ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    // Normalize
10804ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    if (!rl_src2.is_const) {
10814ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      DCHECK(rl_src1.is_const);
10824ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      RegLocation rl_temp = rl_src1;
10834ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      rl_src1 = rl_src2;
10844ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      rl_src2 = rl_temp;
10854ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    }
10864ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  }
10871fd3346740dfb7f47be9922312b68a4227fada96buzbee  if (BadOverlap(rl_src1, rl_dest)) {
10881fd3346740dfb7f47be9922312b68a4227fada96buzbee    GenArithOpLong(opcode, rl_dest, rl_src1, rl_src2);
1089a5954be0aac5edd892fb31a209960543d00e4500buzbee    return;
10904ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  }
10914ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  DCHECK(rl_src2.is_const);
10921fd3346740dfb7f47be9922312b68a4227fada96buzbee  int64_t val = mir_graph_->ConstantValueWide(rl_src2);
10934ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  uint32_t val_lo = Low32Bits(val);
10944ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  uint32_t val_hi = High32Bits(val);
10954ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  int32_t mod_imm_lo = ModifiedImmediate(val_lo);
10964ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  int32_t mod_imm_hi = ModifiedImmediate(val_hi);
10974ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
10984ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  // Only a subset of add/sub immediate instructions set carry - so bail if we don't fit
1099df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom  switch (opcode) {
11004ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::ADD_LONG:
11014ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::ADD_LONG_2ADDR:
11024ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::SUB_LONG:
11034ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::SUB_LONG_2ADDR:
11044ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      if ((mod_imm_lo < 0) || (mod_imm_hi < 0)) {
11051fd3346740dfb7f47be9922312b68a4227fada96buzbee        GenArithOpLong(opcode, rl_dest, rl_src1, rl_src2);
1106a5954be0aac5edd892fb31a209960543d00e4500buzbee        return;
11074ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      }
11084ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      break;
11094ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    default:
11104ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      break;
11114ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  }
11121fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src1 = LoadValueWide(rl_src1, kCoreReg);
11131fd3346740dfb7f47be9922312b68a4227fada96buzbee  RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
11144ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  // NOTE: once we've done the EvalLoc on dest, we can no longer bail.
11154ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  switch (opcode) {
11164ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::ADD_LONG:
11174ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::ADD_LONG_2ADDR:
11181fd3346740dfb7f47be9922312b68a4227fada96buzbee      NewLIR3(kThumb2AddRRI8, rl_result.low_reg, rl_src1.low_reg, mod_imm_lo);
11191fd3346740dfb7f47be9922312b68a4227fada96buzbee      NewLIR3(kThumb2AdcRRI8, rl_result.high_reg, rl_src1.high_reg, mod_imm_hi);
11204ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      break;
11214ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::OR_LONG:
11224ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::OR_LONG_2ADDR:
11234ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      if ((val_lo != 0) || (rl_result.low_reg != rl_src1.low_reg)) {
11241fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegImm(kOpOr, rl_result.low_reg, rl_src1.low_reg, val_lo);
11254ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      }
11264ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      if ((val_hi != 0) || (rl_result.high_reg != rl_src1.high_reg)) {
11271fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegImm(kOpOr, rl_result.high_reg, rl_src1.high_reg, val_hi);
11284ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      }
11294ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      break;
11304ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::XOR_LONG:
11314ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::XOR_LONG_2ADDR:
11321fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpRegRegImm(kOpXor, rl_result.low_reg, rl_src1.low_reg, val_lo);
11331fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpRegRegImm(kOpXor, rl_result.high_reg, rl_src1.high_reg, val_hi);
11344ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      break;
11354ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::AND_LONG:
11364ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::AND_LONG_2ADDR:
11374ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      if ((val_lo != 0xffffffff) || (rl_result.low_reg != rl_src1.low_reg)) {
11381fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegImm(kOpAnd, rl_result.low_reg, rl_src1.low_reg, val_lo);
11394ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      }
11404ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      if ((val_hi != 0xffffffff) || (rl_result.high_reg != rl_src1.high_reg)) {
11411fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegRegImm(kOpAnd, rl_result.high_reg, rl_src1.high_reg, val_hi);
11424ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      }
11434ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      break;
11444ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::SUB_LONG_2ADDR:
11454ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    case Instruction::SUB_LONG:
11461fd3346740dfb7f47be9922312b68a4227fada96buzbee      NewLIR3(kThumb2SubRRI8, rl_result.low_reg, rl_src1.low_reg, mod_imm_lo);
11471fd3346740dfb7f47be9922312b68a4227fada96buzbee      NewLIR3(kThumb2SbcRRI8, rl_result.high_reg, rl_src1.high_reg, mod_imm_hi);
11484ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      break;
11494ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    default:
11504ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      LOG(FATAL) << "Unexpected opcode " << opcode;
11514ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  }
11521fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValueWide(rl_dest, rl_result);
11534ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee}
11544ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
1155efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}  // namespace art
1156