int_arm.cc revision 1bc37c60da71c923ea9a2e99d31ba1b3d76d79a8
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
19efc6369224b036a1fb77849f7ae65b3492c832c0buzbee#include "oat_compilation_unit.h"
20efc6369224b036a1fb77849f7ae65b3492c832c0buzbee#include "oat/runtime/oat_support_entrypoints.h"
211bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee#include "arm_lir.h"
221bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee#include "../codegen_util.h"
231bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee#include "../ralloc_util.h"
24efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
25efc6369224b036a1fb77849f7ae65b3492c832c0buzbeenamespace art {
26efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
27efc6369224b036a1fb77849f7ae65b3492c832c0buzbeeLIR* opCmpBranch(CompilationUnit* cUnit, ConditionCode cond, int src1,
28efc6369224b036a1fb77849f7ae65b3492c832c0buzbee         int src2, LIR* target)
29efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{
30efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  opRegReg(cUnit, kOpCmp, src1, src2);
31efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return opCondBranch(cUnit, cond, target);
32efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
33efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
34efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/*
35efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Generate a Thumb2 IT instruction, which can nullify up to
36efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * four subsequent instructions based on a condition and its
37efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * inverse.  The condition applies to the first instruction, which
38efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * is executed if the condition is met.  The string "guide" consists
39efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * of 0 to 3 chars, and applies to the 2nd through 4th instruction.
40efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * A "T" means the instruction is executed if the condition is
41efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * met, and an "E" means the instruction is executed if the condition
42efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * is not met.
43efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */
44efc6369224b036a1fb77849f7ae65b3492c832c0buzbeeLIR* opIT(CompilationUnit* cUnit, ArmConditionCode code, const char* guide)
45efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{
46efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  int mask;
47efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  int condBit = code & 1;
48efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  int altBit = condBit ^ 1;
49efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  int mask3 = 0;
50efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  int mask2 = 0;
51efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  int mask1 = 0;
52efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
53efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  //Note: case fallthroughs intentional
54efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  switch (strlen(guide)) {
55efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    case 3:
56efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      mask1 = (guide[2] == 'T') ? condBit : altBit;
57efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    case 2:
58efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      mask2 = (guide[1] == 'T') ? condBit : altBit;
59efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    case 1:
60efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      mask3 = (guide[0] == 'T') ? condBit : altBit;
61efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      break;
62efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    case 0:
63efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      break;
64efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    default:
65efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      LOG(FATAL) << "OAT: bad case in opIT";
66efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
67efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  mask = (mask3 << 3) | (mask2 << 2) | (mask1 << 1) |
68efc6369224b036a1fb77849f7ae65b3492c832c0buzbee       (1 << (3 - strlen(guide)));
69efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return newLIR2(cUnit, kThumb2It, code, mask);
70efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
71efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
72efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/*
73efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * 64-bit 3way compare function.
74efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *     mov   rX, #-1
75efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *     cmp   op1hi, op2hi
76efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *     blt   done
77efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *     bgt   flip
78efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *     sub   rX, op1lo, op2lo (treat as unsigned)
79efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *     beq   done
80efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *     ite   hi
81efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *     mov(hi)   rX, #-1
82efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *     mov(!hi)  rX, #1
83efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * flip:
84efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *     neg   rX
85efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * done:
86efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */
87efc6369224b036a1fb77849f7ae65b3492c832c0buzbeevoid genCmpLong(CompilationUnit* cUnit, RegLocation rlDest,
88efc6369224b036a1fb77849f7ae65b3492c832c0buzbee        RegLocation rlSrc1, RegLocation rlSrc2)
89efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{
90efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  LIR* target1;
91efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  LIR* target2;
92efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  rlSrc1 = loadValueWide(cUnit, rlSrc1, kCoreReg);
93efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg);
94efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  int tReg = oatAllocTemp(cUnit);
95efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  loadConstant(cUnit, tReg, -1);
96efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  opRegReg(cUnit, kOpCmp, rlSrc1.highReg, rlSrc2.highReg);
97efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  LIR* branch1 = opCondBranch(cUnit, kCondLt, NULL);
98efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  LIR* branch2 = opCondBranch(cUnit, kCondGt, NULL);
99efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  opRegRegReg(cUnit, kOpSub, tReg, rlSrc1.lowReg, rlSrc2.lowReg);
100efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  LIR* branch3 = opCondBranch(cUnit, kCondEq, NULL);
101efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
102efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  opIT(cUnit, kArmCondHi, "E");
103efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  newLIR2(cUnit, kThumb2MovImmShift, tReg, modifiedImmediate(-1));
104efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  loadConstant(cUnit, tReg, 1);
105efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  genBarrier(cUnit);
106efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
107efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  target2 = newLIR0(cUnit, kPseudoTargetLabel);
108efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  opRegReg(cUnit, kOpNeg, tReg, tReg);
109efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
110efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  target1 = newLIR0(cUnit, kPseudoTargetLabel);
111efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
112efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  RegLocation rlTemp = locCReturn(); // Just using as template, will change
113efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  rlTemp.lowReg = tReg;
114efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  storeValue(cUnit, rlDest, rlTemp);
115efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  oatFreeTemp(cUnit, tReg);
116efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
117cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee  branch1->target = target1;
118cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee  branch2->target = target2;
119efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  branch3->target = branch1->target;
120efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
121efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
122efc6369224b036a1fb77849f7ae65b3492c832c0buzbeevoid genFusedLongCmpBranch(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir)
123efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{
124efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  LIR* labelList = cUnit->blockLabelList;
125efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  LIR* taken = &labelList[bb->taken->id];
126efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  LIR* notTaken = &labelList[bb->fallThrough->id];
127efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  RegLocation rlSrc1 = oatGetSrcWide(cUnit, mir, 0);
128efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  RegLocation rlSrc2 = oatGetSrcWide(cUnit, mir, 2);
129efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  rlSrc1 = loadValueWide(cUnit, rlSrc1, kCoreReg);
130efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg);
131efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  ConditionCode ccode = static_cast<ConditionCode>(mir->dalvikInsn.arg[0]);
132efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  opRegReg(cUnit, kOpCmp, rlSrc1.highReg, rlSrc2.highReg);
133efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  switch(ccode) {
134efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    case kCondEq:
135efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      opCondBranch(cUnit, kCondNe, notTaken);
136efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      break;
137efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    case kCondNe:
138efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      opCondBranch(cUnit, kCondNe, taken);
139efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      break;
140efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    case kCondLt:
141efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      opCondBranch(cUnit, kCondLt, taken);
142efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      opCondBranch(cUnit, kCondGt, notTaken);
143efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      ccode = kCondCc;
144efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      break;
145efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    case kCondLe:
146efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      opCondBranch(cUnit, kCondLt, taken);
147efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      opCondBranch(cUnit, kCondGt, notTaken);
148efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      ccode = kCondLs;
149efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      break;
150efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    case kCondGt:
151efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      opCondBranch(cUnit, kCondGt, taken);
152efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      opCondBranch(cUnit, kCondLt, notTaken);
153efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      ccode = kCondHi;
154efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      break;
155efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    case kCondGe:
156efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      opCondBranch(cUnit, kCondGt, taken);
157efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      opCondBranch(cUnit, kCondLt, notTaken);
158efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      ccode = kCondCs;
159efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      break;
160efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    default:
161cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      LOG(FATAL) << "Unexpected ccode: " << ccode;
162efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
163efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  opRegReg(cUnit, kOpCmp, rlSrc1.lowReg, rlSrc2.lowReg);
164efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  opCondBranch(cUnit, ccode, taken);
165efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
166efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
167efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/*
168efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Generate a register comparison to an immediate and branch.  Caller
169efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * is responsible for setting branch target field.
170efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */
171efc6369224b036a1fb77849f7ae65b3492c832c0buzbeeLIR* opCmpImmBranch(CompilationUnit* cUnit, ConditionCode cond, int reg,
172efc6369224b036a1fb77849f7ae65b3492c832c0buzbee          int checkValue, LIR* target)
173efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{
174efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  LIR* branch;
175efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  int modImm;
176efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  ArmConditionCode armCond = oatArmConditionEncoding(cond);
177efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  if ((ARM_LOWREG(reg)) && (checkValue == 0) &&
178efc6369224b036a1fb77849f7ae65b3492c832c0buzbee     ((armCond == kArmCondEq) || (armCond == kArmCondNe))) {
179efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    branch = newLIR2(cUnit, (armCond == kArmCondEq) ? kThumb2Cbz : kThumb2Cbnz,
180efc6369224b036a1fb77849f7ae65b3492c832c0buzbee                     reg, 0);
181efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  } else {
182efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    modImm = modifiedImmediate(checkValue);
183efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    if (ARM_LOWREG(reg) && ((checkValue & 0xff) == checkValue)) {
184efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      newLIR2(cUnit, kThumbCmpRI8, reg, checkValue);
185efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    } else if (modImm >= 0) {
186efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      newLIR2(cUnit, kThumb2CmpRI8, reg, modImm);
187efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    } else {
188efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      int tReg = oatAllocTemp(cUnit);
189efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      loadConstant(cUnit, tReg, checkValue);
190efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      opRegReg(cUnit, kOpCmp, reg, tReg);
191efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    }
192efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    branch = newLIR2(cUnit, kThumbBCond, 0, armCond);
193efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
194efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  branch->target = target;
195efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return branch;
196efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
197efc6369224b036a1fb77849f7ae65b3492c832c0buzbeeLIR* opRegCopyNoInsert(CompilationUnit* cUnit, int rDest, int rSrc)
198efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{
199efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  LIR* res;
200efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  int opcode;
201efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  if (ARM_FPREG(rDest) || ARM_FPREG(rSrc))
202efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    return fpRegCopy(cUnit, rDest, rSrc);
203efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  if (ARM_LOWREG(rDest) && ARM_LOWREG(rSrc))
204efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    opcode = kThumbMovRR;
205efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  else if (!ARM_LOWREG(rDest) && !ARM_LOWREG(rSrc))
206efc6369224b036a1fb77849f7ae65b3492c832c0buzbee     opcode = kThumbMovRR_H2H;
207efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  else if (ARM_LOWREG(rDest))
208efc6369224b036a1fb77849f7ae65b3492c832c0buzbee     opcode = kThumbMovRR_H2L;
209efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  else
210efc6369224b036a1fb77849f7ae65b3492c832c0buzbee     opcode = kThumbMovRR_L2H;
211efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  res = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, rDest, rSrc);
212efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  if (!(cUnit->disableOpt & (1 << kSafeOptimizations)) && rDest == rSrc) {
213efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    res->flags.isNop = true;
214efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
215efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return res;
216efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
217efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
218efc6369224b036a1fb77849f7ae65b3492c832c0buzbeeLIR* opRegCopy(CompilationUnit* cUnit, int rDest, int rSrc)
219efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{
220efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  LIR* res = opRegCopyNoInsert(cUnit, rDest, rSrc);
221cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee  oatAppendLIR(cUnit, res);
222efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return res;
223efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
224efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
225efc6369224b036a1fb77849f7ae65b3492c832c0buzbeevoid opRegCopyWide(CompilationUnit* cUnit, int destLo, int destHi,
226efc6369224b036a1fb77849f7ae65b3492c832c0buzbee               int srcLo, int srcHi)
227efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{
228efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  bool destFP = ARM_FPREG(destLo) && ARM_FPREG(destHi);
229efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  bool srcFP = ARM_FPREG(srcLo) && ARM_FPREG(srcHi);
230efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  DCHECK_EQ(ARM_FPREG(srcLo), ARM_FPREG(srcHi));
231efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  DCHECK_EQ(ARM_FPREG(destLo), ARM_FPREG(destHi));
232efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  if (destFP) {
233efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    if (srcFP) {
234efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      opRegCopy(cUnit, s2d(destLo, destHi), s2d(srcLo, srcHi));
235efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    } else {
236efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      newLIR3(cUnit, kThumb2Fmdrr, s2d(destLo, destHi), srcLo, srcHi);
237efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    }
238efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  } else {
239efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    if (srcFP) {
240efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      newLIR3(cUnit, kThumb2Fmrrd, destLo, destHi, s2d(srcLo, srcHi));
241efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    } else {
242efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      // Handle overlap
243efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      if (srcHi == destLo) {
244efc6369224b036a1fb77849f7ae65b3492c832c0buzbee        opRegCopy(cUnit, destHi, srcHi);
245efc6369224b036a1fb77849f7ae65b3492c832c0buzbee        opRegCopy(cUnit, destLo, srcLo);
246efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      } else {
247efc6369224b036a1fb77849f7ae65b3492c832c0buzbee        opRegCopy(cUnit, destLo, srcLo);
248efc6369224b036a1fb77849f7ae65b3492c832c0buzbee        opRegCopy(cUnit, destHi, srcHi);
249efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      }
250efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    }
251efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
252efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
253efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
254efc6369224b036a1fb77849f7ae65b3492c832c0buzbee// Table of magic divisors
255efc6369224b036a1fb77849f7ae65b3492c832c0buzbeestruct MagicTable {
256efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  uint32_t magic;
257efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  uint32_t shift;
258efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  DividePattern pattern;
259efc6369224b036a1fb77849f7ae65b3492c832c0buzbee};
260efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
261efc6369224b036a1fb77849f7ae65b3492c832c0buzbeestatic const MagicTable magicTable[] = {
262efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0, 0, DivideNone},        // 0
263efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0, 0, DivideNone},        // 1
264efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0, 0, DivideNone},        // 2
265efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0x55555556, 0, Divide3},  // 3
266efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0, 0, DivideNone},        // 4
267efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0x66666667, 1, Divide5},  // 5
268efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0x2AAAAAAB, 0, Divide3},  // 6
269efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0x92492493, 2, Divide7},  // 7
270efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0, 0, DivideNone},        // 8
271efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0x38E38E39, 1, Divide5},  // 9
272efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0x66666667, 2, Divide5},  // 10
273efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0x2E8BA2E9, 1, Divide5},  // 11
274efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0x2AAAAAAB, 1, Divide5},  // 12
275efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0x4EC4EC4F, 2, Divide5},  // 13
276efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0x92492493, 3, Divide7},  // 14
277efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  {0x88888889, 3, Divide7},  // 15
278efc6369224b036a1fb77849f7ae65b3492c832c0buzbee};
279efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
280efc6369224b036a1fb77849f7ae65b3492c832c0buzbee// Integer division by constant via reciprocal multiply (Hacker's Delight, 10-4)
281efc6369224b036a1fb77849f7ae65b3492c832c0buzbeebool smallLiteralDivide(CompilationUnit* cUnit, Instruction::Code dalvikOpcode,
282efc6369224b036a1fb77849f7ae65b3492c832c0buzbee                        RegLocation rlSrc, RegLocation rlDest, int lit)
283efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{
284cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee  if ((lit < 0) || (lit >= static_cast<int>(sizeof(magicTable)/sizeof(magicTable[0])))) {
285efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    return false;
286efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
287efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  DividePattern pattern = magicTable[lit].pattern;
288efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  if (pattern == DivideNone) {
289efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    return false;
290efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
291efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  // Tuning: add rem patterns
292efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  if (dalvikOpcode != Instruction::DIV_INT_LIT8) {
293efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    return false;
294efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
295efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
296efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  int rMagic = oatAllocTemp(cUnit);
297efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  loadConstant(cUnit, rMagic, magicTable[lit].magic);
298efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
299efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
300efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  int rHi = oatAllocTemp(cUnit);
301efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  int rLo = oatAllocTemp(cUnit);
302efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  newLIR4(cUnit, kThumb2Smull, rLo, rHi, rMagic, rlSrc.lowReg);
303efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  switch(pattern) {
304efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    case Divide3:
305efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      opRegRegRegShift(cUnit, kOpSub, rlResult.lowReg, rHi,
306efc6369224b036a1fb77849f7ae65b3492c832c0buzbee               rlSrc.lowReg, encodeShift(kArmAsr, 31));
307efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      break;
308efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    case Divide5:
309efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      opRegRegImm(cUnit, kOpAsr, rLo, rlSrc.lowReg, 31);
310efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      opRegRegRegShift(cUnit, kOpRsub, rlResult.lowReg, rLo, rHi,
311efc6369224b036a1fb77849f7ae65b3492c832c0buzbee               encodeShift(kArmAsr, magicTable[lit].shift));
312efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      break;
313efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    case Divide7:
314efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      opRegReg(cUnit, kOpAdd, rHi, rlSrc.lowReg);
315efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      opRegRegImm(cUnit, kOpAsr, rLo, rlSrc.lowReg, 31);
316efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      opRegRegRegShift(cUnit, kOpRsub, rlResult.lowReg, rLo, rHi,
317efc6369224b036a1fb77849f7ae65b3492c832c0buzbee               encodeShift(kArmAsr, magicTable[lit].shift));
318efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      break;
319efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    default:
320cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee      LOG(FATAL) << "Unexpected pattern: " << pattern;
321efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
322efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  storeValue(cUnit, rlDest, rlResult);
323efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return true;
324efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
325efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
326efc6369224b036a1fb77849f7ae65b3492c832c0buzbeeLIR* genRegMemCheck(CompilationUnit* cUnit, ConditionCode cCode,
327efc6369224b036a1fb77849f7ae65b3492c832c0buzbee                    int reg1, int base, int offset, ThrowKind kind)
328efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{
329efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  LOG(FATAL) << "Unexpected use of genRegMemCheck for Arm";
330efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return NULL;
331efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
332efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
333efc6369224b036a1fb77849f7ae65b3492c832c0buzbeeRegLocation genDivRemLit(CompilationUnit* cUnit, RegLocation rlDest, int reg1, int lit, bool isDiv)
334efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{
335efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  LOG(FATAL) << "Unexpected use of genDivRemLit for Arm";
336efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return rlDest;
337efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
338efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
339efc6369224b036a1fb77849f7ae65b3492c832c0buzbeeRegLocation genDivRem(CompilationUnit* cUnit, RegLocation rlDest, int reg1, int reg2, bool isDiv)
340efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{
341efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  LOG(FATAL) << "Unexpected use of genDivRem for Arm";
342efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return rlDest;
343efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
344efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
345efc6369224b036a1fb77849f7ae65b3492c832c0buzbeebool genInlinedMinMaxInt(CompilationUnit *cUnit, CallInfo* info, bool isMin)
346efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{
347efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  DCHECK_EQ(cUnit->instructionSet, kThumb2);
348efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  RegLocation rlSrc1 = info->args[0];
349efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  RegLocation rlSrc2 = info->args[1];
350efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  rlSrc1 = loadValue(cUnit, rlSrc1, kCoreReg);
351efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  rlSrc2 = loadValue(cUnit, rlSrc2, kCoreReg);
352efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  RegLocation rlDest = inlineTarget(cUnit, info);
353efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
354efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  opRegReg(cUnit, kOpCmp, rlSrc1.lowReg, rlSrc2.lowReg);
355efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  opIT(cUnit, (isMin) ? kArmCondGt : kArmCondLt, "E");
356efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  opRegReg(cUnit, kOpMov, rlResult.lowReg, rlSrc2.lowReg);
357efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  opRegReg(cUnit, kOpMov, rlResult.lowReg, rlSrc1.lowReg);
358efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  genBarrier(cUnit);
359efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  storeValue(cUnit, rlDest, rlResult);
360efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return true;
361efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
362efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
363efc6369224b036a1fb77849f7ae65b3492c832c0buzbeevoid opLea(CompilationUnit* cUnit, int rBase, int reg1, int reg2, int scale, int offset)
364efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{
365efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  LOG(FATAL) << "Unexpected use of opLea for Arm";
366efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
367efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
368efc6369224b036a1fb77849f7ae65b3492c832c0buzbeevoid opTlsCmp(CompilationUnit* cUnit, int offset, int val)
369efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{
370efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  LOG(FATAL) << "Unexpected use of opTlsCmp for Arm";
371efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
372efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
373efc6369224b036a1fb77849f7ae65b3492c832c0buzbeebool genInlinedCas32(CompilationUnit* cUnit, CallInfo* info, bool need_write_barrier) {
374efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  DCHECK_EQ(cUnit->instructionSet, kThumb2);
375efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  // Unused - RegLocation rlSrcUnsafe = info->args[0];
376efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  RegLocation rlSrcObj= info->args[1];  // Object - known non-null
377efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  RegLocation rlSrcOffset= info->args[2];  // long low
378efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  rlSrcOffset.wide = 0;  // ignore high half in info->args[3]
379efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  RegLocation rlSrcExpected= info->args[4];  // int or Object
380efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  RegLocation rlSrcNewValue= info->args[5];  // int or Object
381efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  RegLocation rlDest = inlineTarget(cUnit, info);  // boolean place for result
382efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
383efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
3841bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee  // Release store semantics, get the barrier out of the way.  TODO: revisit
3851bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee  oatGenMemBarrier(cUnit, kStoreLoad);
386efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
387efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  RegLocation rlObject = loadValue(cUnit, rlSrcObj, kCoreReg);
388efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  RegLocation rlNewValue = loadValue(cUnit, rlSrcNewValue, kCoreReg);
389efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
390efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  if (need_write_barrier) {
391efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    // Mark card for object assuming new value is stored.
392efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    markGCCard(cUnit, rlNewValue.lowReg, rlObject.lowReg);
393efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
394efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
395efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  RegLocation rlOffset = loadValue(cUnit, rlSrcOffset, kCoreReg);
396efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
397efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  int rPtr = oatAllocTemp(cUnit);
398efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  opRegRegReg(cUnit, kOpAdd, rPtr, rlObject.lowReg, rlOffset.lowReg);
399efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
400efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  // Free now unneeded rlObject and rlOffset to give more temps.
401efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  oatClobberSReg(cUnit, rlObject.sRegLow);
402efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  oatFreeTemp(cUnit, rlObject.lowReg);
403efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  oatClobberSReg(cUnit, rlOffset.sRegLow);
404efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  oatFreeTemp(cUnit, rlOffset.lowReg);
405efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
406efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  int rOldValue = oatAllocTemp(cUnit);
407efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  newLIR3(cUnit, kThumb2Ldrex, rOldValue, rPtr, 0);  // rOldValue := [rPtr]
408efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
409efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  RegLocation rlExpected = loadValue(cUnit, rlSrcExpected, kCoreReg);
410efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
411efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  // if (rOldValue == rExpected) {
412efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  //   [rPtr] <- rNewValue && rResult := success ? 0 : 1
413efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  //   rResult ^= 1
414efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  // } else {
415efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  //   rResult := 0
416efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  // }
417efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  opRegReg(cUnit, kOpCmp, rOldValue, rlExpected.lowReg);
418efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  oatFreeTemp(cUnit, rOldValue);  // Now unneeded.
419efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
420efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  opIT(cUnit, kArmCondEq, "TE");
421efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  newLIR4(cUnit, kThumb2Strex, rlResult.lowReg, rlNewValue.lowReg, rPtr, 0);
422efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  oatFreeTemp(cUnit, rPtr);  // Now unneeded.
423efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  opRegImm(cUnit, kOpXor, rlResult.lowReg, 1);
424efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  opRegReg(cUnit, kOpXor, rlResult.lowReg, rlResult.lowReg);
425efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
426efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  storeValue(cUnit, rlDest, rlResult);
427efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
428efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return true;
429efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
430efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
431efc6369224b036a1fb77849f7ae65b3492c832c0buzbeeLIR* opPcRelLoad(CompilationUnit* cUnit, int reg, LIR* target)
432efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{
433efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return rawLIR(cUnit, cUnit->currentDalvikOffset, kThumb2LdrPcRel12, reg, 0, 0, 0, 0, target);
434efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
435efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
436efc6369224b036a1fb77849f7ae65b3492c832c0buzbeeLIR* opVldm(CompilationUnit* cUnit, int rBase, int count)
437efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{
438efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return newLIR3(cUnit, kThumb2Vldms, rBase, fr0, count);
439efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
440efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
441efc6369224b036a1fb77849f7ae65b3492c832c0buzbeeLIR* opVstm(CompilationUnit* cUnit, int rBase, int count)
442efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{
443efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return newLIR3(cUnit, kThumb2Vstms, rBase, fr0, count);
444efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
445efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
446efc6369224b036a1fb77849f7ae65b3492c832c0buzbeevoid genMultiplyByTwoBitMultiplier(CompilationUnit* cUnit, RegLocation rlSrc,
447efc6369224b036a1fb77849f7ae65b3492c832c0buzbee                                   RegLocation rlResult, int lit,
448efc6369224b036a1fb77849f7ae65b3492c832c0buzbee                                   int firstBit, int secondBit)
449efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{
450efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  opRegRegRegShift(cUnit, kOpAdd, rlResult.lowReg, rlSrc.lowReg, rlSrc.lowReg,
451efc6369224b036a1fb77849f7ae65b3492c832c0buzbee                   encodeShift(kArmLsl, secondBit - firstBit));
452efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  if (firstBit != 0) {
453efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    opRegRegImm(cUnit, kOpLsl, rlResult.lowReg, rlResult.lowReg, firstBit);
454efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
455efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
456efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
457efc6369224b036a1fb77849f7ae65b3492c832c0buzbeevoid genDivZeroCheck(CompilationUnit* cUnit, int regLo, int regHi)
458efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{
459efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  int tReg = oatAllocTemp(cUnit);
460efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  newLIR4(cUnit, kThumb2OrrRRRs, tReg, regLo, regHi, 0);
461efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  oatFreeTemp(cUnit, tReg);
462efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  genCheck(cUnit, kCondEq, kThrowDivZero);
463efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
464efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
465efc6369224b036a1fb77849f7ae65b3492c832c0buzbee// Test suspend flag, return target of taken suspend branch
466efc6369224b036a1fb77849f7ae65b3492c832c0buzbeeLIR* opTestSuspend(CompilationUnit* cUnit, LIR* target)
467efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{
468efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  newLIR2(cUnit, kThumbSubRI8, rARM_SUSPEND, 1);
469efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return opCondBranch(cUnit, (target == NULL) ? kCondEq : kCondNe, target);
470efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
471efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
472efc6369224b036a1fb77849f7ae65b3492c832c0buzbee// Decrement register and branch on condition
473efc6369224b036a1fb77849f7ae65b3492c832c0buzbeeLIR* opDecAndBranch(CompilationUnit* cUnit, ConditionCode cCode, int reg, LIR* target)
474efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{
475efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  // Combine sub & test using sub setflags encoding here
476efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  newLIR3(cUnit, kThumb2SubsRRI12, reg, reg, 1);
477efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return opCondBranch(cUnit, cCode, target);
478efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
479efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
4801bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbeevoid oatGenMemBarrier(CompilationUnit* cUnit, MemBarrierKind barrierKind)
481efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{
482efc6369224b036a1fb77849f7ae65b3492c832c0buzbee#if ANDROID_SMP != 0
4831bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee  int dmbFlavor;
4841bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee  // TODO: revisit Arm barrier kinds
4851bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee  switch (barrierKind) {
4861bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee    case kLoadStore: dmbFlavor = kSY; break;
4871bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee    case kLoadLoad: dmbFlavor = kSY; break;
4881bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee    case kStoreStore: dmbFlavor = kST; break;
4891bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee    case kStoreLoad: dmbFlavor = kSY; break;
4901bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee    default:
4911bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee      LOG(FATAL) << "Unexpected MemBarrierKind: " << barrierKind;
4921bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee      dmbFlavor = kSY;  // quiet gcc.
4931bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee      break;
4941bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee  }
4951bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee  LIR* dmb = newLIR1(cUnit, kThumb2Dmb, dmbFlavor);
496efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  dmb->defMask = ENCODE_ALL;
497efc6369224b036a1fb77849f7ae65b3492c832c0buzbee#endif
498efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
499efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
500efc6369224b036a1fb77849f7ae65b3492c832c0buzbeebool genNegLong(CompilationUnit* cUnit, RegLocation rlDest,
501efc6369224b036a1fb77849f7ae65b3492c832c0buzbee                RegLocation rlSrc)
502efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{
503efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  rlSrc = loadValueWide(cUnit, rlSrc, kCoreReg);
504efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
505efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  int zReg = oatAllocTemp(cUnit);
506efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  loadConstantNoClobber(cUnit, zReg, 0);
507efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  // Check for destructive overlap
508efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  if (rlResult.lowReg == rlSrc.highReg) {
509efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    int tReg = oatAllocTemp(cUnit);
510efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    opRegRegReg(cUnit, kOpSub, rlResult.lowReg, zReg, rlSrc.lowReg);
511efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    opRegRegReg(cUnit, kOpSbc, rlResult.highReg, zReg, tReg);
512efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    oatFreeTemp(cUnit, tReg);
513efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  } else {
514efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    opRegRegReg(cUnit, kOpSub, rlResult.lowReg, zReg, rlSrc.lowReg);
515efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    opRegRegReg(cUnit, kOpSbc, rlResult.highReg, zReg, rlSrc.highReg);
516efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
517efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  oatFreeTemp(cUnit, zReg);
518efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  storeValueWide(cUnit, rlDest, rlResult);
519efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return false;
520efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
521efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
522efc6369224b036a1fb77849f7ae65b3492c832c0buzbeebool genAddLong(CompilationUnit* cUnit, RegLocation rlDest,
523efc6369224b036a1fb77849f7ae65b3492c832c0buzbee                RegLocation rlSrc1, RegLocation rlSrc2)
524efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{
525efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  LOG(FATAL) << "Unexpected use of genAddLong for Arm";
526efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return false;
527efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
528efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
529efc6369224b036a1fb77849f7ae65b3492c832c0buzbeebool genSubLong(CompilationUnit* cUnit, RegLocation rlDest,
530efc6369224b036a1fb77849f7ae65b3492c832c0buzbee                RegLocation rlSrc1, RegLocation rlSrc2)
531efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{
532efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  LOG(FATAL) << "Unexpected use of genSubLong for Arm";
533efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return false;
534efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
535efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
536efc6369224b036a1fb77849f7ae65b3492c832c0buzbeebool genAndLong(CompilationUnit* cUnit, RegLocation rlDest,
537efc6369224b036a1fb77849f7ae65b3492c832c0buzbee                RegLocation rlSrc1, RegLocation rlSrc2)
538efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{
539efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  LOG(FATAL) << "Unexpected use of genAndLong for Arm";
540efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return false;
541efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
542efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
543efc6369224b036a1fb77849f7ae65b3492c832c0buzbeebool genOrLong(CompilationUnit* cUnit, RegLocation rlDest,
544efc6369224b036a1fb77849f7ae65b3492c832c0buzbee               RegLocation rlSrc1, RegLocation rlSrc2)
545efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{
546efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  LOG(FATAL) << "Unexpected use of genOrLong for Arm";
547efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return false;
548efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
549efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
550efc6369224b036a1fb77849f7ae65b3492c832c0buzbeebool genXorLong(CompilationUnit* cUnit, RegLocation rlDest,
551efc6369224b036a1fb77849f7ae65b3492c832c0buzbee               RegLocation rlSrc1, RegLocation rlSrc2)
552efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{
553efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  LOG(FATAL) << "Unexpected use of genXoLong for Arm";
554efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return false;
555efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
556efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
557efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}  // namespace art
558