blob: e3ac5bb0438b2dc02630dc1559752776b313ceed [file] [log] [blame]
Ben Chengba4fc8b2009-06-01 13:00:29 -07001/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Bill Buzbee50a6bf22009-07-08 13:08:04 -070017/*
18 * This file contains codegen and support common to all supported
19 * ARM variants. It is included by:
20 *
21 * Codegen-$(TARGET_ARCH_VARIANT).c
22 *
23 * which combines this common code with specific support found in the
24 * applicable directory below this one.
25 */
26
Ben Cheng5d90c202009-11-22 23:31:11 -080027static bool genConversionCall(CompilationUnit *cUnit, MIR *mir, void *funct,
28 int srcSize, int tgtSize)
29{
30 /*
31 * Don't optimize the register usage since it calls out to template
32 * functions
33 */
34 RegLocation rlSrc;
35 RegLocation rlDest;
Bill Buzbeec6f10662010-02-09 11:16:15 -080036 dvmCompilerFlushAllRegs(cUnit); /* Send everything to home location */
Ben Cheng5d90c202009-11-22 23:31:11 -080037 if (srcSize == 1) {
Bill Buzbeec6f10662010-02-09 11:16:15 -080038 rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
Ben Cheng5d90c202009-11-22 23:31:11 -080039 loadValueDirectFixed(cUnit, rlSrc, r0);
40 } else {
Bill Buzbeec6f10662010-02-09 11:16:15 -080041 rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
Ben Cheng5d90c202009-11-22 23:31:11 -080042 loadValueDirectWideFixed(cUnit, rlSrc, r0, r1);
43 }
44 loadConstant(cUnit, r2, (int)funct);
45 opReg(cUnit, kOpBlx, r2);
Elliott Hughes6a555132010-02-25 15:41:42 -080046 dvmCompilerClobberCallRegs(cUnit);
Ben Cheng5d90c202009-11-22 23:31:11 -080047 if (tgtSize == 1) {
48 RegLocation rlResult;
Bill Buzbeec6f10662010-02-09 11:16:15 -080049 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
50 rlResult = dvmCompilerGetReturn(cUnit);
Ben Cheng5d90c202009-11-22 23:31:11 -080051 storeValue(cUnit, rlDest, rlResult);
52 } else {
53 RegLocation rlResult;
Bill Buzbeec6f10662010-02-09 11:16:15 -080054 rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
55 rlResult = dvmCompilerGetReturnWide(cUnit);
Ben Cheng5d90c202009-11-22 23:31:11 -080056 storeValueWide(cUnit, rlDest, rlResult);
57 }
58 return false;
59}
Ben Chengba4fc8b2009-06-01 13:00:29 -070060
Ben Chengba4fc8b2009-06-01 13:00:29 -070061
Ben Cheng5d90c202009-11-22 23:31:11 -080062static bool genArithOpFloatPortable(CompilationUnit *cUnit, MIR *mir,
63 RegLocation rlDest, RegLocation rlSrc1,
64 RegLocation rlSrc2)
65{
66 RegLocation rlResult;
67 void* funct;
68
69 /* TODO: use a proper include file to define these */
70 float __aeabi_fadd(float a, float b);
71 float __aeabi_fsub(float a, float b);
72 float __aeabi_fdiv(float a, float b);
73 float __aeabi_fmul(float a, float b);
74 float fmodf(float a, float b);
75
76 switch (mir->dalvikInsn.opCode) {
77 case OP_ADD_FLOAT_2ADDR:
78 case OP_ADD_FLOAT:
79 funct = (void*) __aeabi_fadd;
80 break;
81 case OP_SUB_FLOAT_2ADDR:
82 case OP_SUB_FLOAT:
83 funct = (void*) __aeabi_fsub;
84 break;
85 case OP_DIV_FLOAT_2ADDR:
86 case OP_DIV_FLOAT:
87 funct = (void*) __aeabi_fdiv;
88 break;
89 case OP_MUL_FLOAT_2ADDR:
90 case OP_MUL_FLOAT:
91 funct = (void*) __aeabi_fmul;
92 break;
93 case OP_REM_FLOAT_2ADDR:
94 case OP_REM_FLOAT:
95 funct = (void*) fmodf;
96 break;
97 case OP_NEG_FLOAT: {
98 genNegFloat(cUnit, rlDest, rlSrc1);
99 return false;
100 }
101 default:
102 return true;
103 }
Bill Buzbeec6f10662010-02-09 11:16:15 -0800104 dvmCompilerFlushAllRegs(cUnit); /* Send everything to home location */
Ben Cheng5d90c202009-11-22 23:31:11 -0800105 loadValueDirectFixed(cUnit, rlSrc1, r0);
106 loadValueDirectFixed(cUnit, rlSrc2, r1);
107 loadConstant(cUnit, r2, (int)funct);
108 opReg(cUnit, kOpBlx, r2);
Elliott Hughes6a555132010-02-25 15:41:42 -0800109 dvmCompilerClobberCallRegs(cUnit);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800110 rlResult = dvmCompilerGetReturn(cUnit);
Ben Cheng5d90c202009-11-22 23:31:11 -0800111 storeValue(cUnit, rlDest, rlResult);
112 return false;
113}
114
115static bool genArithOpDoublePortable(CompilationUnit *cUnit, MIR *mir,
116 RegLocation rlDest, RegLocation rlSrc1,
117 RegLocation rlSrc2)
118{
119 RegLocation rlResult;
120 void* funct;
121
122 /* TODO: use a proper include file to define these */
123 double __aeabi_dadd(double a, double b);
124 double __aeabi_dsub(double a, double b);
125 double __aeabi_ddiv(double a, double b);
126 double __aeabi_dmul(double a, double b);
127 double fmod(double a, double b);
128
129 switch (mir->dalvikInsn.opCode) {
130 case OP_ADD_DOUBLE_2ADDR:
131 case OP_ADD_DOUBLE:
132 funct = (void*) __aeabi_dadd;
133 break;
134 case OP_SUB_DOUBLE_2ADDR:
135 case OP_SUB_DOUBLE:
136 funct = (void*) __aeabi_dsub;
137 break;
138 case OP_DIV_DOUBLE_2ADDR:
139 case OP_DIV_DOUBLE:
140 funct = (void*) __aeabi_ddiv;
141 break;
142 case OP_MUL_DOUBLE_2ADDR:
143 case OP_MUL_DOUBLE:
144 funct = (void*) __aeabi_dmul;
145 break;
146 case OP_REM_DOUBLE_2ADDR:
147 case OP_REM_DOUBLE:
148 funct = (void*) fmod;
149 break;
150 case OP_NEG_DOUBLE: {
151 genNegDouble(cUnit, rlDest, rlSrc1);
152 return false;
153 }
154 default:
155 return true;
156 }
Bill Buzbeec6f10662010-02-09 11:16:15 -0800157 dvmCompilerFlushAllRegs(cUnit); /* Send everything to home location */
Ben Cheng5d90c202009-11-22 23:31:11 -0800158 loadConstant(cUnit, rlr, (int)funct);
159 loadValueDirectWideFixed(cUnit, rlSrc1, r0, r1);
160 loadValueDirectWideFixed(cUnit, rlSrc2, r2, r3);
161 opReg(cUnit, kOpBlx, rlr);
Elliott Hughes6a555132010-02-25 15:41:42 -0800162 dvmCompilerClobberCallRegs(cUnit);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800163 rlResult = dvmCompilerGetReturnWide(cUnit);
Ben Cheng5d90c202009-11-22 23:31:11 -0800164 storeValueWide(cUnit, rlDest, rlResult);
165 return false;
166}
167
168static bool genConversionPortable(CompilationUnit *cUnit, MIR *mir)
169{
170 OpCode opCode = mir->dalvikInsn.opCode;
171
172 float __aeabi_i2f( int op1 );
173 int __aeabi_f2iz( float op1 );
174 float __aeabi_d2f( double op1 );
175 double __aeabi_f2d( float op1 );
176 double __aeabi_i2d( int op1 );
177 int __aeabi_d2iz( double op1 );
178 float __aeabi_l2f( long op1 );
179 double __aeabi_l2d( long op1 );
180 s8 dvmJitf2l( float op1 );
181 s8 dvmJitd2l( double op1 );
182
183 switch (opCode) {
184 case OP_INT_TO_FLOAT:
185 return genConversionCall(cUnit, mir, (void*)__aeabi_i2f, 1, 1);
186 case OP_FLOAT_TO_INT:
187 return genConversionCall(cUnit, mir, (void*)__aeabi_f2iz, 1, 1);
188 case OP_DOUBLE_TO_FLOAT:
189 return genConversionCall(cUnit, mir, (void*)__aeabi_d2f, 2, 1);
190 case OP_FLOAT_TO_DOUBLE:
191 return genConversionCall(cUnit, mir, (void*)__aeabi_f2d, 1, 2);
192 case OP_INT_TO_DOUBLE:
193 return genConversionCall(cUnit, mir, (void*)__aeabi_i2d, 1, 2);
194 case OP_DOUBLE_TO_INT:
195 return genConversionCall(cUnit, mir, (void*)__aeabi_d2iz, 2, 1);
196 case OP_FLOAT_TO_LONG:
197 return genConversionCall(cUnit, mir, (void*)dvmJitf2l, 1, 2);
198 case OP_LONG_TO_FLOAT:
199 return genConversionCall(cUnit, mir, (void*)__aeabi_l2f, 2, 1);
200 case OP_DOUBLE_TO_LONG:
201 return genConversionCall(cUnit, mir, (void*)dvmJitd2l, 2, 2);
202 case OP_LONG_TO_DOUBLE:
203 return genConversionCall(cUnit, mir, (void*)__aeabi_l2d, 2, 2);
204 default:
205 return true;
206 }
207 return false;
208}
Ben Chengba4fc8b2009-06-01 13:00:29 -0700209
Jeff Hao97319a82009-08-12 16:57:15 -0700210#if defined(WITH_SELF_VERIFICATION)
jeffhao9e45c0b2010-02-03 10:24:05 -0800211static void selfVerificationBranchInsert(LIR *currentLIR, ArmOpCode opCode,
212 int dest, int src1)
Jeff Hao97319a82009-08-12 16:57:15 -0700213{
jeffhao9e45c0b2010-02-03 10:24:05 -0800214 ArmLIR *insn = dvmCompilerNew(sizeof(ArmLIR), true);
215 insn->opCode = opCode;
216 insn->operands[0] = dest;
217 insn->operands[1] = src1;
218 setupResourceMasks(insn);
219 dvmCompilerInsertLIRBefore(currentLIR, (LIR *) insn);
Jeff Hao97319a82009-08-12 16:57:15 -0700220}
221
jeffhao9e45c0b2010-02-03 10:24:05 -0800222static void selfVerificationBranchInsertPass(CompilationUnit *cUnit)
Jeff Hao97319a82009-08-12 16:57:15 -0700223{
jeffhao9e45c0b2010-02-03 10:24:05 -0800224 ArmLIR *thisLIR;
225 ArmLIR *branchLIR = dvmCompilerNew(sizeof(ArmLIR), true);
226 TemplateOpCode opCode = TEMPLATE_MEM_OP_DECODE;
Jeff Hao97319a82009-08-12 16:57:15 -0700227
jeffhao9e45c0b2010-02-03 10:24:05 -0800228 for (thisLIR = (ArmLIR *) cUnit->firstLIRInsn;
229 thisLIR != (ArmLIR *) cUnit->lastLIRInsn;
230 thisLIR = NEXT_LIR(thisLIR)) {
231 if (thisLIR->branchInsertSV) {
232 /* Branch to mem op decode template */
233 selfVerificationBranchInsert((LIR *) thisLIR, kThumbBlx1,
234 (int) gDvmJit.codeCache + templateEntryOffsets[opCode],
235 (int) gDvmJit.codeCache + templateEntryOffsets[opCode]);
236 selfVerificationBranchInsert((LIR *) thisLIR, kThumbBlx2,
237 (int) gDvmJit.codeCache + templateEntryOffsets[opCode],
238 (int) gDvmJit.codeCache + templateEntryOffsets[opCode]);
Jeff Hao97319a82009-08-12 16:57:15 -0700239 }
240 }
Jeff Hao97319a82009-08-12 16:57:15 -0700241}
Jeff Hao97319a82009-08-12 16:57:15 -0700242#endif
243
Bill Buzbeebe6534f2010-03-12 16:01:35 -0800244/* Generate conditional branch instructions */
245static ArmLIR *genConditionalBranch(CompilationUnit *cUnit,
246 ArmConditionCode cond,
247 ArmLIR *target)
248{
249 ArmLIR *branch = opCondBranch(cUnit, cond);
250 branch->generic.target = (LIR *) target;
251 return branch;
252}
253
Ben Chengba4fc8b2009-06-01 13:00:29 -0700254/* Generate a unconditional branch to go to the interpreter */
Bill Buzbee89efc3d2009-07-28 11:22:22 -0700255static inline ArmLIR *genTrap(CompilationUnit *cUnit, int dOffset,
256 ArmLIR *pcrLabel)
Ben Chengba4fc8b2009-06-01 13:00:29 -0700257{
Bill Buzbee1465db52009-09-23 17:17:35 -0700258 ArmLIR *branch = opNone(cUnit, kOpUncondBr);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700259 return genCheckCommon(cUnit, dOffset, branch, pcrLabel);
260}
261
262/* Load a wide field from an object instance */
263static void genIGetWide(CompilationUnit *cUnit, MIR *mir, int fieldOffset)
264{
265 DecodedInstruction *dInsn = &mir->dalvikInsn;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800266 RegLocation rlObj = dvmCompilerGetSrc(cUnit, mir, 0);
267 RegLocation rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -0700268 RegLocation rlResult;
269 rlObj = loadValue(cUnit, rlObj, kCoreReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800270 int regPtr = dvmCompilerAllocTemp(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700271
Bill Buzbee1465db52009-09-23 17:17:35 -0700272 assert(rlDest.wide);
Ben Chenge9695e52009-06-16 16:11:47 -0700273
Bill Buzbee1465db52009-09-23 17:17:35 -0700274 genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset,
275 NULL);/* null object? */
276 opRegRegImm(cUnit, kOpAdd, regPtr, rlObj.lowReg, fieldOffset);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800277 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
Ben Cheng11d8f142010-03-24 15:24:19 -0700278
279 HEAP_ACCESS_SHADOW(true);
Bill Buzbee1465db52009-09-23 17:17:35 -0700280 loadPair(cUnit, regPtr, rlResult.lowReg, rlResult.highReg);
Ben Cheng11d8f142010-03-24 15:24:19 -0700281 HEAP_ACCESS_SHADOW(false);
282
Bill Buzbeec6f10662010-02-09 11:16:15 -0800283 dvmCompilerFreeTemp(cUnit, regPtr);
Bill Buzbee1465db52009-09-23 17:17:35 -0700284 storeValueWide(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700285}
286
287/* Store a wide field to an object instance */
288static void genIPutWide(CompilationUnit *cUnit, MIR *mir, int fieldOffset)
289{
290 DecodedInstruction *dInsn = &mir->dalvikInsn;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800291 RegLocation rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
292 RegLocation rlObj = dvmCompilerGetSrc(cUnit, mir, 2);
Bill Buzbee1465db52009-09-23 17:17:35 -0700293 rlObj = loadValue(cUnit, rlObj, kCoreReg);
294 int regPtr;
295 rlSrc = loadValueWide(cUnit, rlSrc, kAnyReg);
296 genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset,
297 NULL);/* null object? */
Bill Buzbeec6f10662010-02-09 11:16:15 -0800298 regPtr = dvmCompilerAllocTemp(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700299 opRegRegImm(cUnit, kOpAdd, regPtr, rlObj.lowReg, fieldOffset);
Ben Cheng11d8f142010-03-24 15:24:19 -0700300
301 HEAP_ACCESS_SHADOW(true);
Bill Buzbee1465db52009-09-23 17:17:35 -0700302 storePair(cUnit, regPtr, rlSrc.lowReg, rlSrc.highReg);
Ben Cheng11d8f142010-03-24 15:24:19 -0700303 HEAP_ACCESS_SHADOW(false);
304
Bill Buzbeec6f10662010-02-09 11:16:15 -0800305 dvmCompilerFreeTemp(cUnit, regPtr);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700306}
307
308/*
309 * Load a field from an object instance
310 *
Ben Chengba4fc8b2009-06-01 13:00:29 -0700311 */
Bill Buzbee270c1d62009-08-13 16:58:07 -0700312static void genIGet(CompilationUnit *cUnit, MIR *mir, OpSize size,
Ben Chengba4fc8b2009-06-01 13:00:29 -0700313 int fieldOffset)
314{
Bill Buzbee1465db52009-09-23 17:17:35 -0700315 int regPtr;
316 RegLocation rlResult;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700317 DecodedInstruction *dInsn = &mir->dalvikInsn;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800318 RegLocation rlObj = dvmCompilerGetSrc(cUnit, mir, 0);
319 RegLocation rlDest = dvmCompilerGetDest(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -0700320 rlObj = loadValue(cUnit, rlObj, kCoreReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800321 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -0700322 genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset,
323 NULL);/* null object? */
Ben Cheng11d8f142010-03-24 15:24:19 -0700324
325 HEAP_ACCESS_SHADOW(true);
Ben Cheng5d90c202009-11-22 23:31:11 -0800326 loadBaseDisp(cUnit, mir, rlObj.lowReg, fieldOffset, rlResult.lowReg,
327 size, rlObj.sRegLow);
Ben Cheng11d8f142010-03-24 15:24:19 -0700328 HEAP_ACCESS_SHADOW(false);
329
Bill Buzbee1465db52009-09-23 17:17:35 -0700330 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700331}
332
333/*
334 * Store a field to an object instance
335 *
Ben Chengba4fc8b2009-06-01 13:00:29 -0700336 */
Bill Buzbee270c1d62009-08-13 16:58:07 -0700337static void genIPut(CompilationUnit *cUnit, MIR *mir, OpSize size,
Ben Chengba4fc8b2009-06-01 13:00:29 -0700338 int fieldOffset)
339{
340 DecodedInstruction *dInsn = &mir->dalvikInsn;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800341 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
342 RegLocation rlObj = dvmCompilerGetSrc(cUnit, mir, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -0700343 rlObj = loadValue(cUnit, rlObj, kCoreReg);
344 rlSrc = loadValue(cUnit, rlSrc, kAnyReg);
345 int regPtr;
346 genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset,
347 NULL);/* null object? */
Ben Cheng11d8f142010-03-24 15:24:19 -0700348
349 HEAP_ACCESS_SHADOW(true);
Bill Buzbee1465db52009-09-23 17:17:35 -0700350 storeBaseDisp(cUnit, rlObj.lowReg, fieldOffset, rlSrc.lowReg, size);
Ben Cheng11d8f142010-03-24 15:24:19 -0700351 HEAP_ACCESS_SHADOW(false);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700352}
353
354
Ben Chengba4fc8b2009-06-01 13:00:29 -0700355/*
356 * Generate array load
Ben Chengba4fc8b2009-06-01 13:00:29 -0700357 */
Bill Buzbee270c1d62009-08-13 16:58:07 -0700358static void genArrayGet(CompilationUnit *cUnit, MIR *mir, OpSize size,
Bill Buzbee1465db52009-09-23 17:17:35 -0700359 RegLocation rlArray, RegLocation rlIndex,
360 RegLocation rlDest, int scale)
Ben Chengba4fc8b2009-06-01 13:00:29 -0700361{
362 int lenOffset = offsetof(ArrayObject, length);
363 int dataOffset = offsetof(ArrayObject, contents);
Bill Buzbee1465db52009-09-23 17:17:35 -0700364 RegLocation rlResult;
365 rlArray = loadValue(cUnit, rlArray, kCoreReg);
366 rlIndex = loadValue(cUnit, rlIndex, kCoreReg);
367 int regPtr;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700368
369 /* null object? */
Ben Cheng4238ec22009-08-24 16:32:22 -0700370 ArmLIR * pcrLabel = NULL;
371
372 if (!(mir->OptimizationFlags & MIR_IGNORE_NULL_CHECK)) {
Bill Buzbee1465db52009-09-23 17:17:35 -0700373 pcrLabel = genNullCheck(cUnit, rlArray.sRegLow,
374 rlArray.lowReg, mir->offset, NULL);
Ben Cheng4238ec22009-08-24 16:32:22 -0700375 }
376
Bill Buzbeec6f10662010-02-09 11:16:15 -0800377 regPtr = dvmCompilerAllocTemp(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700378
Ben Cheng4238ec22009-08-24 16:32:22 -0700379 if (!(mir->OptimizationFlags & MIR_IGNORE_RANGE_CHECK)) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800380 int regLen = dvmCompilerAllocTemp(cUnit);
Ben Cheng4238ec22009-08-24 16:32:22 -0700381 /* Get len */
Bill Buzbee1465db52009-09-23 17:17:35 -0700382 loadWordDisp(cUnit, rlArray.lowReg, lenOffset, regLen);
383 /* regPtr -> array data */
384 opRegRegImm(cUnit, kOpAdd, regPtr, rlArray.lowReg, dataOffset);
385 genBoundsCheck(cUnit, rlIndex.lowReg, regLen, mir->offset,
386 pcrLabel);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800387 dvmCompilerFreeTemp(cUnit, regLen);
Ben Cheng4238ec22009-08-24 16:32:22 -0700388 } else {
Bill Buzbee1465db52009-09-23 17:17:35 -0700389 /* regPtr -> array data */
390 opRegRegImm(cUnit, kOpAdd, regPtr, rlArray.lowReg, dataOffset);
Ben Cheng4238ec22009-08-24 16:32:22 -0700391 }
Bill Buzbee1465db52009-09-23 17:17:35 -0700392 if ((size == kLong) || (size == kDouble)) {
393 if (scale) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800394 int rNewIndex = dvmCompilerAllocTemp(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700395 opRegRegImm(cUnit, kOpLsl, rNewIndex, rlIndex.lowReg, scale);
396 opRegReg(cUnit, kOpAdd, regPtr, rNewIndex);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800397 dvmCompilerFreeTemp(cUnit, rNewIndex);
Bill Buzbee1465db52009-09-23 17:17:35 -0700398 } else {
399 opRegReg(cUnit, kOpAdd, regPtr, rlIndex.lowReg);
400 }
Bill Buzbeec6f10662010-02-09 11:16:15 -0800401 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
Ben Cheng11d8f142010-03-24 15:24:19 -0700402
403 HEAP_ACCESS_SHADOW(true);
Bill Buzbee1465db52009-09-23 17:17:35 -0700404 loadPair(cUnit, regPtr, rlResult.lowReg, rlResult.highReg);
Ben Cheng11d8f142010-03-24 15:24:19 -0700405 HEAP_ACCESS_SHADOW(false);
406
Bill Buzbeec6f10662010-02-09 11:16:15 -0800407 dvmCompilerFreeTemp(cUnit, regPtr);
Bill Buzbee1465db52009-09-23 17:17:35 -0700408 storeValueWide(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700409 } else {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800410 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
Ben Cheng11d8f142010-03-24 15:24:19 -0700411
412 HEAP_ACCESS_SHADOW(true);
Bill Buzbee1465db52009-09-23 17:17:35 -0700413 loadBaseIndexed(cUnit, regPtr, rlIndex.lowReg, rlResult.lowReg,
414 scale, size);
Ben Cheng11d8f142010-03-24 15:24:19 -0700415 HEAP_ACCESS_SHADOW(false);
416
Bill Buzbeec6f10662010-02-09 11:16:15 -0800417 dvmCompilerFreeTemp(cUnit, regPtr);
Bill Buzbee1465db52009-09-23 17:17:35 -0700418 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700419 }
420}
421
Ben Chengba4fc8b2009-06-01 13:00:29 -0700422/*
423 * Generate array store
424 *
Ben Chengba4fc8b2009-06-01 13:00:29 -0700425 */
Bill Buzbee270c1d62009-08-13 16:58:07 -0700426static void genArrayPut(CompilationUnit *cUnit, MIR *mir, OpSize size,
Bill Buzbee1465db52009-09-23 17:17:35 -0700427 RegLocation rlArray, RegLocation rlIndex,
428 RegLocation rlSrc, int scale)
Ben Chengba4fc8b2009-06-01 13:00:29 -0700429{
430 int lenOffset = offsetof(ArrayObject, length);
431 int dataOffset = offsetof(ArrayObject, contents);
432
Bill Buzbee1465db52009-09-23 17:17:35 -0700433 int regPtr;
434 rlArray = loadValue(cUnit, rlArray, kCoreReg);
435 rlIndex = loadValue(cUnit, rlIndex, kCoreReg);
Ben Chenge9695e52009-06-16 16:11:47 -0700436
Bill Buzbeec6f10662010-02-09 11:16:15 -0800437 if (dvmCompilerIsTemp(cUnit, rlArray.lowReg)) {
438 dvmCompilerClobber(cUnit, rlArray.lowReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700439 regPtr = rlArray.lowReg;
440 } else {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800441 regPtr = dvmCompilerAllocTemp(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700442 genRegCopy(cUnit, regPtr, rlArray.lowReg);
443 }
Ben Chenge9695e52009-06-16 16:11:47 -0700444
Ben Cheng1efc9c52009-06-08 18:25:27 -0700445 /* null object? */
Ben Cheng4238ec22009-08-24 16:32:22 -0700446 ArmLIR * pcrLabel = NULL;
447
448 if (!(mir->OptimizationFlags & MIR_IGNORE_NULL_CHECK)) {
Bill Buzbee1465db52009-09-23 17:17:35 -0700449 pcrLabel = genNullCheck(cUnit, rlArray.sRegLow, rlArray.lowReg,
450 mir->offset, NULL);
Ben Cheng4238ec22009-08-24 16:32:22 -0700451 }
452
453 if (!(mir->OptimizationFlags & MIR_IGNORE_RANGE_CHECK)) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800454 int regLen = dvmCompilerAllocTemp(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700455 //NOTE: max live temps(4) here.
Ben Cheng4238ec22009-08-24 16:32:22 -0700456 /* Get len */
Bill Buzbee1465db52009-09-23 17:17:35 -0700457 loadWordDisp(cUnit, rlArray.lowReg, lenOffset, regLen);
458 /* regPtr -> array data */
459 opRegImm(cUnit, kOpAdd, regPtr, dataOffset);
460 genBoundsCheck(cUnit, rlIndex.lowReg, regLen, mir->offset,
461 pcrLabel);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800462 dvmCompilerFreeTemp(cUnit, regLen);
Ben Cheng4238ec22009-08-24 16:32:22 -0700463 } else {
Bill Buzbee1465db52009-09-23 17:17:35 -0700464 /* regPtr -> array data */
465 opRegImm(cUnit, kOpAdd, regPtr, dataOffset);
Ben Cheng4238ec22009-08-24 16:32:22 -0700466 }
Bill Buzbee1465db52009-09-23 17:17:35 -0700467 /* at this point, regPtr points to array, 2 live temps */
Bill Buzbee1465db52009-09-23 17:17:35 -0700468 if ((size == kLong) || (size == kDouble)) {
469 //TODO: need specific wide routine that can handle fp regs
470 if (scale) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800471 int rNewIndex = dvmCompilerAllocTemp(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700472 opRegRegImm(cUnit, kOpLsl, rNewIndex, rlIndex.lowReg, scale);
473 opRegReg(cUnit, kOpAdd, regPtr, rNewIndex);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800474 dvmCompilerFreeTemp(cUnit, rNewIndex);
Bill Buzbee1465db52009-09-23 17:17:35 -0700475 } else {
476 opRegReg(cUnit, kOpAdd, regPtr, rlIndex.lowReg);
477 }
478 rlSrc = loadValueWide(cUnit, rlSrc, kAnyReg);
Ben Cheng11d8f142010-03-24 15:24:19 -0700479
480 HEAP_ACCESS_SHADOW(true);
Bill Buzbee1465db52009-09-23 17:17:35 -0700481 storePair(cUnit, regPtr, rlSrc.lowReg, rlSrc.highReg);
Ben Cheng11d8f142010-03-24 15:24:19 -0700482 HEAP_ACCESS_SHADOW(false);
483
Bill Buzbeec6f10662010-02-09 11:16:15 -0800484 dvmCompilerFreeTemp(cUnit, regPtr);
Bill Buzbee270c1d62009-08-13 16:58:07 -0700485 } else {
Bill Buzbee1465db52009-09-23 17:17:35 -0700486 rlSrc = loadValue(cUnit, rlSrc, kAnyReg);
Ben Cheng11d8f142010-03-24 15:24:19 -0700487
488 HEAP_ACCESS_SHADOW(true);
Bill Buzbee1465db52009-09-23 17:17:35 -0700489 storeBaseIndexed(cUnit, regPtr, rlIndex.lowReg, rlSrc.lowReg,
490 scale, size);
Ben Cheng11d8f142010-03-24 15:24:19 -0700491 HEAP_ACCESS_SHADOW(false);
jeffhao9e45c0b2010-02-03 10:24:05 -0800492 }
Ben Chengba4fc8b2009-06-01 13:00:29 -0700493}
494
Bill Buzbeebe6534f2010-03-12 16:01:35 -0800495/*
496 * Generate array object store
497 * Must use explicit register allocation here because of
498 * call-out to dvmCanPutArrayElement
499 */
500static void genArrayObjectPut(CompilationUnit *cUnit, MIR *mir,
501 RegLocation rlArray, RegLocation rlIndex,
502 RegLocation rlSrc, int scale)
503{
504 int lenOffset = offsetof(ArrayObject, length);
505 int dataOffset = offsetof(ArrayObject, contents);
506
507 dvmCompilerFlushAllRegs(cUnit);
508
509 int regLen = r0;
510 int regPtr = r4PC; /* Preserved across call */
511 int regArray = r1;
512 int regIndex = r7; /* Preserved across call */
513
514 loadValueDirectFixed(cUnit, rlArray, regArray);
515 loadValueDirectFixed(cUnit, rlIndex, regIndex);
516
517 /* null object? */
518 ArmLIR * pcrLabel = NULL;
519
520 if (!(mir->OptimizationFlags & MIR_IGNORE_NULL_CHECK)) {
521 pcrLabel = genNullCheck(cUnit, rlArray.sRegLow, regArray,
522 mir->offset, NULL);
523 }
524
525 if (!(mir->OptimizationFlags & MIR_IGNORE_RANGE_CHECK)) {
526 /* Get len */
527 loadWordDisp(cUnit, regArray, lenOffset, regLen);
528 /* regPtr -> array data */
529 opRegRegImm(cUnit, kOpAdd, regPtr, regArray, dataOffset);
530 genBoundsCheck(cUnit, regIndex, regLen, mir->offset,
531 pcrLabel);
532 } else {
533 /* regPtr -> array data */
534 opRegRegImm(cUnit, kOpAdd, regPtr, regArray, dataOffset);
535 }
536
537 /* Get object to store */
538 loadValueDirectFixed(cUnit, rlSrc, r0);
539 loadConstant(cUnit, r2, (int)dvmCanPutArrayElement);
540
541 /* Are we storing null? If so, avoid check */
542 opRegImm(cUnit, kOpCmp, r0, 0);
543 ArmLIR *branchOver = opCondBranch(cUnit, kArmCondEq);
544
545 /* Make sure the types are compatible */
546 loadWordDisp(cUnit, regArray, offsetof(Object, clazz), r1);
547 loadWordDisp(cUnit, r0, offsetof(Object, clazz), r0);
548 opReg(cUnit, kOpBlx, r2);
549 dvmCompilerClobberCallRegs(cUnit);
Bill Buzbee900a3af2010-03-16 12:41:43 -0700550
551 /*
552 * Using fixed registers here, and counting on r4 and r7 being
553 * preserved across the above call. Tell the register allocation
554 * utilities about the regs we are using directly
555 */
556 dvmCompilerLockTemp(cUnit, regPtr); // r4PC
557 dvmCompilerLockTemp(cUnit, regIndex); // r7
558 dvmCompilerLockTemp(cUnit, r0);
559
Bill Buzbeebe6534f2010-03-12 16:01:35 -0800560 /* Bad? - roll back and re-execute if so */
561 genRegImmCheck(cUnit, kArmCondEq, r0, 0, mir->offset, pcrLabel);
562
563 /* Resume here - must reload element, regPtr & index preserved */
564 loadValueDirectFixed(cUnit, rlSrc, r0);
565
566 ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel);
567 target->defMask = ENCODE_ALL;
568 branchOver->generic.target = (LIR *) target;
569
Ben Cheng11d8f142010-03-24 15:24:19 -0700570 HEAP_ACCESS_SHADOW(true);
Bill Buzbeebe6534f2010-03-12 16:01:35 -0800571 storeBaseIndexed(cUnit, regPtr, regIndex, r0,
572 scale, kWord);
Ben Cheng11d8f142010-03-24 15:24:19 -0700573 HEAP_ACCESS_SHADOW(false);
Bill Buzbeebe6534f2010-03-12 16:01:35 -0800574}
575
Ben Cheng5d90c202009-11-22 23:31:11 -0800576static bool genShiftOpLong(CompilationUnit *cUnit, MIR *mir,
577 RegLocation rlDest, RegLocation rlSrc1,
578 RegLocation rlShift)
Ben Chengba4fc8b2009-06-01 13:00:29 -0700579{
Ben Chenge9695e52009-06-16 16:11:47 -0700580 /*
581 * Don't mess with the regsiters here as there is a particular calling
582 * convention to the out-of-line handler.
583 */
Bill Buzbee1465db52009-09-23 17:17:35 -0700584 RegLocation rlResult;
585
586 loadValueDirectWideFixed(cUnit, rlSrc1, r0, r1);
587 loadValueDirect(cUnit, rlShift, r2);
Ben Chenge9695e52009-06-16 16:11:47 -0700588 switch( mir->dalvikInsn.opCode) {
589 case OP_SHL_LONG:
590 case OP_SHL_LONG_2ADDR:
591 genDispatchToHandler(cUnit, TEMPLATE_SHL_LONG);
592 break;
593 case OP_SHR_LONG:
594 case OP_SHR_LONG_2ADDR:
595 genDispatchToHandler(cUnit, TEMPLATE_SHR_LONG);
596 break;
597 case OP_USHR_LONG:
598 case OP_USHR_LONG_2ADDR:
599 genDispatchToHandler(cUnit, TEMPLATE_USHR_LONG);
600 break;
601 default:
602 return true;
603 }
Bill Buzbeec6f10662010-02-09 11:16:15 -0800604 rlResult = dvmCompilerGetReturnWide(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700605 storeValueWide(cUnit, rlDest, rlResult);
Ben Chenge9695e52009-06-16 16:11:47 -0700606 return false;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700607}
Ben Chenge9695e52009-06-16 16:11:47 -0700608
Ben Cheng5d90c202009-11-22 23:31:11 -0800609static bool genArithOpLong(CompilationUnit *cUnit, MIR *mir,
610 RegLocation rlDest, RegLocation rlSrc1,
611 RegLocation rlSrc2)
Ben Chengba4fc8b2009-06-01 13:00:29 -0700612{
Bill Buzbee1465db52009-09-23 17:17:35 -0700613 RegLocation rlResult;
614 OpKind firstOp = kOpBkpt;
615 OpKind secondOp = kOpBkpt;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700616 bool callOut = false;
617 void *callTgt;
618 int retReg = r0;
619 /* TODO - find proper .h file to declare these */
620 long long __aeabi_ldivmod(long long op1, long long op2);
621
622 switch (mir->dalvikInsn.opCode) {
623 case OP_NOT_LONG:
Bill Buzbee1465db52009-09-23 17:17:35 -0700624 rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800625 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -0700626 opRegReg(cUnit, kOpMvn, rlResult.lowReg, rlSrc2.lowReg);
627 opRegReg(cUnit, kOpMvn, rlResult.highReg, rlSrc2.highReg);
628 storeValueWide(cUnit, rlDest, rlResult);
629 return false;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700630 break;
631 case OP_ADD_LONG:
632 case OP_ADD_LONG_2ADDR:
Bill Buzbee1465db52009-09-23 17:17:35 -0700633 firstOp = kOpAdd;
634 secondOp = kOpAdc;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700635 break;
636 case OP_SUB_LONG:
637 case OP_SUB_LONG_2ADDR:
Bill Buzbee1465db52009-09-23 17:17:35 -0700638 firstOp = kOpSub;
639 secondOp = kOpSbc;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700640 break;
641 case OP_MUL_LONG:
642 case OP_MUL_LONG_2ADDR:
Bill Buzbee1465db52009-09-23 17:17:35 -0700643 genMulLong(cUnit, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700644 return false;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700645 case OP_DIV_LONG:
646 case OP_DIV_LONG_2ADDR:
647 callOut = true;
648 retReg = r0;
649 callTgt = (void*)__aeabi_ldivmod;
650 break;
651 /* NOTE - result is in r2/r3 instead of r0/r1 */
652 case OP_REM_LONG:
653 case OP_REM_LONG_2ADDR:
654 callOut = true;
655 callTgt = (void*)__aeabi_ldivmod;
656 retReg = r2;
657 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700658 case OP_AND_LONG_2ADDR:
Bill Buzbee1465db52009-09-23 17:17:35 -0700659 case OP_AND_LONG:
660 firstOp = kOpAnd;
661 secondOp = kOpAnd;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700662 break;
663 case OP_OR_LONG:
664 case OP_OR_LONG_2ADDR:
Bill Buzbee1465db52009-09-23 17:17:35 -0700665 firstOp = kOpOr;
666 secondOp = kOpOr;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700667 break;
668 case OP_XOR_LONG:
669 case OP_XOR_LONG_2ADDR:
Bill Buzbee1465db52009-09-23 17:17:35 -0700670 firstOp = kOpXor;
671 secondOp = kOpXor;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700672 break;
Ben Chenge9695e52009-06-16 16:11:47 -0700673 case OP_NEG_LONG: {
Bill Buzbee51ecf602010-01-14 14:27:52 -0800674 //TUNING: can improve this using Thumb2 code
Bill Buzbeec6f10662010-02-09 11:16:15 -0800675 int tReg = dvmCompilerAllocTemp(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700676 rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800677 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee51ecf602010-01-14 14:27:52 -0800678 loadConstantValue(cUnit, tReg, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -0700679 opRegRegReg(cUnit, kOpSub, rlResult.lowReg,
Bill Buzbee51ecf602010-01-14 14:27:52 -0800680 tReg, rlSrc2.lowReg);
681 opRegReg(cUnit, kOpSbc, tReg, rlSrc2.highReg);
682 genRegCopy(cUnit, rlResult.highReg, tReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700683 storeValueWide(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700684 return false;
Ben Chenge9695e52009-06-16 16:11:47 -0700685 }
Ben Chengba4fc8b2009-06-01 13:00:29 -0700686 default:
687 LOGE("Invalid long arith op");
Bill Buzbeefc519dc2010-03-06 23:30:57 -0800688 dvmCompilerAbort(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700689 }
690 if (!callOut) {
Bill Buzbee80cef862010-03-25 10:38:34 -0700691 genLong3Addr(cUnit, mir, firstOp, secondOp, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700692 } else {
Bill Buzbee1465db52009-09-23 17:17:35 -0700693 // Adjust return regs in to handle case of rem returning r2/r3
Bill Buzbeec6f10662010-02-09 11:16:15 -0800694 dvmCompilerFlushAllRegs(cUnit); /* Send everything to home location */
Bill Buzbee1465db52009-09-23 17:17:35 -0700695 loadValueDirectWideFixed(cUnit, rlSrc1, r0, r1);
696 loadConstant(cUnit, rlr, (int) callTgt);
697 loadValueDirectWideFixed(cUnit, rlSrc2, r2, r3);
698 opReg(cUnit, kOpBlx, rlr);
Elliott Hughes6a555132010-02-25 15:41:42 -0800699 dvmCompilerClobberCallRegs(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700700 if (retReg == r0)
Bill Buzbeec6f10662010-02-09 11:16:15 -0800701 rlResult = dvmCompilerGetReturnWide(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700702 else
Bill Buzbeec6f10662010-02-09 11:16:15 -0800703 rlResult = dvmCompilerGetReturnWideAlt(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700704 storeValueWide(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700705 }
706 return false;
707}
708
Ben Cheng5d90c202009-11-22 23:31:11 -0800709static bool genArithOpInt(CompilationUnit *cUnit, MIR *mir,
710 RegLocation rlDest, RegLocation rlSrc1,
711 RegLocation rlSrc2)
Ben Chengba4fc8b2009-06-01 13:00:29 -0700712{
Bill Buzbee1465db52009-09-23 17:17:35 -0700713 OpKind op = kOpBkpt;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700714 bool callOut = false;
715 bool checkZero = false;
Bill Buzbee1465db52009-09-23 17:17:35 -0700716 bool unary = false;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700717 int retReg = r0;
718 void *callTgt;
Bill Buzbee1465db52009-09-23 17:17:35 -0700719 RegLocation rlResult;
Bill Buzbee0e605272009-12-01 14:28:05 -0800720 bool shiftOp = false;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700721
722 /* TODO - find proper .h file to declare these */
723 int __aeabi_idivmod(int op1, int op2);
724 int __aeabi_idiv(int op1, int op2);
725
726 switch (mir->dalvikInsn.opCode) {
727 case OP_NEG_INT:
Bill Buzbee1465db52009-09-23 17:17:35 -0700728 op = kOpNeg;
729 unary = true;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700730 break;
731 case OP_NOT_INT:
Bill Buzbee1465db52009-09-23 17:17:35 -0700732 op = kOpMvn;
733 unary = true;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700734 break;
735 case OP_ADD_INT:
736 case OP_ADD_INT_2ADDR:
Bill Buzbee1465db52009-09-23 17:17:35 -0700737 op = kOpAdd;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700738 break;
739 case OP_SUB_INT:
740 case OP_SUB_INT_2ADDR:
Bill Buzbee1465db52009-09-23 17:17:35 -0700741 op = kOpSub;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700742 break;
743 case OP_MUL_INT:
744 case OP_MUL_INT_2ADDR:
Bill Buzbee1465db52009-09-23 17:17:35 -0700745 op = kOpMul;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700746 break;
747 case OP_DIV_INT:
748 case OP_DIV_INT_2ADDR:
749 callOut = true;
750 checkZero = true;
751 callTgt = __aeabi_idiv;
752 retReg = r0;
753 break;
754 /* NOTE: returns in r1 */
755 case OP_REM_INT:
756 case OP_REM_INT_2ADDR:
757 callOut = true;
758 checkZero = true;
759 callTgt = __aeabi_idivmod;
760 retReg = r1;
761 break;
762 case OP_AND_INT:
763 case OP_AND_INT_2ADDR:
Bill Buzbee1465db52009-09-23 17:17:35 -0700764 op = kOpAnd;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700765 break;
766 case OP_OR_INT:
767 case OP_OR_INT_2ADDR:
Bill Buzbee1465db52009-09-23 17:17:35 -0700768 op = kOpOr;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700769 break;
770 case OP_XOR_INT:
771 case OP_XOR_INT_2ADDR:
Bill Buzbee1465db52009-09-23 17:17:35 -0700772 op = kOpXor;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700773 break;
774 case OP_SHL_INT:
775 case OP_SHL_INT_2ADDR:
Bill Buzbee0e605272009-12-01 14:28:05 -0800776 shiftOp = true;
Bill Buzbee1465db52009-09-23 17:17:35 -0700777 op = kOpLsl;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700778 break;
779 case OP_SHR_INT:
780 case OP_SHR_INT_2ADDR:
Bill Buzbee0e605272009-12-01 14:28:05 -0800781 shiftOp = true;
Bill Buzbee1465db52009-09-23 17:17:35 -0700782 op = kOpAsr;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700783 break;
784 case OP_USHR_INT:
785 case OP_USHR_INT_2ADDR:
Bill Buzbee0e605272009-12-01 14:28:05 -0800786 shiftOp = true;
Bill Buzbee1465db52009-09-23 17:17:35 -0700787 op = kOpLsr;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700788 break;
789 default:
790 LOGE("Invalid word arith op: 0x%x(%d)",
791 mir->dalvikInsn.opCode, mir->dalvikInsn.opCode);
Bill Buzbeefc519dc2010-03-06 23:30:57 -0800792 dvmCompilerAbort(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700793 }
794 if (!callOut) {
Bill Buzbee1465db52009-09-23 17:17:35 -0700795 rlSrc1 = loadValue(cUnit, rlSrc1, kCoreReg);
796 if (unary) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800797 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -0700798 opRegReg(cUnit, op, rlResult.lowReg,
799 rlSrc1.lowReg);
Ben Chenge9695e52009-06-16 16:11:47 -0700800 } else {
Bill Buzbee1465db52009-09-23 17:17:35 -0700801 rlSrc2 = loadValue(cUnit, rlSrc2, kCoreReg);
Bill Buzbee0e605272009-12-01 14:28:05 -0800802 if (shiftOp) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800803 int tReg = dvmCompilerAllocTemp(cUnit);
Bill Buzbee0e605272009-12-01 14:28:05 -0800804 opRegRegImm(cUnit, kOpAnd, tReg, rlSrc2.lowReg, 31);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800805 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee0e605272009-12-01 14:28:05 -0800806 opRegRegReg(cUnit, op, rlResult.lowReg,
807 rlSrc1.lowReg, tReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800808 dvmCompilerFreeTemp(cUnit, tReg);
Bill Buzbee0e605272009-12-01 14:28:05 -0800809 } else {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800810 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee0e605272009-12-01 14:28:05 -0800811 opRegRegReg(cUnit, op, rlResult.lowReg,
812 rlSrc1.lowReg, rlSrc2.lowReg);
813 }
Ben Chenge9695e52009-06-16 16:11:47 -0700814 }
Bill Buzbee1465db52009-09-23 17:17:35 -0700815 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700816 } else {
Bill Buzbee1465db52009-09-23 17:17:35 -0700817 RegLocation rlResult;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800818 dvmCompilerFlushAllRegs(cUnit); /* Send everything to home location */
Bill Buzbee1465db52009-09-23 17:17:35 -0700819 loadValueDirectFixed(cUnit, rlSrc2, r1);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700820 loadConstant(cUnit, r2, (int) callTgt);
Bill Buzbee1465db52009-09-23 17:17:35 -0700821 loadValueDirectFixed(cUnit, rlSrc1, r0);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700822 if (checkZero) {
Bill Buzbee1465db52009-09-23 17:17:35 -0700823 genNullCheck(cUnit, rlSrc2.sRegLow, r1, mir->offset, NULL);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700824 }
Bill Buzbee1465db52009-09-23 17:17:35 -0700825 opReg(cUnit, kOpBlx, r2);
Elliott Hughes6a555132010-02-25 15:41:42 -0800826 dvmCompilerClobberCallRegs(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700827 if (retReg == r0)
Bill Buzbeec6f10662010-02-09 11:16:15 -0800828 rlResult = dvmCompilerGetReturn(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700829 else
Bill Buzbeec6f10662010-02-09 11:16:15 -0800830 rlResult = dvmCompilerGetReturnAlt(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700831 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700832 }
833 return false;
834}
835
Ben Cheng5d90c202009-11-22 23:31:11 -0800836static bool genArithOp(CompilationUnit *cUnit, MIR *mir)
Ben Chengba4fc8b2009-06-01 13:00:29 -0700837{
838 OpCode opCode = mir->dalvikInsn.opCode;
Bill Buzbee1465db52009-09-23 17:17:35 -0700839 RegLocation rlDest;
840 RegLocation rlSrc1;
841 RegLocation rlSrc2;
842 /* Deduce sizes of operands */
843 if (mir->ssaRep->numUses == 2) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800844 rlSrc1 = dvmCompilerGetSrc(cUnit, mir, 0);
845 rlSrc2 = dvmCompilerGetSrc(cUnit, mir, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -0700846 } else if (mir->ssaRep->numUses == 3) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800847 rlSrc1 = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
848 rlSrc2 = dvmCompilerGetSrc(cUnit, mir, 2);
Bill Buzbee1465db52009-09-23 17:17:35 -0700849 } else {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800850 rlSrc1 = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
851 rlSrc2 = dvmCompilerGetSrcWide(cUnit, mir, 2, 3);
Bill Buzbee1465db52009-09-23 17:17:35 -0700852 assert(mir->ssaRep->numUses == 4);
853 }
854 if (mir->ssaRep->numDefs == 1) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800855 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -0700856 } else {
857 assert(mir->ssaRep->numDefs == 2);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800858 rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -0700859 }
Ben Chengba4fc8b2009-06-01 13:00:29 -0700860
861 if ((opCode >= OP_ADD_LONG_2ADDR) && (opCode <= OP_XOR_LONG_2ADDR)) {
Ben Cheng5d90c202009-11-22 23:31:11 -0800862 return genArithOpLong(cUnit,mir, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700863 }
864 if ((opCode >= OP_ADD_LONG) && (opCode <= OP_XOR_LONG)) {
Ben Cheng5d90c202009-11-22 23:31:11 -0800865 return genArithOpLong(cUnit,mir, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700866 }
867 if ((opCode >= OP_SHL_LONG_2ADDR) && (opCode <= OP_USHR_LONG_2ADDR)) {
Ben Cheng5d90c202009-11-22 23:31:11 -0800868 return genShiftOpLong(cUnit,mir, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700869 }
870 if ((opCode >= OP_SHL_LONG) && (opCode <= OP_USHR_LONG)) {
Ben Cheng5d90c202009-11-22 23:31:11 -0800871 return genShiftOpLong(cUnit,mir, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700872 }
873 if ((opCode >= OP_ADD_INT_2ADDR) && (opCode <= OP_USHR_INT_2ADDR)) {
Ben Cheng5d90c202009-11-22 23:31:11 -0800874 return genArithOpInt(cUnit,mir, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700875 }
876 if ((opCode >= OP_ADD_INT) && (opCode <= OP_USHR_INT)) {
Ben Cheng5d90c202009-11-22 23:31:11 -0800877 return genArithOpInt(cUnit,mir, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700878 }
879 if ((opCode >= OP_ADD_FLOAT_2ADDR) && (opCode <= OP_REM_FLOAT_2ADDR)) {
Ben Cheng5d90c202009-11-22 23:31:11 -0800880 return genArithOpFloat(cUnit,mir, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700881 }
882 if ((opCode >= OP_ADD_FLOAT) && (opCode <= OP_REM_FLOAT)) {
Ben Cheng5d90c202009-11-22 23:31:11 -0800883 return genArithOpFloat(cUnit, mir, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700884 }
885 if ((opCode >= OP_ADD_DOUBLE_2ADDR) && (opCode <= OP_REM_DOUBLE_2ADDR)) {
Ben Cheng5d90c202009-11-22 23:31:11 -0800886 return genArithOpDouble(cUnit,mir, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700887 }
888 if ((opCode >= OP_ADD_DOUBLE) && (opCode <= OP_REM_DOUBLE)) {
Ben Cheng5d90c202009-11-22 23:31:11 -0800889 return genArithOpDouble(cUnit,mir, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700890 }
891 return true;
892}
893
Bill Buzbee1465db52009-09-23 17:17:35 -0700894/* Generate unconditional branch instructions */
895static ArmLIR *genUnconditionalBranch(CompilationUnit *cUnit, ArmLIR *target)
896{
897 ArmLIR *branch = opNone(cUnit, kOpUncondBr);
898 branch->generic.target = (LIR *) target;
899 return branch;
900}
901
Bill Buzbee1465db52009-09-23 17:17:35 -0700902/* Perform the actual operation for OP_RETURN_* */
903static void genReturnCommon(CompilationUnit *cUnit, MIR *mir)
904{
905 genDispatchToHandler(cUnit, TEMPLATE_RETURN);
Ben Cheng86717f72010-03-05 15:27:21 -0800906#if defined(JIT_STATS)
Bill Buzbee1465db52009-09-23 17:17:35 -0700907 gDvmJit.returnOp++;
908#endif
909 int dPC = (int) (cUnit->method->insns + mir->offset);
910 /* Insert branch, but defer setting of target */
911 ArmLIR *branch = genUnconditionalBranch(cUnit, NULL);
912 /* Set up the place holder to reconstruct this Dalvik PC */
913 ArmLIR *pcrLabel = dvmCompilerNew(sizeof(ArmLIR), true);
914 pcrLabel->opCode = ARM_PSEUDO_kPCReconstruction_CELL;
915 pcrLabel->operands[0] = dPC;
916 pcrLabel->operands[1] = mir->offset;
917 /* Insert the place holder to the growable list */
918 dvmInsertGrowableList(&cUnit->pcReconstructionList, pcrLabel);
919 /* Branch to the PC reconstruction code */
920 branch->generic.target = (LIR *) pcrLabel;
921}
922
Ben Chengba4fc8b2009-06-01 13:00:29 -0700923static void genProcessArgsNoRange(CompilationUnit *cUnit, MIR *mir,
924 DecodedInstruction *dInsn,
Bill Buzbee89efc3d2009-07-28 11:22:22 -0700925 ArmLIR **pcrLabel)
Ben Chengba4fc8b2009-06-01 13:00:29 -0700926{
927 unsigned int i;
928 unsigned int regMask = 0;
Bill Buzbee1465db52009-09-23 17:17:35 -0700929 RegLocation rlArg;
930 int numDone = 0;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700931
Bill Buzbee1465db52009-09-23 17:17:35 -0700932 /*
933 * Load arguments to r0..r4. Note that these registers may contain
934 * live values, so we clobber them immediately after loading to prevent
935 * them from being used as sources for subsequent loads.
936 */
Bill Buzbeec6f10662010-02-09 11:16:15 -0800937 dvmCompilerLockAllTemps(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700938 for (i = 0; i < dInsn->vA; i++) {
939 regMask |= 1 << i;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800940 rlArg = dvmCompilerGetSrc(cUnit, mir, numDone++);
Bill Buzbee1465db52009-09-23 17:17:35 -0700941 loadValueDirectFixed(cUnit, rlArg, i);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700942 }
943 if (regMask) {
944 /* Up to 5 args are pushed on top of FP - sizeofStackSaveArea */
Bill Buzbee1465db52009-09-23 17:17:35 -0700945 opRegRegImm(cUnit, kOpSub, r7, rFP,
946 sizeof(StackSaveArea) + (dInsn->vA << 2));
Ben Chengba4fc8b2009-06-01 13:00:29 -0700947 /* generate null check */
948 if (pcrLabel) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800949 *pcrLabel = genNullCheck(cUnit, dvmCompilerSSASrc(mir, 0), r0,
Bill Buzbee1465db52009-09-23 17:17:35 -0700950 mir->offset, NULL);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700951 }
Bill Buzbee270c1d62009-08-13 16:58:07 -0700952 storeMultiple(cUnit, r7, regMask);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700953 }
954}
955
956static void genProcessArgsRange(CompilationUnit *cUnit, MIR *mir,
957 DecodedInstruction *dInsn,
Bill Buzbee89efc3d2009-07-28 11:22:22 -0700958 ArmLIR **pcrLabel)
Ben Chengba4fc8b2009-06-01 13:00:29 -0700959{
960 int srcOffset = dInsn->vC << 2;
961 int numArgs = dInsn->vA;
962 int regMask;
Bill Buzbee1465db52009-09-23 17:17:35 -0700963
964 /*
965 * Note: here, all promoted registers will have been flushed
966 * back to the Dalvik base locations, so register usage restrictins
967 * are lifted. All parms loaded from original Dalvik register
968 * region - even though some might conceivably have valid copies
969 * cached in a preserved register.
970 */
Bill Buzbeec6f10662010-02-09 11:16:15 -0800971 dvmCompilerLockAllTemps(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700972
Ben Chengba4fc8b2009-06-01 13:00:29 -0700973 /*
974 * r4PC : &rFP[vC]
975 * r7: &newFP[0]
976 */
Bill Buzbee1465db52009-09-23 17:17:35 -0700977 opRegRegImm(cUnit, kOpAdd, r4PC, rFP, srcOffset);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700978 /* load [r0 .. min(numArgs,4)] */
979 regMask = (1 << ((numArgs < 4) ? numArgs : 4)) - 1;
Ben Chengd7d426a2009-09-22 11:23:36 -0700980 /*
981 * Protect the loadMultiple instruction from being reordered with other
982 * Dalvik stack accesses.
983 */
Bill Buzbee270c1d62009-08-13 16:58:07 -0700984 loadMultiple(cUnit, r4PC, regMask);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700985
Bill Buzbee1465db52009-09-23 17:17:35 -0700986 opRegRegImm(cUnit, kOpSub, r7, rFP,
987 sizeof(StackSaveArea) + (numArgs << 2));
Ben Chengba4fc8b2009-06-01 13:00:29 -0700988 /* generate null check */
989 if (pcrLabel) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800990 *pcrLabel = genNullCheck(cUnit, dvmCompilerSSASrc(mir, 0), r0,
Bill Buzbee1465db52009-09-23 17:17:35 -0700991 mir->offset, NULL);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700992 }
993
994 /*
995 * Handle remaining 4n arguments:
996 * store previously loaded 4 values and load the next 4 values
997 */
998 if (numArgs >= 8) {
Bill Buzbee89efc3d2009-07-28 11:22:22 -0700999 ArmLIR *loopLabel = NULL;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001000 /*
1001 * r0 contains "this" and it will be used later, so push it to the stack
Bill Buzbee270c1d62009-08-13 16:58:07 -07001002 * first. Pushing r5 (rFP) is just for stack alignment purposes.
Ben Chengba4fc8b2009-06-01 13:00:29 -07001003 */
Bill Buzbee1465db52009-09-23 17:17:35 -07001004 opImm(cUnit, kOpPush, (1 << r0 | 1 << rFP));
Ben Chengba4fc8b2009-06-01 13:00:29 -07001005 /* No need to generate the loop structure if numArgs <= 11 */
1006 if (numArgs > 11) {
1007 loadConstant(cUnit, 5, ((numArgs - 4) >> 2) << 2);
Bill Buzbee1465db52009-09-23 17:17:35 -07001008 loopLabel = newLIR0(cUnit, kArmPseudoTargetLabel);
Ben Chengd7d426a2009-09-22 11:23:36 -07001009 loopLabel->defMask = ENCODE_ALL;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001010 }
Bill Buzbee270c1d62009-08-13 16:58:07 -07001011 storeMultiple(cUnit, r7, regMask);
Ben Chengd7d426a2009-09-22 11:23:36 -07001012 /*
1013 * Protect the loadMultiple instruction from being reordered with other
1014 * Dalvik stack accesses.
1015 */
Bill Buzbee270c1d62009-08-13 16:58:07 -07001016 loadMultiple(cUnit, r4PC, regMask);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001017 /* No need to generate the loop structure if numArgs <= 11 */
1018 if (numArgs > 11) {
Bill Buzbee1465db52009-09-23 17:17:35 -07001019 opRegImm(cUnit, kOpSub, rFP, 4);
1020 genConditionalBranch(cUnit, kArmCondNe, loopLabel);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001021 }
1022 }
1023
1024 /* Save the last batch of loaded values */
Bill Buzbee270c1d62009-08-13 16:58:07 -07001025 storeMultiple(cUnit, r7, regMask);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001026
1027 /* Generate the loop epilogue - don't use r0 */
1028 if ((numArgs > 4) && (numArgs % 4)) {
1029 regMask = ((1 << (numArgs & 0x3)) - 1) << 1;
Ben Chengd7d426a2009-09-22 11:23:36 -07001030 /*
1031 * Protect the loadMultiple instruction from being reordered with other
1032 * Dalvik stack accesses.
1033 */
Bill Buzbee270c1d62009-08-13 16:58:07 -07001034 loadMultiple(cUnit, r4PC, regMask);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001035 }
1036 if (numArgs >= 8)
Bill Buzbee1465db52009-09-23 17:17:35 -07001037 opImm(cUnit, kOpPop, (1 << r0 | 1 << rFP));
Ben Chengba4fc8b2009-06-01 13:00:29 -07001038
1039 /* Save the modulo 4 arguments */
1040 if ((numArgs > 4) && (numArgs % 4)) {
Bill Buzbee270c1d62009-08-13 16:58:07 -07001041 storeMultiple(cUnit, r7, regMask);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001042 }
1043}
1044
Ben Cheng38329f52009-07-07 14:19:20 -07001045/*
1046 * Generate code to setup the call stack then jump to the chaining cell if it
1047 * is not a native method.
1048 */
1049static void genInvokeSingletonCommon(CompilationUnit *cUnit, MIR *mir,
Bill Buzbee89efc3d2009-07-28 11:22:22 -07001050 BasicBlock *bb, ArmLIR *labelList,
1051 ArmLIR *pcrLabel,
Ben Cheng38329f52009-07-07 14:19:20 -07001052 const Method *calleeMethod)
Ben Chengba4fc8b2009-06-01 13:00:29 -07001053{
Bill Buzbee1465db52009-09-23 17:17:35 -07001054 /*
1055 * Note: all Dalvik register state should be flushed to
1056 * memory by the point, so register usage restrictions no
1057 * longer apply. All temp & preserved registers may be used.
1058 */
Bill Buzbeec6f10662010-02-09 11:16:15 -08001059 dvmCompilerLockAllTemps(cUnit);
Bill Buzbee89efc3d2009-07-28 11:22:22 -07001060 ArmLIR *retChainingCell = &labelList[bb->fallThrough->id];
Ben Chengba4fc8b2009-06-01 13:00:29 -07001061
1062 /* r1 = &retChainingCell */
Bill Buzbeec6f10662010-02-09 11:16:15 -08001063 dvmCompilerLockTemp(cUnit, r1);
Bill Buzbee1465db52009-09-23 17:17:35 -07001064 ArmLIR *addrRetChain = opRegRegImm(cUnit, kOpAdd, r1, rpc, 0);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001065 /* r4PC = dalvikCallsite */
1066 loadConstant(cUnit, r4PC,
1067 (int) (cUnit->method->insns + mir->offset));
1068 addrRetChain->generic.target = (LIR *) retChainingCell;
1069 /*
Ben Cheng38329f52009-07-07 14:19:20 -07001070 * r0 = calleeMethod (loaded upon calling genInvokeSingletonCommon)
Ben Chengba4fc8b2009-06-01 13:00:29 -07001071 * r1 = &ChainingCell
1072 * r4PC = callsiteDPC
1073 */
1074 if (dvmIsNativeMethod(calleeMethod)) {
Ben Cheng38329f52009-07-07 14:19:20 -07001075 genDispatchToHandler(cUnit, TEMPLATE_INVOKE_METHOD_NATIVE);
Ben Cheng86717f72010-03-05 15:27:21 -08001076#if defined(JIT_STATS)
Ben Cheng38329f52009-07-07 14:19:20 -07001077 gDvmJit.invokeNative++;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001078#endif
1079 } else {
1080 genDispatchToHandler(cUnit, TEMPLATE_INVOKE_METHOD_CHAIN);
Ben Cheng86717f72010-03-05 15:27:21 -08001081#if defined(JIT_STATS)
1082 gDvmJit.invokeMonomorphic++;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001083#endif
Ben Cheng38329f52009-07-07 14:19:20 -07001084 /* Branch to the chaining cell */
Ben Chengba4fc8b2009-06-01 13:00:29 -07001085 genUnconditionalBranch(cUnit, &labelList[bb->taken->id]);
1086 }
1087 /* Handle exceptions using the interpreter */
1088 genTrap(cUnit, mir->offset, pcrLabel);
1089}
1090
Ben Cheng38329f52009-07-07 14:19:20 -07001091/*
1092 * Generate code to check the validity of a predicted chain and take actions
1093 * based on the result.
1094 *
1095 * 0x426a99aa : ldr r4, [pc, #72] --> r4 <- dalvikPC of this invoke
1096 * 0x426a99ac : add r1, pc, #32 --> r1 <- &retChainingCell
1097 * 0x426a99ae : add r2, pc, #40 --> r2 <- &predictedChainingCell
1098 * 0x426a99b0 : blx_1 0x426a918c --+ TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN
1099 * 0x426a99b2 : blx_2 see above --+
1100 * 0x426a99b4 : b 0x426a99d8 --> off to the predicted chain
1101 * 0x426a99b6 : b 0x426a99c8 --> punt to the interpreter
1102 * 0x426a99b8 : ldr r0, [r7, #44] --> r0 <- this->class->vtable[methodIdx]
1103 * 0x426a99ba : cmp r1, #0 --> compare r1 (rechain count) against 0
1104 * 0x426a99bc : bgt 0x426a99c2 --> >=0? don't rechain
1105 * 0x426a99be : ldr r7, [r6, #96] --+ dvmJitToPatchPredictedChain
1106 * 0x426a99c0 : blx r7 --+
1107 * 0x426a99c2 : add r1, pc, #12 --> r1 <- &retChainingCell
1108 * 0x426a99c4 : blx_1 0x426a9098 --+ TEMPLATE_INVOKE_METHOD_NO_OPT
1109 * 0x426a99c6 : blx_2 see above --+
1110 */
1111static void genInvokeVirtualCommon(CompilationUnit *cUnit, MIR *mir,
1112 int methodIndex,
Bill Buzbee89efc3d2009-07-28 11:22:22 -07001113 ArmLIR *retChainingCell,
1114 ArmLIR *predChainingCell,
1115 ArmLIR *pcrLabel)
Ben Cheng38329f52009-07-07 14:19:20 -07001116{
Bill Buzbee1465db52009-09-23 17:17:35 -07001117 /*
1118 * Note: all Dalvik register state should be flushed to
1119 * memory by the point, so register usage restrictions no
1120 * longer apply. Lock temps to prevent them from being
1121 * allocated by utility routines.
1122 */
Bill Buzbeec6f10662010-02-09 11:16:15 -08001123 dvmCompilerLockAllTemps(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07001124
Ben Cheng38329f52009-07-07 14:19:20 -07001125 /* "this" is already left in r0 by genProcessArgs* */
1126
1127 /* r4PC = dalvikCallsite */
1128 loadConstant(cUnit, r4PC,
1129 (int) (cUnit->method->insns + mir->offset));
1130
1131 /* r1 = &retChainingCell */
Bill Buzbee1465db52009-09-23 17:17:35 -07001132 ArmLIR *addrRetChain = opRegRegImm(cUnit, kOpAdd, r1, rpc, 0);
Ben Cheng38329f52009-07-07 14:19:20 -07001133 addrRetChain->generic.target = (LIR *) retChainingCell;
1134
1135 /* r2 = &predictedChainingCell */
Bill Buzbee1465db52009-09-23 17:17:35 -07001136 ArmLIR *predictedChainingCell = opRegRegImm(cUnit, kOpAdd, r2, rpc, 0);
Ben Cheng38329f52009-07-07 14:19:20 -07001137 predictedChainingCell->generic.target = (LIR *) predChainingCell;
1138
1139 genDispatchToHandler(cUnit, TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN);
1140
1141 /* return through lr - jump to the chaining cell */
1142 genUnconditionalBranch(cUnit, predChainingCell);
1143
1144 /*
1145 * null-check on "this" may have been eliminated, but we still need a PC-
1146 * reconstruction label for stack overflow bailout.
1147 */
1148 if (pcrLabel == NULL) {
1149 int dPC = (int) (cUnit->method->insns + mir->offset);
Bill Buzbee89efc3d2009-07-28 11:22:22 -07001150 pcrLabel = dvmCompilerNew(sizeof(ArmLIR), true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001151 pcrLabel->opCode = ARM_PSEUDO_kPCReconstruction_CELL;
Ben Cheng38329f52009-07-07 14:19:20 -07001152 pcrLabel->operands[0] = dPC;
1153 pcrLabel->operands[1] = mir->offset;
1154 /* Insert the place holder to the growable list */
1155 dvmInsertGrowableList(&cUnit->pcReconstructionList, pcrLabel);
1156 }
1157
1158 /* return through lr+2 - punt to the interpreter */
1159 genUnconditionalBranch(cUnit, pcrLabel);
1160
1161 /*
1162 * return through lr+4 - fully resolve the callee method.
1163 * r1 <- count
1164 * r2 <- &predictedChainCell
1165 * r3 <- this->class
1166 * r4 <- dPC
1167 * r7 <- this->class->vtable
1168 */
1169
1170 /* r0 <- calleeMethod */
Bill Buzbee270c1d62009-08-13 16:58:07 -07001171 loadWordDisp(cUnit, r7, methodIndex * 4, r0);
Ben Cheng38329f52009-07-07 14:19:20 -07001172
1173 /* Check if rechain limit is reached */
Bill Buzbee1465db52009-09-23 17:17:35 -07001174 opRegImm(cUnit, kOpCmp, r1, 0);
Ben Cheng38329f52009-07-07 14:19:20 -07001175
Bill Buzbee1465db52009-09-23 17:17:35 -07001176 ArmLIR *bypassRechaining = opCondBranch(cUnit, kArmCondGt);
Ben Cheng38329f52009-07-07 14:19:20 -07001177
Bill Buzbee270c1d62009-08-13 16:58:07 -07001178 loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
1179 jitToInterpEntries.dvmJitToPatchPredictedChain), r7);
Ben Cheng38329f52009-07-07 14:19:20 -07001180
1181 /*
1182 * r0 = calleeMethod
1183 * r2 = &predictedChainingCell
1184 * r3 = class
1185 *
1186 * &returnChainingCell has been loaded into r1 but is not needed
1187 * when patching the chaining cell and will be clobbered upon
1188 * returning so it will be reconstructed again.
1189 */
Bill Buzbee1465db52009-09-23 17:17:35 -07001190 opReg(cUnit, kOpBlx, r7);
Ben Cheng38329f52009-07-07 14:19:20 -07001191
1192 /* r1 = &retChainingCell */
Bill Buzbee1465db52009-09-23 17:17:35 -07001193 addrRetChain = opRegRegImm(cUnit, kOpAdd, r1, rpc, 0);
Ben Cheng38329f52009-07-07 14:19:20 -07001194 addrRetChain->generic.target = (LIR *) retChainingCell;
1195
1196 bypassRechaining->generic.target = (LIR *) addrRetChain;
1197 /*
1198 * r0 = calleeMethod,
1199 * r1 = &ChainingCell,
1200 * r4PC = callsiteDPC,
1201 */
1202 genDispatchToHandler(cUnit, TEMPLATE_INVOKE_METHOD_NO_OPT);
Ben Cheng86717f72010-03-05 15:27:21 -08001203#if defined(JIT_STATS)
1204 gDvmJit.invokePolymorphic++;
Ben Cheng38329f52009-07-07 14:19:20 -07001205#endif
1206 /* Handle exceptions using the interpreter */
1207 genTrap(cUnit, mir->offset, pcrLabel);
1208}
1209
1210/*
1211 * Up calling this function, "this" is stored in r0. The actual class will be
1212 * chased down off r0 and the predicted one will be retrieved through
1213 * predictedChainingCell then a comparison is performed to see whether the
1214 * previously established chaining is still valid.
1215 *
1216 * The return LIR is a branch based on the comparison result. The actual branch
1217 * target will be setup in the caller.
1218 */
Bill Buzbee89efc3d2009-07-28 11:22:22 -07001219static ArmLIR *genCheckPredictedChain(CompilationUnit *cUnit,
1220 ArmLIR *predChainingCell,
1221 ArmLIR *retChainingCell,
Ben Cheng38329f52009-07-07 14:19:20 -07001222 MIR *mir)
1223{
Bill Buzbee1465db52009-09-23 17:17:35 -07001224 /*
1225 * Note: all Dalvik register state should be flushed to
1226 * memory by the point, so register usage restrictions no
1227 * longer apply. All temp & preserved registers may be used.
1228 */
Bill Buzbeec6f10662010-02-09 11:16:15 -08001229 dvmCompilerLockAllTemps(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07001230
Ben Cheng38329f52009-07-07 14:19:20 -07001231 /* r3 now contains this->clazz */
Bill Buzbee270c1d62009-08-13 16:58:07 -07001232 loadWordDisp(cUnit, r0, offsetof(Object, clazz), r3);
Ben Cheng38329f52009-07-07 14:19:20 -07001233
1234 /*
1235 * r2 now contains predicted class. The starting offset of the
1236 * cached value is 4 bytes into the chaining cell.
1237 */
Bill Buzbee89efc3d2009-07-28 11:22:22 -07001238 ArmLIR *getPredictedClass =
Bill Buzbee270c1d62009-08-13 16:58:07 -07001239 loadWordDisp(cUnit, rpc, offsetof(PredictedChainingCell, clazz), r2);
Ben Cheng38329f52009-07-07 14:19:20 -07001240 getPredictedClass->generic.target = (LIR *) predChainingCell;
1241
1242 /*
1243 * r0 now contains predicted method. The starting offset of the
1244 * cached value is 8 bytes into the chaining cell.
1245 */
Bill Buzbee89efc3d2009-07-28 11:22:22 -07001246 ArmLIR *getPredictedMethod =
Bill Buzbee270c1d62009-08-13 16:58:07 -07001247 loadWordDisp(cUnit, rpc, offsetof(PredictedChainingCell, method), r0);
Ben Cheng38329f52009-07-07 14:19:20 -07001248 getPredictedMethod->generic.target = (LIR *) predChainingCell;
1249
1250 /* Load the stats counter to see if it is time to unchain and refresh */
Bill Buzbee89efc3d2009-07-28 11:22:22 -07001251 ArmLIR *getRechainingRequestCount =
Bill Buzbee270c1d62009-08-13 16:58:07 -07001252 loadWordDisp(cUnit, rpc, offsetof(PredictedChainingCell, counter), r7);
Ben Cheng38329f52009-07-07 14:19:20 -07001253 getRechainingRequestCount->generic.target =
1254 (LIR *) predChainingCell;
1255
1256 /* r4PC = dalvikCallsite */
1257 loadConstant(cUnit, r4PC,
1258 (int) (cUnit->method->insns + mir->offset));
1259
1260 /* r1 = &retChainingCell */
Bill Buzbee1465db52009-09-23 17:17:35 -07001261 ArmLIR *addrRetChain = opRegRegImm(cUnit, kOpAdd, r1, rpc, 0);
Ben Cheng38329f52009-07-07 14:19:20 -07001262 addrRetChain->generic.target = (LIR *) retChainingCell;
1263
1264 /* Check if r2 (predicted class) == r3 (actual class) */
Bill Buzbee1465db52009-09-23 17:17:35 -07001265 opRegReg(cUnit, kOpCmp, r2, r3);
Ben Cheng38329f52009-07-07 14:19:20 -07001266
Bill Buzbee1465db52009-09-23 17:17:35 -07001267 return opCondBranch(cUnit, kArmCondEq);
Ben Cheng38329f52009-07-07 14:19:20 -07001268}
1269
Ben Chengba4fc8b2009-06-01 13:00:29 -07001270/* Geneate a branch to go back to the interpreter */
1271static void genPuntToInterp(CompilationUnit *cUnit, unsigned int offset)
1272{
1273 /* r0 = dalvik pc */
Bill Buzbeec6f10662010-02-09 11:16:15 -08001274 dvmCompilerFlushAllRegs(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001275 loadConstant(cUnit, r0, (int) (cUnit->method->insns + offset));
Bill Buzbee270c1d62009-08-13 16:58:07 -07001276 loadWordDisp(cUnit, r0, offsetof(Object, clazz), r3);
1277 loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
1278 jitToInterpEntries.dvmJitToInterpPunt), r1);
Bill Buzbee1465db52009-09-23 17:17:35 -07001279 opReg(cUnit, kOpBlx, r1);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001280}
1281
1282/*
1283 * Attempt to single step one instruction using the interpreter and return
1284 * to the compiled code for the next Dalvik instruction
1285 */
1286static void genInterpSingleStep(CompilationUnit *cUnit, MIR *mir)
1287{
1288 int flags = dexGetInstrFlags(gDvm.instrFlags, mir->dalvikInsn.opCode);
1289 int flagsToCheck = kInstrCanBranch | kInstrCanSwitch | kInstrCanReturn |
1290 kInstrCanThrow;
Bill Buzbee1465db52009-09-23 17:17:35 -07001291
Bill Buzbee45273872010-03-11 11:12:15 -08001292 //If already optimized out, just ignore
1293 if (mir->dalvikInsn.opCode == OP_NOP)
1294 return;
1295
Bill Buzbee1465db52009-09-23 17:17:35 -07001296 //Ugly, but necessary. Flush all Dalvik regs so Interp can find them
Bill Buzbeec6f10662010-02-09 11:16:15 -08001297 dvmCompilerFlushAllRegs(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07001298
Ben Chengba4fc8b2009-06-01 13:00:29 -07001299 if ((mir->next == NULL) || (flags & flagsToCheck)) {
1300 genPuntToInterp(cUnit, mir->offset);
1301 return;
1302 }
1303 int entryAddr = offsetof(InterpState,
1304 jitToInterpEntries.dvmJitToInterpSingleStep);
Bill Buzbee270c1d62009-08-13 16:58:07 -07001305 loadWordDisp(cUnit, rGLUE, entryAddr, r2);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001306 /* r0 = dalvik pc */
1307 loadConstant(cUnit, r0, (int) (cUnit->method->insns + mir->offset));
1308 /* r1 = dalvik pc of following instruction */
1309 loadConstant(cUnit, r1, (int) (cUnit->method->insns + mir->next->offset));
Bill Buzbee1465db52009-09-23 17:17:35 -07001310 opReg(cUnit, kOpBlx, r2);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001311}
1312
Bill Buzbeec1d9ed42010-02-02 11:04:33 -08001313/*
1314 * To prevent a thread in a monitor wait from blocking the Jit from
1315 * resetting the code cache, heavyweight monitor lock will not
1316 * be allowed to return to an existing translation. Instead, we will
1317 * handle them by branching to a handler, which will in turn call the
1318 * runtime lock routine and then branch directly back to the
1319 * interpreter main loop. Given the high cost of the heavyweight
1320 * lock operation, this additional cost should be slight (especially when
1321 * considering that we expect the vast majority of lock operations to
1322 * use the fast-path thin lock bypass).
1323 */
Ben Cheng5d90c202009-11-22 23:31:11 -08001324static void genMonitorPortable(CompilationUnit *cUnit, MIR *mir)
Bill Buzbee270c1d62009-08-13 16:58:07 -07001325{
Bill Buzbeeefbd3c52009-11-04 22:18:40 -08001326 bool isEnter = (mir->dalvikInsn.opCode == OP_MONITOR_ENTER);
Bill Buzbee1465db52009-09-23 17:17:35 -07001327 genExportPC(cUnit, mir);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001328 dvmCompilerFlushAllRegs(cUnit); /* Send everything to home location */
1329 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001330 loadValueDirectFixed(cUnit, rlSrc, r1);
1331 loadWordDisp(cUnit, rGLUE, offsetof(InterpState, self), r0);
Bill Buzbeec1d9ed42010-02-02 11:04:33 -08001332 genNullCheck(cUnit, rlSrc.sRegLow, r1, mir->offset, NULL);
Bill Buzbeeefbd3c52009-11-04 22:18:40 -08001333 if (isEnter) {
Bill Buzbeec1d9ed42010-02-02 11:04:33 -08001334 /* Get dPC of next insn */
1335 loadConstant(cUnit, r4PC, (int)(cUnit->method->insns + mir->offset +
1336 dexGetInstrWidthAbs(gDvm.instrWidth, OP_MONITOR_ENTER)));
1337#if defined(WITH_DEADLOCK_PREDICTION)
1338 genDispatchToHandler(cUnit, TEMPLATE_MONITOR_ENTER_DEBUG);
1339#else
1340 genDispatchToHandler(cUnit, TEMPLATE_MONITOR_ENTER);
1341#endif
Bill Buzbee1465db52009-09-23 17:17:35 -07001342 } else {
1343 loadConstant(cUnit, r2, (int)dvmUnlockObject);
Bill Buzbeec1d9ed42010-02-02 11:04:33 -08001344 /* Do the call */
1345 opReg(cUnit, kOpBlx, r2);
Bill Buzbee6bbdd6b2010-02-16 14:40:01 -08001346 opRegImm(cUnit, kOpCmp, r0, 0); /* Did we throw? */
1347 ArmLIR *branchOver = opCondBranch(cUnit, kArmCondNe);
1348 loadConstant(cUnit, r0,
1349 (int) (cUnit->method->insns + mir->offset +
1350 dexGetInstrWidthAbs(gDvm.instrWidth, OP_MONITOR_EXIT)));
1351 genDispatchToHandler(cUnit, TEMPLATE_THROW_EXCEPTION_COMMON);
1352 ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel);
1353 target->defMask = ENCODE_ALL;
1354 branchOver->generic.target = (LIR *) target;
Elliott Hughes6a555132010-02-25 15:41:42 -08001355 dvmCompilerClobberCallRegs(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07001356 }
Bill Buzbee270c1d62009-08-13 16:58:07 -07001357}
1358
Ben Chengba4fc8b2009-06-01 13:00:29 -07001359/*
1360 * The following are the first-level codegen routines that analyze the format
1361 * of each bytecode then either dispatch special purpose codegen routines
1362 * or produce corresponding Thumb instructions directly.
1363 */
1364
1365static bool handleFmt10t_Fmt20t_Fmt30t(CompilationUnit *cUnit, MIR *mir,
Bill Buzbee89efc3d2009-07-28 11:22:22 -07001366 BasicBlock *bb, ArmLIR *labelList)
Ben Chengba4fc8b2009-06-01 13:00:29 -07001367{
1368 /* For OP_GOTO, OP_GOTO_16, and OP_GOTO_32 */
1369 genUnconditionalBranch(cUnit, &labelList[bb->taken->id]);
1370 return false;
1371}
1372
1373static bool handleFmt10x(CompilationUnit *cUnit, MIR *mir)
1374{
1375 OpCode dalvikOpCode = mir->dalvikInsn.opCode;
1376 if (((dalvikOpCode >= OP_UNUSED_3E) && (dalvikOpCode <= OP_UNUSED_43)) ||
Andy McFadden96516932009-10-28 17:39:02 -07001377 ((dalvikOpCode >= OP_UNUSED_E3) && (dalvikOpCode <= OP_UNUSED_EB))) {
Ben Chengba4fc8b2009-06-01 13:00:29 -07001378 LOGE("Codegen: got unused opcode 0x%x\n",dalvikOpCode);
1379 return true;
1380 }
1381 switch (dalvikOpCode) {
1382 case OP_RETURN_VOID:
1383 genReturnCommon(cUnit,mir);
1384 break;
1385 case OP_UNUSED_73:
1386 case OP_UNUSED_79:
1387 case OP_UNUSED_7A:
1388 LOGE("Codegen: got unused opcode 0x%x\n",dalvikOpCode);
1389 return true;
1390 case OP_NOP:
1391 break;
1392 default:
1393 return true;
1394 }
1395 return false;
1396}
1397
1398static bool handleFmt11n_Fmt31i(CompilationUnit *cUnit, MIR *mir)
1399{
Bill Buzbee1465db52009-09-23 17:17:35 -07001400 RegLocation rlDest;
1401 RegLocation rlResult;
1402 if (mir->ssaRep->numDefs == 2) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001403 rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -07001404 } else {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001405 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001406 }
Ben Chenge9695e52009-06-16 16:11:47 -07001407
Ben Chengba4fc8b2009-06-01 13:00:29 -07001408 switch (mir->dalvikInsn.opCode) {
1409 case OP_CONST:
Ben Chenge9695e52009-06-16 16:11:47 -07001410 case OP_CONST_4: {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001411 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001412 loadConstantValue(cUnit, rlResult.lowReg, mir->dalvikInsn.vB);
1413 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001414 break;
Ben Chenge9695e52009-06-16 16:11:47 -07001415 }
1416 case OP_CONST_WIDE_32: {
Bill Buzbee1465db52009-09-23 17:17:35 -07001417 //TUNING: single routine to load constant pair for support doubles
Bill Buzbee964a7b02010-01-28 12:54:19 -08001418 //TUNING: load 0/-1 separately to avoid load dependency
Bill Buzbeec6f10662010-02-09 11:16:15 -08001419 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001420 loadConstantValue(cUnit, rlResult.lowReg, mir->dalvikInsn.vB);
1421 opRegRegImm(cUnit, kOpAsr, rlResult.highReg,
1422 rlResult.lowReg, 31);
1423 storeValueWide(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001424 break;
Ben Chenge9695e52009-06-16 16:11:47 -07001425 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07001426 default:
1427 return true;
1428 }
1429 return false;
1430}
1431
1432static bool handleFmt21h(CompilationUnit *cUnit, MIR *mir)
1433{
Bill Buzbee1465db52009-09-23 17:17:35 -07001434 RegLocation rlDest;
1435 RegLocation rlResult;
1436 if (mir->ssaRep->numDefs == 2) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001437 rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -07001438 } else {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001439 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001440 }
Bill Buzbeec6f10662010-02-09 11:16:15 -08001441 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
Ben Chenge9695e52009-06-16 16:11:47 -07001442
Ben Chengba4fc8b2009-06-01 13:00:29 -07001443 switch (mir->dalvikInsn.opCode) {
Ben Chenge9695e52009-06-16 16:11:47 -07001444 case OP_CONST_HIGH16: {
Bill Buzbee1465db52009-09-23 17:17:35 -07001445 loadConstantValue(cUnit, rlResult.lowReg, mir->dalvikInsn.vB << 16);
1446 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001447 break;
Ben Chenge9695e52009-06-16 16:11:47 -07001448 }
1449 case OP_CONST_WIDE_HIGH16: {
Bill Buzbee1465db52009-09-23 17:17:35 -07001450 loadConstantValueWide(cUnit, rlResult.lowReg, rlResult.highReg,
1451 0, mir->dalvikInsn.vB << 16);
1452 storeValueWide(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001453 break;
Ben Chenge9695e52009-06-16 16:11:47 -07001454 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07001455 default:
1456 return true;
1457 }
1458 return false;
1459}
1460
1461static bool handleFmt20bc(CompilationUnit *cUnit, MIR *mir)
1462{
1463 /* For OP_THROW_VERIFICATION_ERROR */
1464 genInterpSingleStep(cUnit, mir);
1465 return false;
1466}
1467
1468static bool handleFmt21c_Fmt31c(CompilationUnit *cUnit, MIR *mir)
1469{
Bill Buzbee1465db52009-09-23 17:17:35 -07001470 RegLocation rlResult;
1471 RegLocation rlDest;
1472 RegLocation rlSrc;
Ben Chenge9695e52009-06-16 16:11:47 -07001473
Ben Chengba4fc8b2009-06-01 13:00:29 -07001474 switch (mir->dalvikInsn.opCode) {
Ben Chengba4fc8b2009-06-01 13:00:29 -07001475 case OP_CONST_STRING_JUMBO:
1476 case OP_CONST_STRING: {
1477 void *strPtr = (void*)
1478 (cUnit->method->clazz->pDvmDex->pResStrings[mir->dalvikInsn.vB]);
1479 assert(strPtr != NULL);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001480 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
1481 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001482 loadConstantValue(cUnit, rlResult.lowReg, (int) strPtr );
1483 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001484 break;
1485 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07001486 case OP_CONST_CLASS: {
1487 void *classPtr = (void*)
1488 (cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vB]);
1489 assert(classPtr != NULL);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001490 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
1491 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001492 loadConstantValue(cUnit, rlResult.lowReg, (int) classPtr );
1493 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001494 break;
1495 }
1496 case OP_SGET_OBJECT:
1497 case OP_SGET_BOOLEAN:
1498 case OP_SGET_CHAR:
1499 case OP_SGET_BYTE:
1500 case OP_SGET_SHORT:
1501 case OP_SGET: {
Bill Buzbee50a6bf22009-07-08 13:08:04 -07001502 int valOffset = offsetof(StaticField, value);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001503 int tReg = dvmCompilerAllocTemp(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001504 void *fieldPtr = (void*)
1505 (cUnit->method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vB]);
1506 assert(fieldPtr != NULL);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001507 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
1508 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001509 loadConstant(cUnit, tReg, (int) fieldPtr + valOffset);
Ben Cheng11d8f142010-03-24 15:24:19 -07001510
1511 HEAP_ACCESS_SHADOW(true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001512 loadWordDisp(cUnit, tReg, 0, rlResult.lowReg);
Ben Cheng11d8f142010-03-24 15:24:19 -07001513 HEAP_ACCESS_SHADOW(false);
1514
Bill Buzbee1465db52009-09-23 17:17:35 -07001515 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001516 break;
1517 }
1518 case OP_SGET_WIDE: {
Bill Buzbee50a6bf22009-07-08 13:08:04 -07001519 int valOffset = offsetof(StaticField, value);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001520 void *fieldPtr = (void*)
1521 (cUnit->method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vB]);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001522 int tReg = dvmCompilerAllocTemp(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001523 assert(fieldPtr != NULL);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001524 rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
1525 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001526 loadConstant(cUnit, tReg, (int) fieldPtr + valOffset);
Ben Cheng11d8f142010-03-24 15:24:19 -07001527
1528 HEAP_ACCESS_SHADOW(true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001529 loadPair(cUnit, tReg, rlResult.lowReg, rlResult.highReg);
Ben Cheng11d8f142010-03-24 15:24:19 -07001530 HEAP_ACCESS_SHADOW(false);
1531
Bill Buzbee1465db52009-09-23 17:17:35 -07001532 storeValueWide(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001533 break;
1534 }
1535 case OP_SPUT_OBJECT:
1536 case OP_SPUT_BOOLEAN:
1537 case OP_SPUT_CHAR:
1538 case OP_SPUT_BYTE:
1539 case OP_SPUT_SHORT:
1540 case OP_SPUT: {
Bill Buzbee50a6bf22009-07-08 13:08:04 -07001541 int valOffset = offsetof(StaticField, value);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001542 int tReg = dvmCompilerAllocTemp(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001543 void *fieldPtr = (void*)
1544 (cUnit->method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vB]);
Ben Chenge9695e52009-06-16 16:11:47 -07001545
Ben Chengba4fc8b2009-06-01 13:00:29 -07001546 assert(fieldPtr != NULL);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001547 rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001548 rlSrc = loadValue(cUnit, rlSrc, kAnyReg);
1549 loadConstant(cUnit, tReg, (int) fieldPtr + valOffset);
Ben Cheng11d8f142010-03-24 15:24:19 -07001550
1551 HEAP_ACCESS_SHADOW(true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001552 storeWordDisp(cUnit, tReg, 0 ,rlSrc.lowReg);
Ben Cheng11d8f142010-03-24 15:24:19 -07001553 HEAP_ACCESS_SHADOW(false);
1554
Ben Chengba4fc8b2009-06-01 13:00:29 -07001555 break;
1556 }
1557 case OP_SPUT_WIDE: {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001558 int tReg = dvmCompilerAllocTemp(cUnit);
Bill Buzbee50a6bf22009-07-08 13:08:04 -07001559 int valOffset = offsetof(StaticField, value);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001560 void *fieldPtr = (void*)
1561 (cUnit->method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vB]);
Ben Chenge9695e52009-06-16 16:11:47 -07001562
Ben Chengba4fc8b2009-06-01 13:00:29 -07001563 assert(fieldPtr != NULL);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001564 rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -07001565 rlSrc = loadValueWide(cUnit, rlSrc, kAnyReg);
1566 loadConstant(cUnit, tReg, (int) fieldPtr + valOffset);
Ben Cheng11d8f142010-03-24 15:24:19 -07001567
1568 HEAP_ACCESS_SHADOW(true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001569 storePair(cUnit, tReg, rlSrc.lowReg, rlSrc.highReg);
Ben Cheng11d8f142010-03-24 15:24:19 -07001570 HEAP_ACCESS_SHADOW(false);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001571 break;
1572 }
1573 case OP_NEW_INSTANCE: {
Ben Chenge9695e52009-06-16 16:11:47 -07001574 /*
1575 * Obey the calling convention and don't mess with the register
1576 * usage.
1577 */
Ben Chengba4fc8b2009-06-01 13:00:29 -07001578 ClassObject *classPtr = (void*)
1579 (cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vB]);
1580 assert(classPtr != NULL);
1581 assert(classPtr->status & CLASS_INITIALIZED);
Ben Cheng79d173c2009-09-29 16:12:51 -07001582 /*
1583 * If it is going to throw, it should not make to the trace to begin
Bill Buzbee1465db52009-09-23 17:17:35 -07001584 * with. However, Alloc might throw, so we need to genExportPC()
Ben Cheng79d173c2009-09-29 16:12:51 -07001585 */
1586 assert((classPtr->accessFlags & (ACC_INTERFACE|ACC_ABSTRACT)) == 0);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001587 dvmCompilerFlushAllRegs(cUnit); /* Everything to home location */
Bill Buzbee1465db52009-09-23 17:17:35 -07001588 genExportPC(cUnit, mir);
1589 loadConstant(cUnit, r2, (int)dvmAllocObject);
Ben Chenge9695e52009-06-16 16:11:47 -07001590 loadConstant(cUnit, r0, (int) classPtr);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001591 loadConstant(cUnit, r1, ALLOC_DONT_TRACK);
Bill Buzbee1465db52009-09-23 17:17:35 -07001592 opReg(cUnit, kOpBlx, r2);
Elliott Hughes6a555132010-02-25 15:41:42 -08001593 dvmCompilerClobberCallRegs(cUnit);
Ben Cheng4f489172009-09-27 17:08:35 -07001594 /* generate a branch over if allocation is successful */
Bill Buzbee1465db52009-09-23 17:17:35 -07001595 opRegImm(cUnit, kOpCmp, r0, 0); /* NULL? */
1596 ArmLIR *branchOver = opCondBranch(cUnit, kArmCondNe);
Ben Cheng4f489172009-09-27 17:08:35 -07001597 /*
1598 * OOM exception needs to be thrown here and cannot re-execute
1599 */
1600 loadConstant(cUnit, r0,
1601 (int) (cUnit->method->insns + mir->offset));
1602 genDispatchToHandler(cUnit, TEMPLATE_THROW_EXCEPTION_COMMON);
1603 /* noreturn */
1604
Bill Buzbee1465db52009-09-23 17:17:35 -07001605 ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel);
Ben Cheng4f489172009-09-27 17:08:35 -07001606 target->defMask = ENCODE_ALL;
1607 branchOver->generic.target = (LIR *) target;
Bill Buzbeec6f10662010-02-09 11:16:15 -08001608 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
1609 rlResult = dvmCompilerGetReturn(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07001610 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001611 break;
1612 }
1613 case OP_CHECK_CAST: {
Ben Chenge9695e52009-06-16 16:11:47 -07001614 /*
1615 * Obey the calling convention and don't mess with the register
1616 * usage.
1617 */
Ben Chengba4fc8b2009-06-01 13:00:29 -07001618 ClassObject *classPtr =
1619 (cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vB]);
Bill Buzbee4df41a52009-11-12 17:07:16 -08001620 /*
1621 * Note: It is possible that classPtr is NULL at this point,
1622 * even though this instruction has been successfully interpreted.
1623 * If the previous interpretation had a null source, the
1624 * interpreter would not have bothered to resolve the clazz.
1625 * Bail out to the interpreter in this case, and log it
1626 * so that we can tell if it happens frequently.
1627 */
1628 if (classPtr == NULL) {
Ben Cheng11d8f142010-03-24 15:24:19 -07001629 LOGVV("null clazz in OP_CHECK_CAST, single-stepping");
Bill Buzbee4df41a52009-11-12 17:07:16 -08001630 genInterpSingleStep(cUnit, mir);
1631 return false;
1632 }
Bill Buzbeec6f10662010-02-09 11:16:15 -08001633 dvmCompilerFlushAllRegs(cUnit); /* Everything to home location */
Ben Chengba4fc8b2009-06-01 13:00:29 -07001634 loadConstant(cUnit, r1, (int) classPtr );
Bill Buzbeec6f10662010-02-09 11:16:15 -08001635 rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001636 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
1637 opRegImm(cUnit, kOpCmp, rlSrc.lowReg, 0); /* Null? */
1638 ArmLIR *branch1 = opCondBranch(cUnit, kArmCondEq);
1639 /*
1640 * rlSrc.lowReg now contains object->clazz. Note that
1641 * it could have been allocated r0, but we're okay so long
1642 * as we don't do anything desctructive until r0 is loaded
1643 * with clazz.
1644 */
Ben Chengba4fc8b2009-06-01 13:00:29 -07001645 /* r0 now contains object->clazz */
Bill Buzbee1465db52009-09-23 17:17:35 -07001646 loadWordDisp(cUnit, rlSrc.lowReg, offsetof(Object, clazz), r0);
1647 loadConstant(cUnit, r2, (int)dvmInstanceofNonTrivial);
1648 opRegReg(cUnit, kOpCmp, r0, r1);
1649 ArmLIR *branch2 = opCondBranch(cUnit, kArmCondEq);
1650 opReg(cUnit, kOpBlx, r2);
Elliott Hughes6a555132010-02-25 15:41:42 -08001651 dvmCompilerClobberCallRegs(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07001652 /*
1653 * If null, check cast failed - punt to the interpreter. Because
1654 * interpreter will be the one throwing, we don't need to
1655 * genExportPC() here.
1656 */
Bill Buzbee270c1d62009-08-13 16:58:07 -07001657 genZeroCheck(cUnit, r0, mir->offset, NULL);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001658 /* check cast passed - branch target here */
Bill Buzbee1465db52009-09-23 17:17:35 -07001659 ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel);
Ben Chengd7d426a2009-09-22 11:23:36 -07001660 target->defMask = ENCODE_ALL;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001661 branch1->generic.target = (LIR *)target;
1662 branch2->generic.target = (LIR *)target;
1663 break;
1664 }
1665 default:
1666 return true;
1667 }
1668 return false;
1669}
1670
1671static bool handleFmt11x(CompilationUnit *cUnit, MIR *mir)
1672{
1673 OpCode dalvikOpCode = mir->dalvikInsn.opCode;
Bill Buzbee1465db52009-09-23 17:17:35 -07001674 RegLocation rlResult;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001675 switch (dalvikOpCode) {
1676 case OP_MOVE_EXCEPTION: {
1677 int offset = offsetof(InterpState, self);
1678 int exOffset = offsetof(Thread, exception);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001679 int selfReg = dvmCompilerAllocTemp(cUnit);
1680 int resetReg = dvmCompilerAllocTemp(cUnit);
1681 RegLocation rlDest = dvmCompilerGetDest(cUnit, mir, 0);
1682 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001683 loadWordDisp(cUnit, rGLUE, offset, selfReg);
Bill Buzbeef9f33282009-11-22 12:45:30 -08001684 loadConstant(cUnit, resetReg, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001685 loadWordDisp(cUnit, selfReg, exOffset, rlResult.lowReg);
Bill Buzbeef9f33282009-11-22 12:45:30 -08001686 storeWordDisp(cUnit, selfReg, exOffset, resetReg);
Bill Buzbee1465db52009-09-23 17:17:35 -07001687 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001688 break;
1689 }
1690 case OP_MOVE_RESULT:
1691 case OP_MOVE_RESULT_OBJECT: {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001692 RegLocation rlDest = dvmCompilerGetDest(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001693 RegLocation rlSrc = LOC_DALVIK_RETURN_VAL;
1694 rlSrc.fp = rlDest.fp;
1695 storeValue(cUnit, rlDest, rlSrc);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001696 break;
1697 }
1698 case OP_MOVE_RESULT_WIDE: {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001699 RegLocation rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -07001700 RegLocation rlSrc = LOC_DALVIK_RETURN_VAL_WIDE;
1701 rlSrc.fp = rlDest.fp;
1702 storeValueWide(cUnit, rlDest, rlSrc);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001703 break;
1704 }
1705 case OP_RETURN_WIDE: {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001706 RegLocation rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -07001707 RegLocation rlDest = LOC_DALVIK_RETURN_VAL_WIDE;
1708 rlDest.fp = rlSrc.fp;
1709 storeValueWide(cUnit, rlDest, rlSrc);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001710 genReturnCommon(cUnit,mir);
1711 break;
1712 }
1713 case OP_RETURN:
1714 case OP_RETURN_OBJECT: {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001715 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001716 RegLocation rlDest = LOC_DALVIK_RETURN_VAL;
1717 rlDest.fp = rlSrc.fp;
1718 storeValue(cUnit, rlDest, rlSrc);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001719 genReturnCommon(cUnit,mir);
1720 break;
1721 }
Bill Buzbee1465db52009-09-23 17:17:35 -07001722 case OP_MONITOR_EXIT:
Ben Chengba4fc8b2009-06-01 13:00:29 -07001723 case OP_MONITOR_ENTER:
Bill Buzbeed0937ef2009-12-22 16:15:39 -08001724#if defined(WITH_DEADLOCK_PREDICTION) || defined(WITH_MONITOR_TRACKING)
Ben Cheng5d90c202009-11-22 23:31:11 -08001725 genMonitorPortable(cUnit, mir);
Bill Buzbee1465db52009-09-23 17:17:35 -07001726#else
Ben Cheng5d90c202009-11-22 23:31:11 -08001727 genMonitor(cUnit, mir);
Bill Buzbee1465db52009-09-23 17:17:35 -07001728#endif
Ben Chengba4fc8b2009-06-01 13:00:29 -07001729 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001730 case OP_THROW: {
1731 genInterpSingleStep(cUnit, mir);
1732 break;
1733 }
1734 default:
1735 return true;
1736 }
1737 return false;
1738}
1739
Bill Buzbeed45ba372009-06-15 17:00:57 -07001740static bool handleFmt12x(CompilationUnit *cUnit, MIR *mir)
1741{
1742 OpCode opCode = mir->dalvikInsn.opCode;
Bill Buzbee1465db52009-09-23 17:17:35 -07001743 RegLocation rlDest;
1744 RegLocation rlSrc;
1745 RegLocation rlResult;
Bill Buzbeed45ba372009-06-15 17:00:57 -07001746
Ben Chengba4fc8b2009-06-01 13:00:29 -07001747 if ( (opCode >= OP_ADD_INT_2ADDR) && (opCode <= OP_REM_DOUBLE_2ADDR)) {
Ben Cheng5d90c202009-11-22 23:31:11 -08001748 return genArithOp( cUnit, mir );
Ben Chengba4fc8b2009-06-01 13:00:29 -07001749 }
1750
Bill Buzbee1465db52009-09-23 17:17:35 -07001751 if (mir->ssaRep->numUses == 2)
Bill Buzbeec6f10662010-02-09 11:16:15 -08001752 rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -07001753 else
Bill Buzbeec6f10662010-02-09 11:16:15 -08001754 rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001755 if (mir->ssaRep->numDefs == 2)
Bill Buzbeec6f10662010-02-09 11:16:15 -08001756 rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -07001757 else
Bill Buzbeec6f10662010-02-09 11:16:15 -08001758 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
Ben Chenge9695e52009-06-16 16:11:47 -07001759
Ben Chengba4fc8b2009-06-01 13:00:29 -07001760 switch (opCode) {
Bill Buzbee1465db52009-09-23 17:17:35 -07001761 case OP_DOUBLE_TO_INT:
Ben Chengba4fc8b2009-06-01 13:00:29 -07001762 case OP_INT_TO_FLOAT:
Ben Chengba4fc8b2009-06-01 13:00:29 -07001763 case OP_FLOAT_TO_INT:
Ben Chengba4fc8b2009-06-01 13:00:29 -07001764 case OP_DOUBLE_TO_FLOAT:
Ben Chengba4fc8b2009-06-01 13:00:29 -07001765 case OP_FLOAT_TO_DOUBLE:
Ben Chengba4fc8b2009-06-01 13:00:29 -07001766 case OP_INT_TO_DOUBLE:
Ben Chengba4fc8b2009-06-01 13:00:29 -07001767 case OP_FLOAT_TO_LONG:
Ben Chengba4fc8b2009-06-01 13:00:29 -07001768 case OP_LONG_TO_FLOAT:
Ben Chengba4fc8b2009-06-01 13:00:29 -07001769 case OP_DOUBLE_TO_LONG:
Ben Chengba4fc8b2009-06-01 13:00:29 -07001770 case OP_LONG_TO_DOUBLE:
Ben Cheng5d90c202009-11-22 23:31:11 -08001771 return genConversion(cUnit, mir);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001772 case OP_NEG_INT:
1773 case OP_NOT_INT:
Ben Cheng5d90c202009-11-22 23:31:11 -08001774 return genArithOpInt(cUnit, mir, rlDest, rlSrc, rlSrc);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001775 case OP_NEG_LONG:
1776 case OP_NOT_LONG:
Ben Cheng5d90c202009-11-22 23:31:11 -08001777 return genArithOpLong(cUnit, mir, rlDest, rlSrc, rlSrc);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001778 case OP_NEG_FLOAT:
Ben Cheng5d90c202009-11-22 23:31:11 -08001779 return genArithOpFloat(cUnit, mir, rlDest, rlSrc, rlSrc);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001780 case OP_NEG_DOUBLE:
Ben Cheng5d90c202009-11-22 23:31:11 -08001781 return genArithOpDouble(cUnit, mir, rlDest, rlSrc, rlSrc);
Bill Buzbee1465db52009-09-23 17:17:35 -07001782 case OP_MOVE_WIDE:
1783 storeValueWide(cUnit, rlDest, rlSrc);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001784 break;
Bill Buzbee1465db52009-09-23 17:17:35 -07001785 case OP_INT_TO_LONG:
Bill Buzbeec6f10662010-02-09 11:16:15 -08001786 rlSrc = dvmCompilerUpdateLoc(cUnit, rlSrc);
1787 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee964a7b02010-01-28 12:54:19 -08001788 //TUNING: shouldn't loadValueDirect already check for phys reg?
Bill Buzbee1465db52009-09-23 17:17:35 -07001789 if (rlSrc.location == kLocPhysReg) {
1790 genRegCopy(cUnit, rlResult.lowReg, rlSrc.lowReg);
1791 } else {
1792 loadValueDirect(cUnit, rlSrc, rlResult.lowReg);
1793 }
1794 opRegRegImm(cUnit, kOpAsr, rlResult.highReg,
1795 rlResult.lowReg, 31);
1796 storeValueWide(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001797 break;
Bill Buzbee1465db52009-09-23 17:17:35 -07001798 case OP_LONG_TO_INT:
Bill Buzbeec6f10662010-02-09 11:16:15 -08001799 rlSrc = dvmCompilerUpdateLocWide(cUnit, rlSrc);
1800 rlSrc = dvmCompilerWideToNarrow(cUnit, rlSrc);
Bill Buzbee1465db52009-09-23 17:17:35 -07001801 // Intentional fallthrough
Ben Chengba4fc8b2009-06-01 13:00:29 -07001802 case OP_MOVE:
1803 case OP_MOVE_OBJECT:
Bill Buzbee1465db52009-09-23 17:17:35 -07001804 storeValue(cUnit, rlDest, rlSrc);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001805 break;
1806 case OP_INT_TO_BYTE:
Bill Buzbee1465db52009-09-23 17:17:35 -07001807 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001808 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001809 opRegReg(cUnit, kOp2Byte, rlResult.lowReg, rlSrc.lowReg);
1810 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001811 break;
1812 case OP_INT_TO_SHORT:
Bill Buzbee1465db52009-09-23 17:17:35 -07001813 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001814 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001815 opRegReg(cUnit, kOp2Short, rlResult.lowReg, rlSrc.lowReg);
1816 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001817 break;
1818 case OP_INT_TO_CHAR:
Bill Buzbee1465db52009-09-23 17:17:35 -07001819 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001820 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001821 opRegReg(cUnit, kOp2Char, rlResult.lowReg, rlSrc.lowReg);
1822 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001823 break;
1824 case OP_ARRAY_LENGTH: {
1825 int lenOffset = offsetof(ArrayObject, length);
Bill Buzbee1465db52009-09-23 17:17:35 -07001826 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
1827 genNullCheck(cUnit, rlSrc.sRegLow, rlSrc.lowReg,
1828 mir->offset, NULL);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001829 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001830 loadWordDisp(cUnit, rlSrc.lowReg, lenOffset,
1831 rlResult.lowReg);
1832 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001833 break;
1834 }
1835 default:
1836 return true;
1837 }
1838 return false;
1839}
1840
1841static bool handleFmt21s(CompilationUnit *cUnit, MIR *mir)
1842{
1843 OpCode dalvikOpCode = mir->dalvikInsn.opCode;
Bill Buzbee1465db52009-09-23 17:17:35 -07001844 RegLocation rlDest;
1845 RegLocation rlResult;
1846 int BBBB = mir->dalvikInsn.vB;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001847 if (dalvikOpCode == OP_CONST_WIDE_16) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001848 rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
1849 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001850 loadConstantValue(cUnit, rlResult.lowReg, BBBB);
Bill Buzbee964a7b02010-01-28 12:54:19 -08001851 //TUNING: do high separately to avoid load dependency
Bill Buzbee1465db52009-09-23 17:17:35 -07001852 opRegRegImm(cUnit, kOpAsr, rlResult.highReg, rlResult.lowReg, 31);
1853 storeValueWide(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001854 } else if (dalvikOpCode == OP_CONST_16) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001855 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
1856 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001857 loadConstantValue(cUnit, rlResult.lowReg, BBBB);
1858 storeValue(cUnit, rlDest, rlResult);
1859 } else
Ben Chengba4fc8b2009-06-01 13:00:29 -07001860 return true;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001861 return false;
1862}
1863
1864/* Compare agaist zero */
1865static bool handleFmt21t(CompilationUnit *cUnit, MIR *mir, BasicBlock *bb,
Bill Buzbee89efc3d2009-07-28 11:22:22 -07001866 ArmLIR *labelList)
Ben Chengba4fc8b2009-06-01 13:00:29 -07001867{
1868 OpCode dalvikOpCode = mir->dalvikInsn.opCode;
Bill Buzbee89efc3d2009-07-28 11:22:22 -07001869 ArmConditionCode cond;
Bill Buzbeec6f10662010-02-09 11:16:15 -08001870 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001871 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
1872 opRegImm(cUnit, kOpCmp, rlSrc.lowReg, 0);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001873
Bill Buzbee270c1d62009-08-13 16:58:07 -07001874//TUNING: break this out to allow use of Thumb2 CB[N]Z
Ben Chengba4fc8b2009-06-01 13:00:29 -07001875 switch (dalvikOpCode) {
1876 case OP_IF_EQZ:
Bill Buzbee1465db52009-09-23 17:17:35 -07001877 cond = kArmCondEq;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001878 break;
1879 case OP_IF_NEZ:
Bill Buzbee1465db52009-09-23 17:17:35 -07001880 cond = kArmCondNe;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001881 break;
1882 case OP_IF_LTZ:
Bill Buzbee1465db52009-09-23 17:17:35 -07001883 cond = kArmCondLt;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001884 break;
1885 case OP_IF_GEZ:
Bill Buzbee1465db52009-09-23 17:17:35 -07001886 cond = kArmCondGe;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001887 break;
1888 case OP_IF_GTZ:
Bill Buzbee1465db52009-09-23 17:17:35 -07001889 cond = kArmCondGt;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001890 break;
1891 case OP_IF_LEZ:
Bill Buzbee1465db52009-09-23 17:17:35 -07001892 cond = kArmCondLe;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001893 break;
1894 default:
1895 cond = 0;
1896 LOGE("Unexpected opcode (%d) for Fmt21t\n", dalvikOpCode);
Bill Buzbeefc519dc2010-03-06 23:30:57 -08001897 dvmCompilerAbort(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001898 }
1899 genConditionalBranch(cUnit, cond, &labelList[bb->taken->id]);
1900 /* This mostly likely will be optimized away in a later phase */
1901 genUnconditionalBranch(cUnit, &labelList[bb->fallThrough->id]);
1902 return false;
1903}
1904
Elliott Hughesb4c05972010-02-24 16:36:18 -08001905static bool isPowerOfTwo(int x)
1906{
1907 return (x & (x - 1)) == 0;
1908}
1909
1910// Returns true if no more than two bits are set in 'x'.
1911static bool isPopCountLE2(unsigned int x)
1912{
1913 x &= x - 1;
1914 return (x & (x - 1)) == 0;
1915}
1916
1917// Returns the index of the lowest set bit in 'x'.
1918static int lowestSetBit(unsigned int x) {
1919 int bit_posn = 0;
1920 while ((x & 0xf) == 0) {
1921 bit_posn += 4;
1922 x >>= 4;
Bill Buzbee78cb0e22010-02-11 14:04:53 -08001923 }
Elliott Hughesb4c05972010-02-24 16:36:18 -08001924 while ((x & 1) == 0) {
1925 bit_posn++;
1926 x >>= 1;
1927 }
1928 return bit_posn;
1929}
1930
1931// Returns true if it added instructions to 'cUnit' to multiply 'rlSrc' by 'lit'
1932// and store the result in 'rlDest'.
1933static bool handleEasyMultiply(CompilationUnit *cUnit,
1934 RegLocation rlSrc, RegLocation rlDest, int lit)
1935{
1936 // Can we simplify this multiplication?
1937 bool powerOfTwo = false;
1938 bool popCountLE2 = false;
1939 bool powerOfTwoMinusOne = false;
1940 if (lit < 2) {
1941 // Avoid special cases.
1942 return false;
1943 } else if (isPowerOfTwo(lit)) {
1944 powerOfTwo = true;
1945 } else if (isPopCountLE2(lit)) {
1946 popCountLE2 = true;
1947 } else if (isPowerOfTwo(lit + 1)) {
1948 powerOfTwoMinusOne = true;
1949 } else {
1950 return false;
1951 }
1952 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
1953 RegLocation rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
1954 if (powerOfTwo) {
1955 // Shift.
1956 opRegRegImm(cUnit, kOpLsl, rlResult.lowReg, rlSrc.lowReg,
1957 lowestSetBit(lit));
1958 } else if (popCountLE2) {
1959 // Shift and add and shift.
1960 int firstBit = lowestSetBit(lit);
1961 int secondBit = lowestSetBit(lit ^ (1 << firstBit));
1962 genMultiplyByTwoBitMultiplier(cUnit, rlSrc, rlResult, lit,
1963 firstBit, secondBit);
1964 } else {
1965 // Reverse subtract: (src << (shift + 1)) - src.
1966 assert(powerOfTwoMinusOne);
1967 // TODO: rsb dst, src, src lsl#lowestSetBit(lit + 1)
1968 int tReg = dvmCompilerAllocTemp(cUnit);
1969 opRegRegImm(cUnit, kOpLsl, tReg, rlSrc.lowReg, lowestSetBit(lit + 1));
1970 opRegRegReg(cUnit, kOpSub, rlResult.lowReg, tReg, rlSrc.lowReg);
1971 }
1972 storeValue(cUnit, rlDest, rlResult);
1973 return true;
Bill Buzbee78cb0e22010-02-11 14:04:53 -08001974}
1975
Ben Chengba4fc8b2009-06-01 13:00:29 -07001976static bool handleFmt22b_Fmt22s(CompilationUnit *cUnit, MIR *mir)
1977{
1978 OpCode dalvikOpCode = mir->dalvikInsn.opCode;
Bill Buzbeec6f10662010-02-09 11:16:15 -08001979 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
1980 RegLocation rlDest = dvmCompilerGetDest(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001981 RegLocation rlResult;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001982 int lit = mir->dalvikInsn.vC;
Ben Cheng4f489172009-09-27 17:08:35 -07001983 OpKind op = 0; /* Make gcc happy */
Bill Buzbee1465db52009-09-23 17:17:35 -07001984 int shiftOp = false;
1985 bool isDiv = false;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001986
Ben Chengba4fc8b2009-06-01 13:00:29 -07001987 int __aeabi_idivmod(int op1, int op2);
1988 int __aeabi_idiv(int op1, int op2);
1989
1990 switch (dalvikOpCode) {
Bill Buzbee1465db52009-09-23 17:17:35 -07001991 case OP_RSUB_INT_LIT8:
1992 case OP_RSUB_INT: {
1993 int tReg;
1994 //TUNING: add support for use of Arm rsub op
1995 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001996 tReg = dvmCompilerAllocTemp(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07001997 loadConstant(cUnit, tReg, lit);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001998 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001999 opRegRegReg(cUnit, kOpSub, rlResult.lowReg,
2000 tReg, rlSrc.lowReg);
2001 storeValue(cUnit, rlDest, rlResult);
2002 return false;
2003 break;
2004 }
2005
Ben Chengba4fc8b2009-06-01 13:00:29 -07002006 case OP_ADD_INT_LIT8:
2007 case OP_ADD_INT_LIT16:
Bill Buzbee1465db52009-09-23 17:17:35 -07002008 op = kOpAdd;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002009 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002010 case OP_MUL_INT_LIT8:
Bill Buzbee78cb0e22010-02-11 14:04:53 -08002011 case OP_MUL_INT_LIT16: {
Elliott Hughesb4c05972010-02-24 16:36:18 -08002012 if (handleEasyMultiply(cUnit, rlSrc, rlDest, lit)) {
2013 return false;
Bill Buzbee78cb0e22010-02-11 14:04:53 -08002014 }
Elliott Hughesb4c05972010-02-24 16:36:18 -08002015 op = kOpMul;
Bill Buzbee1465db52009-09-23 17:17:35 -07002016 break;
Bill Buzbee78cb0e22010-02-11 14:04:53 -08002017 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07002018 case OP_AND_INT_LIT8:
2019 case OP_AND_INT_LIT16:
Bill Buzbee1465db52009-09-23 17:17:35 -07002020 op = kOpAnd;
2021 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002022 case OP_OR_INT_LIT8:
2023 case OP_OR_INT_LIT16:
Bill Buzbee1465db52009-09-23 17:17:35 -07002024 op = kOpOr;
2025 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002026 case OP_XOR_INT_LIT8:
2027 case OP_XOR_INT_LIT16:
Bill Buzbee1465db52009-09-23 17:17:35 -07002028 op = kOpXor;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002029 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002030 case OP_SHL_INT_LIT8:
Bill Buzbee0e605272009-12-01 14:28:05 -08002031 lit &= 31;
Bill Buzbee1465db52009-09-23 17:17:35 -07002032 shiftOp = true;
2033 op = kOpLsl;
2034 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002035 case OP_SHR_INT_LIT8:
Bill Buzbee0e605272009-12-01 14:28:05 -08002036 lit &= 31;
Bill Buzbee1465db52009-09-23 17:17:35 -07002037 shiftOp = true;
2038 op = kOpAsr;
2039 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002040 case OP_USHR_INT_LIT8:
Bill Buzbee0e605272009-12-01 14:28:05 -08002041 lit &= 31;
Bill Buzbee1465db52009-09-23 17:17:35 -07002042 shiftOp = true;
2043 op = kOpLsr;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002044 break;
2045
2046 case OP_DIV_INT_LIT8:
2047 case OP_DIV_INT_LIT16:
Ben Chengba4fc8b2009-06-01 13:00:29 -07002048 case OP_REM_INT_LIT8:
2049 case OP_REM_INT_LIT16:
2050 if (lit == 0) {
2051 /* Let the interpreter deal with div by 0 */
2052 genInterpSingleStep(cUnit, mir);
2053 return false;
2054 }
Bill Buzbeec6f10662010-02-09 11:16:15 -08002055 dvmCompilerFlushAllRegs(cUnit); /* Everything to home location */
Bill Buzbee1465db52009-09-23 17:17:35 -07002056 loadValueDirectFixed(cUnit, rlSrc, r0);
Bill Buzbeec6f10662010-02-09 11:16:15 -08002057 dvmCompilerClobber(cUnit, r0);
Bill Buzbee1465db52009-09-23 17:17:35 -07002058 if ((dalvikOpCode == OP_DIV_INT_LIT8) ||
2059 (dalvikOpCode == OP_DIV_INT_LIT16)) {
2060 loadConstant(cUnit, r2, (int)__aeabi_idiv);
2061 isDiv = true;
2062 } else {
2063 loadConstant(cUnit, r2, (int)__aeabi_idivmod);
2064 isDiv = false;
2065 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07002066 loadConstant(cUnit, r1, lit);
Bill Buzbee1465db52009-09-23 17:17:35 -07002067 opReg(cUnit, kOpBlx, r2);
Elliott Hughes6a555132010-02-25 15:41:42 -08002068 dvmCompilerClobberCallRegs(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07002069 if (isDiv)
Bill Buzbeec6f10662010-02-09 11:16:15 -08002070 rlResult = dvmCompilerGetReturn(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07002071 else
Bill Buzbeec6f10662010-02-09 11:16:15 -08002072 rlResult = dvmCompilerGetReturnAlt(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07002073 storeValue(cUnit, rlDest, rlResult);
2074 return false;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002075 break;
2076 default:
2077 return true;
2078 }
Bill Buzbee1465db52009-09-23 17:17:35 -07002079 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -08002080 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07002081 // Avoid shifts by literal 0 - no support in Thumb. Change to copy
2082 if (shiftOp && (lit == 0)) {
2083 genRegCopy(cUnit, rlResult.lowReg, rlSrc.lowReg);
2084 } else {
2085 opRegRegImm(cUnit, op, rlResult.lowReg, rlSrc.lowReg, lit);
2086 }
2087 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002088 return false;
2089}
2090
2091static bool handleFmt22c(CompilationUnit *cUnit, MIR *mir)
2092{
2093 OpCode dalvikOpCode = mir->dalvikInsn.opCode;
2094 int fieldOffset;
2095
2096 if (dalvikOpCode >= OP_IGET && dalvikOpCode <= OP_IPUT_SHORT) {
2097 InstField *pInstField = (InstField *)
2098 cUnit->method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vC];
Ben Chengba4fc8b2009-06-01 13:00:29 -07002099
2100 assert(pInstField != NULL);
2101 fieldOffset = pInstField->byteOffset;
2102 } else {
Ben Chenga0e7b602009-10-13 23:09:01 -07002103 /* Deliberately break the code while make the compiler happy */
2104 fieldOffset = -1;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002105 }
2106 switch (dalvikOpCode) {
Ben Chengba4fc8b2009-06-01 13:00:29 -07002107 case OP_NEW_ARRAY: {
Bill Buzbee1465db52009-09-23 17:17:35 -07002108 // Generates a call - use explicit registers
Bill Buzbeec6f10662010-02-09 11:16:15 -08002109 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
2110 RegLocation rlDest = dvmCompilerGetDest(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07002111 RegLocation rlResult;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002112 void *classPtr = (void*)
2113 (cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vC]);
2114 assert(classPtr != NULL);
Bill Buzbeec6f10662010-02-09 11:16:15 -08002115 dvmCompilerFlushAllRegs(cUnit); /* Everything to home location */
Bill Buzbee1465db52009-09-23 17:17:35 -07002116 genExportPC(cUnit, mir);
2117 loadValueDirectFixed(cUnit, rlSrc, r1); /* Len */
Ben Chengba4fc8b2009-06-01 13:00:29 -07002118 loadConstant(cUnit, r0, (int) classPtr );
Bill Buzbee1465db52009-09-23 17:17:35 -07002119 loadConstant(cUnit, r3, (int)dvmAllocArrayByClass);
Ben Cheng4f489172009-09-27 17:08:35 -07002120 /*
2121 * "len < 0": bail to the interpreter to re-execute the
2122 * instruction
2123 */
Bill Buzbee89efc3d2009-07-28 11:22:22 -07002124 ArmLIR *pcrLabel =
Bill Buzbee1465db52009-09-23 17:17:35 -07002125 genRegImmCheck(cUnit, kArmCondMi, r1, 0, mir->offset, NULL);
Bill Buzbee270c1d62009-08-13 16:58:07 -07002126 loadConstant(cUnit, r2, ALLOC_DONT_TRACK);
Bill Buzbee1465db52009-09-23 17:17:35 -07002127 opReg(cUnit, kOpBlx, r3);
Elliott Hughes6a555132010-02-25 15:41:42 -08002128 dvmCompilerClobberCallRegs(cUnit);
Ben Cheng4f489172009-09-27 17:08:35 -07002129 /* generate a branch over if allocation is successful */
Bill Buzbee1465db52009-09-23 17:17:35 -07002130 opRegImm(cUnit, kOpCmp, r0, 0); /* NULL? */
2131 ArmLIR *branchOver = opCondBranch(cUnit, kArmCondNe);
Ben Cheng4f489172009-09-27 17:08:35 -07002132 /*
2133 * OOM exception needs to be thrown here and cannot re-execute
2134 */
2135 loadConstant(cUnit, r0,
2136 (int) (cUnit->method->insns + mir->offset));
2137 genDispatchToHandler(cUnit, TEMPLATE_THROW_EXCEPTION_COMMON);
2138 /* noreturn */
2139
Bill Buzbee1465db52009-09-23 17:17:35 -07002140 ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel);
Ben Cheng4f489172009-09-27 17:08:35 -07002141 target->defMask = ENCODE_ALL;
2142 branchOver->generic.target = (LIR *) target;
Bill Buzbeec6f10662010-02-09 11:16:15 -08002143 rlResult = dvmCompilerGetReturn(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07002144 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002145 break;
2146 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07002147 case OP_INSTANCE_OF: {
Bill Buzbee1465db52009-09-23 17:17:35 -07002148 // May generate a call - use explicit registers
Bill Buzbeec6f10662010-02-09 11:16:15 -08002149 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
2150 RegLocation rlDest = dvmCompilerGetDest(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07002151 RegLocation rlResult;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002152 ClassObject *classPtr =
2153 (cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vC]);
Bill Buzbee480e6782010-01-27 15:43:08 -08002154 /*
2155 * Note: It is possible that classPtr is NULL at this point,
2156 * even though this instruction has been successfully interpreted.
2157 * If the previous interpretation had a null source, the
2158 * interpreter would not have bothered to resolve the clazz.
2159 * Bail out to the interpreter in this case, and log it
2160 * so that we can tell if it happens frequently.
2161 */
2162 if (classPtr == NULL) {
2163 LOGD("null clazz in OP_INSTANCE_OF, single-stepping");
2164 genInterpSingleStep(cUnit, mir);
2165 break;
2166 }
Bill Buzbeec6f10662010-02-09 11:16:15 -08002167 dvmCompilerFlushAllRegs(cUnit); /* Everything to home location */
Bill Buzbee1465db52009-09-23 17:17:35 -07002168 loadValueDirectFixed(cUnit, rlSrc, r0); /* Ref */
Ben Chengba4fc8b2009-06-01 13:00:29 -07002169 loadConstant(cUnit, r2, (int) classPtr );
Bill Buzbee270c1d62009-08-13 16:58:07 -07002170//TUNING: compare to 0 primative to allow use of CB[N]Z
Bill Buzbee1465db52009-09-23 17:17:35 -07002171 opRegImm(cUnit, kOpCmp, r0, 0); /* NULL? */
Ben Cheng752c7942009-06-22 10:50:07 -07002172 /* When taken r0 has NULL which can be used for store directly */
Bill Buzbee1465db52009-09-23 17:17:35 -07002173 ArmLIR *branch1 = opCondBranch(cUnit, kArmCondEq);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002174 /* r1 now contains object->clazz */
Bill Buzbee270c1d62009-08-13 16:58:07 -07002175 loadWordDisp(cUnit, r0, offsetof(Object, clazz), r1);
Bill Buzbee1465db52009-09-23 17:17:35 -07002176 /* r1 now contains object->clazz */
2177 loadConstant(cUnit, r3, (int)dvmInstanceofNonTrivial);
Ben Cheng752c7942009-06-22 10:50:07 -07002178 loadConstant(cUnit, r0, 1); /* Assume true */
Bill Buzbee1465db52009-09-23 17:17:35 -07002179 opRegReg(cUnit, kOpCmp, r1, r2);
2180 ArmLIR *branch2 = opCondBranch(cUnit, kArmCondEq);
2181 genRegCopy(cUnit, r0, r1);
2182 genRegCopy(cUnit, r1, r2);
2183 opReg(cUnit, kOpBlx, r3);
Elliott Hughes6a555132010-02-25 15:41:42 -08002184 dvmCompilerClobberCallRegs(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002185 /* branch target here */
Bill Buzbee1465db52009-09-23 17:17:35 -07002186 ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel);
Ben Chengd7d426a2009-09-22 11:23:36 -07002187 target->defMask = ENCODE_ALL;
Bill Buzbeec6f10662010-02-09 11:16:15 -08002188 rlResult = dvmCompilerGetReturn(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07002189 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002190 branch1->generic.target = (LIR *)target;
2191 branch2->generic.target = (LIR *)target;
2192 break;
2193 }
2194 case OP_IGET_WIDE:
2195 genIGetWide(cUnit, mir, fieldOffset);
2196 break;
2197 case OP_IGET:
2198 case OP_IGET_OBJECT:
Bill Buzbee1465db52009-09-23 17:17:35 -07002199 genIGet(cUnit, mir, kWord, fieldOffset);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002200 break;
2201 case OP_IGET_BOOLEAN:
Bill Buzbee1465db52009-09-23 17:17:35 -07002202 genIGet(cUnit, mir, kUnsignedByte, fieldOffset);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002203 break;
2204 case OP_IGET_BYTE:
Bill Buzbee1465db52009-09-23 17:17:35 -07002205 genIGet(cUnit, mir, kSignedByte, fieldOffset);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002206 break;
2207 case OP_IGET_CHAR:
Bill Buzbee1465db52009-09-23 17:17:35 -07002208 genIGet(cUnit, mir, kUnsignedHalf, fieldOffset);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002209 break;
2210 case OP_IGET_SHORT:
Bill Buzbee1465db52009-09-23 17:17:35 -07002211 genIGet(cUnit, mir, kSignedHalf, fieldOffset);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002212 break;
2213 case OP_IPUT_WIDE:
2214 genIPutWide(cUnit, mir, fieldOffset);
2215 break;
2216 case OP_IPUT:
2217 case OP_IPUT_OBJECT:
Bill Buzbee1465db52009-09-23 17:17:35 -07002218 genIPut(cUnit, mir, kWord, fieldOffset);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002219 break;
2220 case OP_IPUT_SHORT:
2221 case OP_IPUT_CHAR:
Bill Buzbee1465db52009-09-23 17:17:35 -07002222 genIPut(cUnit, mir, kUnsignedHalf, fieldOffset);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002223 break;
2224 case OP_IPUT_BYTE:
2225 case OP_IPUT_BOOLEAN:
Bill Buzbee1465db52009-09-23 17:17:35 -07002226 genIPut(cUnit, mir, kUnsignedByte, fieldOffset);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002227 break;
2228 default:
2229 return true;
2230 }
2231 return false;
2232}
2233
2234static bool handleFmt22cs(CompilationUnit *cUnit, MIR *mir)
2235{
2236 OpCode dalvikOpCode = mir->dalvikInsn.opCode;
2237 int fieldOffset = mir->dalvikInsn.vC;
2238 switch (dalvikOpCode) {
2239 case OP_IGET_QUICK:
2240 case OP_IGET_OBJECT_QUICK:
Bill Buzbee1465db52009-09-23 17:17:35 -07002241 genIGet(cUnit, mir, kWord, fieldOffset);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002242 break;
2243 case OP_IPUT_QUICK:
2244 case OP_IPUT_OBJECT_QUICK:
Bill Buzbee1465db52009-09-23 17:17:35 -07002245 genIPut(cUnit, mir, kWord, fieldOffset);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002246 break;
2247 case OP_IGET_WIDE_QUICK:
2248 genIGetWide(cUnit, mir, fieldOffset);
2249 break;
2250 case OP_IPUT_WIDE_QUICK:
2251 genIPutWide(cUnit, mir, fieldOffset);
2252 break;
2253 default:
2254 return true;
2255 }
2256 return false;
2257
2258}
2259
2260/* Compare agaist zero */
2261static bool handleFmt22t(CompilationUnit *cUnit, MIR *mir, BasicBlock *bb,
Bill Buzbee89efc3d2009-07-28 11:22:22 -07002262 ArmLIR *labelList)
Ben Chengba4fc8b2009-06-01 13:00:29 -07002263{
2264 OpCode dalvikOpCode = mir->dalvikInsn.opCode;
Bill Buzbee89efc3d2009-07-28 11:22:22 -07002265 ArmConditionCode cond;
Bill Buzbeec6f10662010-02-09 11:16:15 -08002266 RegLocation rlSrc1 = dvmCompilerGetSrc(cUnit, mir, 0);
2267 RegLocation rlSrc2 = dvmCompilerGetSrc(cUnit, mir, 1);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002268
Bill Buzbee1465db52009-09-23 17:17:35 -07002269 rlSrc1 = loadValue(cUnit, rlSrc1, kCoreReg);
2270 rlSrc2 = loadValue(cUnit, rlSrc2, kCoreReg);
2271 opRegReg(cUnit, kOpCmp, rlSrc1.lowReg, rlSrc2.lowReg);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002272
2273 switch (dalvikOpCode) {
2274 case OP_IF_EQ:
Bill Buzbee1465db52009-09-23 17:17:35 -07002275 cond = kArmCondEq;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002276 break;
2277 case OP_IF_NE:
Bill Buzbee1465db52009-09-23 17:17:35 -07002278 cond = kArmCondNe;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002279 break;
2280 case OP_IF_LT:
Bill Buzbee1465db52009-09-23 17:17:35 -07002281 cond = kArmCondLt;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002282 break;
2283 case OP_IF_GE:
Bill Buzbee1465db52009-09-23 17:17:35 -07002284 cond = kArmCondGe;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002285 break;
2286 case OP_IF_GT:
Bill Buzbee1465db52009-09-23 17:17:35 -07002287 cond = kArmCondGt;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002288 break;
2289 case OP_IF_LE:
Bill Buzbee1465db52009-09-23 17:17:35 -07002290 cond = kArmCondLe;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002291 break;
2292 default:
2293 cond = 0;
2294 LOGE("Unexpected opcode (%d) for Fmt22t\n", dalvikOpCode);
Bill Buzbeefc519dc2010-03-06 23:30:57 -08002295 dvmCompilerAbort(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002296 }
2297 genConditionalBranch(cUnit, cond, &labelList[bb->taken->id]);
2298 /* This mostly likely will be optimized away in a later phase */
2299 genUnconditionalBranch(cUnit, &labelList[bb->fallThrough->id]);
2300 return false;
2301}
2302
2303static bool handleFmt22x_Fmt32x(CompilationUnit *cUnit, MIR *mir)
2304{
2305 OpCode opCode = mir->dalvikInsn.opCode;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002306
2307 switch (opCode) {
2308 case OP_MOVE_16:
2309 case OP_MOVE_OBJECT_16:
2310 case OP_MOVE_FROM16:
Ben Chenge9695e52009-06-16 16:11:47 -07002311 case OP_MOVE_OBJECT_FROM16: {
Bill Buzbeec6f10662010-02-09 11:16:15 -08002312 storeValue(cUnit, dvmCompilerGetDest(cUnit, mir, 0),
2313 dvmCompilerGetSrc(cUnit, mir, 0));
Ben Chengba4fc8b2009-06-01 13:00:29 -07002314 break;
Ben Chenge9695e52009-06-16 16:11:47 -07002315 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07002316 case OP_MOVE_WIDE_16:
Ben Chenge9695e52009-06-16 16:11:47 -07002317 case OP_MOVE_WIDE_FROM16: {
Bill Buzbeec6f10662010-02-09 11:16:15 -08002318 storeValueWide(cUnit, dvmCompilerGetDestWide(cUnit, mir, 0, 1),
2319 dvmCompilerGetSrcWide(cUnit, mir, 0, 1));
Ben Chengba4fc8b2009-06-01 13:00:29 -07002320 break;
Ben Chenge9695e52009-06-16 16:11:47 -07002321 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07002322 default:
2323 return true;
2324 }
2325 return false;
2326}
2327
2328static bool handleFmt23x(CompilationUnit *cUnit, MIR *mir)
2329{
2330 OpCode opCode = mir->dalvikInsn.opCode;
Bill Buzbee1465db52009-09-23 17:17:35 -07002331 RegLocation rlSrc1;
2332 RegLocation rlSrc2;
2333 RegLocation rlDest;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002334
2335 if ( (opCode >= OP_ADD_INT) && (opCode <= OP_REM_DOUBLE)) {
Ben Cheng5d90c202009-11-22 23:31:11 -08002336 return genArithOp( cUnit, mir );
Ben Chengba4fc8b2009-06-01 13:00:29 -07002337 }
2338
Bill Buzbee1465db52009-09-23 17:17:35 -07002339 /* APUTs have 3 sources and no targets */
2340 if (mir->ssaRep->numDefs == 0) {
2341 if (mir->ssaRep->numUses == 3) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08002342 rlDest = dvmCompilerGetSrc(cUnit, mir, 0);
2343 rlSrc1 = dvmCompilerGetSrc(cUnit, mir, 1);
2344 rlSrc2 = dvmCompilerGetSrc(cUnit, mir, 2);
Bill Buzbee1465db52009-09-23 17:17:35 -07002345 } else {
2346 assert(mir->ssaRep->numUses == 4);
Bill Buzbeec6f10662010-02-09 11:16:15 -08002347 rlDest = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
2348 rlSrc1 = dvmCompilerGetSrc(cUnit, mir, 2);
2349 rlSrc2 = dvmCompilerGetSrc(cUnit, mir, 3);
Bill Buzbee1465db52009-09-23 17:17:35 -07002350 }
2351 } else {
2352 /* Two sources and 1 dest. Deduce the operand sizes */
2353 if (mir->ssaRep->numUses == 4) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08002354 rlSrc1 = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
2355 rlSrc2 = dvmCompilerGetSrcWide(cUnit, mir, 2, 3);
Bill Buzbee1465db52009-09-23 17:17:35 -07002356 } else {
2357 assert(mir->ssaRep->numUses == 2);
Bill Buzbeec6f10662010-02-09 11:16:15 -08002358 rlSrc1 = dvmCompilerGetSrc(cUnit, mir, 0);
2359 rlSrc2 = dvmCompilerGetSrc(cUnit, mir, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -07002360 }
2361 if (mir->ssaRep->numDefs == 2) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08002362 rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -07002363 } else {
2364 assert(mir->ssaRep->numDefs == 1);
Bill Buzbeec6f10662010-02-09 11:16:15 -08002365 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07002366 }
2367 }
2368
2369
Ben Chengba4fc8b2009-06-01 13:00:29 -07002370 switch (opCode) {
Bill Buzbeed45ba372009-06-15 17:00:57 -07002371 case OP_CMPL_FLOAT:
2372 case OP_CMPG_FLOAT:
2373 case OP_CMPL_DOUBLE:
2374 case OP_CMPG_DOUBLE:
Ben Cheng5d90c202009-11-22 23:31:11 -08002375 return genCmpFP(cUnit, mir, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002376 case OP_CMP_LONG:
Bill Buzbee1465db52009-09-23 17:17:35 -07002377 genCmpLong(cUnit, mir, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002378 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002379 case OP_AGET_WIDE:
Bill Buzbee1465db52009-09-23 17:17:35 -07002380 genArrayGet(cUnit, mir, kLong, rlSrc1, rlSrc2, rlDest, 3);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002381 break;
2382 case OP_AGET:
2383 case OP_AGET_OBJECT:
Bill Buzbee1465db52009-09-23 17:17:35 -07002384 genArrayGet(cUnit, mir, kWord, rlSrc1, rlSrc2, rlDest, 2);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002385 break;
2386 case OP_AGET_BOOLEAN:
Bill Buzbee1465db52009-09-23 17:17:35 -07002387 genArrayGet(cUnit, mir, kUnsignedByte, rlSrc1, rlSrc2, rlDest, 0);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002388 break;
2389 case OP_AGET_BYTE:
Bill Buzbee1465db52009-09-23 17:17:35 -07002390 genArrayGet(cUnit, mir, kSignedByte, rlSrc1, rlSrc2, rlDest, 0);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002391 break;
2392 case OP_AGET_CHAR:
Bill Buzbee1465db52009-09-23 17:17:35 -07002393 genArrayGet(cUnit, mir, kUnsignedHalf, rlSrc1, rlSrc2, rlDest, 1);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002394 break;
2395 case OP_AGET_SHORT:
Bill Buzbee1465db52009-09-23 17:17:35 -07002396 genArrayGet(cUnit, mir, kSignedHalf, rlSrc1, rlSrc2, rlDest, 1);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002397 break;
2398 case OP_APUT_WIDE:
Bill Buzbee1465db52009-09-23 17:17:35 -07002399 genArrayPut(cUnit, mir, kLong, rlSrc1, rlSrc2, rlDest, 3);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002400 break;
2401 case OP_APUT:
Bill Buzbee1465db52009-09-23 17:17:35 -07002402 genArrayPut(cUnit, mir, kWord, rlSrc1, rlSrc2, rlDest, 2);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002403 break;
Bill Buzbeebe6534f2010-03-12 16:01:35 -08002404 case OP_APUT_OBJECT:
2405 genArrayObjectPut(cUnit, mir, rlSrc1, rlSrc2, rlDest, 2);
2406 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002407 case OP_APUT_SHORT:
2408 case OP_APUT_CHAR:
Bill Buzbee1465db52009-09-23 17:17:35 -07002409 genArrayPut(cUnit, mir, kUnsignedHalf, rlSrc1, rlSrc2, rlDest, 1);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002410 break;
2411 case OP_APUT_BYTE:
2412 case OP_APUT_BOOLEAN:
Bill Buzbee1465db52009-09-23 17:17:35 -07002413 genArrayPut(cUnit, mir, kUnsignedByte, rlSrc1, rlSrc2, rlDest, 0);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002414 break;
2415 default:
2416 return true;
2417 }
2418 return false;
2419}
2420
Ben Cheng6c10a972009-10-29 14:39:18 -07002421/*
2422 * Find the matching case.
2423 *
2424 * return values:
2425 * r0 (low 32-bit): pc of the chaining cell corresponding to the resolved case,
2426 * including default which is placed at MIN(size, MAX_CHAINED_SWITCH_CASES).
2427 * r1 (high 32-bit): the branch offset of the matching case (only for indexes
2428 * above MAX_CHAINED_SWITCH_CASES).
2429 *
2430 * Instructions around the call are:
2431 *
2432 * mov r2, pc
2433 * blx &findPackedSwitchIndex
2434 * mov pc, r0
2435 * .align4
2436 * chaining cell for case 0 [8 bytes]
2437 * chaining cell for case 1 [8 bytes]
2438 * :
2439 * chaining cell for case MIN(size, MAX_CHAINED_SWITCH_CASES)-1 [8 bytes]
2440 * chaining cell for case default [8 bytes]
2441 * noChain exit
2442 */
2443s8 findPackedSwitchIndex(const u2* switchData, int testVal, int pc)
2444{
2445 int size;
2446 int firstKey;
2447 const int *entries;
2448 int index;
2449 int jumpIndex;
2450 int caseDPCOffset = 0;
2451 /* In Thumb mode pc is 4 ahead of the "mov r2, pc" instruction */
2452 int chainingPC = (pc + 4) & ~3;
2453
2454 /*
2455 * Packed switch data format:
2456 * ushort ident = 0x0100 magic value
2457 * ushort size number of entries in the table
2458 * int first_key first (and lowest) switch case value
2459 * int targets[size] branch targets, relative to switch opcode
2460 *
2461 * Total size is (4+size*2) 16-bit code units.
2462 */
2463 size = switchData[1];
2464 assert(size > 0);
2465
2466 firstKey = switchData[2];
2467 firstKey |= switchData[3] << 16;
2468
2469
2470 /* The entries are guaranteed to be aligned on a 32-bit boundary;
2471 * we can treat them as a native int array.
2472 */
2473 entries = (const int*) &switchData[4];
2474 assert(((u4)entries & 0x3) == 0);
2475
2476 index = testVal - firstKey;
2477
2478 /* Jump to the default cell */
2479 if (index < 0 || index >= size) {
2480 jumpIndex = MIN(size, MAX_CHAINED_SWITCH_CASES);
2481 /* Jump to the non-chaining exit point */
2482 } else if (index >= MAX_CHAINED_SWITCH_CASES) {
2483 jumpIndex = MAX_CHAINED_SWITCH_CASES + 1;
2484 caseDPCOffset = entries[index];
2485 /* Jump to the inline chaining cell */
2486 } else {
2487 jumpIndex = index;
2488 }
2489
2490 chainingPC += jumpIndex * 8;
2491 return (((s8) caseDPCOffset) << 32) | (u8) chainingPC;
2492}
2493
2494/* See comments for findPackedSwitchIndex */
2495s8 findSparseSwitchIndex(const u2* switchData, int testVal, int pc)
2496{
2497 int size;
2498 const int *keys;
2499 const int *entries;
2500 int chainingPC = (pc + 4) & ~3;
2501 int i;
2502
2503 /*
2504 * Sparse switch data format:
2505 * ushort ident = 0x0200 magic value
2506 * ushort size number of entries in the table; > 0
2507 * int keys[size] keys, sorted low-to-high; 32-bit aligned
2508 * int targets[size] branch targets, relative to switch opcode
2509 *
2510 * Total size is (2+size*4) 16-bit code units.
2511 */
2512
2513 size = switchData[1];
2514 assert(size > 0);
2515
2516 /* The keys are guaranteed to be aligned on a 32-bit boundary;
2517 * we can treat them as a native int array.
2518 */
2519 keys = (const int*) &switchData[2];
2520 assert(((u4)keys & 0x3) == 0);
2521
2522 /* The entries are guaranteed to be aligned on a 32-bit boundary;
2523 * we can treat them as a native int array.
2524 */
2525 entries = keys + size;
2526 assert(((u4)entries & 0x3) == 0);
2527
2528 /*
2529 * Run through the list of keys, which are guaranteed to
2530 * be sorted low-to-high.
2531 *
2532 * Most tables have 3-4 entries. Few have more than 10. A binary
2533 * search here is probably not useful.
2534 */
2535 for (i = 0; i < size; i++) {
2536 int k = keys[i];
2537 if (k == testVal) {
2538 /* MAX_CHAINED_SWITCH_CASES + 1 is the start of the overflow case */
2539 int jumpIndex = (i < MAX_CHAINED_SWITCH_CASES) ?
2540 i : MAX_CHAINED_SWITCH_CASES + 1;
2541 chainingPC += jumpIndex * 8;
2542 return (((s8) entries[i]) << 32) | (u8) chainingPC;
2543 } else if (k > testVal) {
2544 break;
2545 }
2546 }
2547 return chainingPC + MIN(size, MAX_CHAINED_SWITCH_CASES) * 8;
2548}
2549
Ben Chengba4fc8b2009-06-01 13:00:29 -07002550static bool handleFmt31t(CompilationUnit *cUnit, MIR *mir)
2551{
2552 OpCode dalvikOpCode = mir->dalvikInsn.opCode;
2553 switch (dalvikOpCode) {
2554 case OP_FILL_ARRAY_DATA: {
Bill Buzbeec6f10662010-02-09 11:16:15 -08002555 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07002556 // Making a call - use explicit registers
Bill Buzbeec6f10662010-02-09 11:16:15 -08002557 dvmCompilerFlushAllRegs(cUnit); /* Everything to home location */
Bill Buzbee1465db52009-09-23 17:17:35 -07002558 genExportPC(cUnit, mir);
2559 loadValueDirectFixed(cUnit, rlSrc, r0);
Bill Buzbeefd023aa2009-11-02 09:23:49 -08002560 loadConstant(cUnit, r2, (int)dvmInterpHandleFillArrayData);
Ben Cheng6c10a972009-10-29 14:39:18 -07002561 loadConstant(cUnit, r1,
2562 (int) (cUnit->method->insns + mir->offset + mir->dalvikInsn.vB));
Bill Buzbee1465db52009-09-23 17:17:35 -07002563 opReg(cUnit, kOpBlx, r2);
Elliott Hughes6a555132010-02-25 15:41:42 -08002564 dvmCompilerClobberCallRegs(cUnit);
Bill Buzbeefd023aa2009-11-02 09:23:49 -08002565 /* generate a branch over if successful */
2566 opRegImm(cUnit, kOpCmp, r0, 0); /* NULL? */
2567 ArmLIR *branchOver = opCondBranch(cUnit, kArmCondNe);
2568 loadConstant(cUnit, r0,
2569 (int) (cUnit->method->insns + mir->offset));
2570 genDispatchToHandler(cUnit, TEMPLATE_THROW_EXCEPTION_COMMON);
2571 ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel);
2572 target->defMask = ENCODE_ALL;
2573 branchOver->generic.target = (LIR *) target;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002574 break;
2575 }
2576 /*
Ben Cheng6c10a972009-10-29 14:39:18 -07002577 * Compute the goto target of up to
2578 * MIN(switchSize, MAX_CHAINED_SWITCH_CASES) + 1 chaining cells.
2579 * See the comment before findPackedSwitchIndex for the code layout.
Ben Chengba4fc8b2009-06-01 13:00:29 -07002580 */
2581 case OP_PACKED_SWITCH:
2582 case OP_SPARSE_SWITCH: {
Bill Buzbeec6f10662010-02-09 11:16:15 -08002583 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
2584 dvmCompilerFlushAllRegs(cUnit); /* Everything to home location */
Bill Buzbee1465db52009-09-23 17:17:35 -07002585 loadValueDirectFixed(cUnit, rlSrc, r1);
Bill Buzbeec6f10662010-02-09 11:16:15 -08002586 dvmCompilerLockAllTemps(cUnit);
Ben Cheng6c10a972009-10-29 14:39:18 -07002587 const u2 *switchData =
2588 cUnit->method->insns + mir->offset + mir->dalvikInsn.vB;
2589 u2 size = switchData[1];
2590
Ben Chengba4fc8b2009-06-01 13:00:29 -07002591 if (dalvikOpCode == OP_PACKED_SWITCH) {
Ben Cheng6c10a972009-10-29 14:39:18 -07002592 loadConstant(cUnit, r4PC, (int)findPackedSwitchIndex);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002593 } else {
Ben Cheng6c10a972009-10-29 14:39:18 -07002594 loadConstant(cUnit, r4PC, (int)findSparseSwitchIndex);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002595 }
Ben Cheng6c10a972009-10-29 14:39:18 -07002596 /* r0 <- Addr of the switch data */
2597 loadConstant(cUnit, r0,
2598 (int) (cUnit->method->insns + mir->offset + mir->dalvikInsn.vB));
2599 /* r2 <- pc of the instruction following the blx */
2600 opRegReg(cUnit, kOpMov, r2, rpc);
Bill Buzbee1465db52009-09-23 17:17:35 -07002601 opReg(cUnit, kOpBlx, r4PC);
Elliott Hughes6a555132010-02-25 15:41:42 -08002602 dvmCompilerClobberCallRegs(cUnit);
Ben Cheng6c10a972009-10-29 14:39:18 -07002603 /* pc <- computed goto target */
2604 opRegReg(cUnit, kOpMov, rpc, r0);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002605 break;
2606 }
2607 default:
2608 return true;
2609 }
2610 return false;
2611}
2612
2613static bool handleFmt35c_3rc(CompilationUnit *cUnit, MIR *mir, BasicBlock *bb,
Bill Buzbee89efc3d2009-07-28 11:22:22 -07002614 ArmLIR *labelList)
Ben Chengba4fc8b2009-06-01 13:00:29 -07002615{
Bill Buzbee9bc3df32009-07-30 10:52:29 -07002616 ArmLIR *retChainingCell = NULL;
Bill Buzbee89efc3d2009-07-28 11:22:22 -07002617 ArmLIR *pcrLabel = NULL;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002618
Bill Buzbeef4ce16f2009-07-28 13:28:25 -07002619 if (bb->fallThrough != NULL)
2620 retChainingCell = &labelList[bb->fallThrough->id];
2621
Ben Chengba4fc8b2009-06-01 13:00:29 -07002622 DecodedInstruction *dInsn = &mir->dalvikInsn;
2623 switch (mir->dalvikInsn.opCode) {
2624 /*
2625 * calleeMethod = this->clazz->vtable[
2626 * method->clazz->pDvmDex->pResMethods[BBBB]->methodIndex
2627 * ]
2628 */
2629 case OP_INVOKE_VIRTUAL:
2630 case OP_INVOKE_VIRTUAL_RANGE: {
Bill Buzbee89efc3d2009-07-28 11:22:22 -07002631 ArmLIR *predChainingCell = &labelList[bb->taken->id];
Ben Chengba4fc8b2009-06-01 13:00:29 -07002632 int methodIndex =
2633 cUnit->method->clazz->pDvmDex->pResMethods[dInsn->vB]->
2634 methodIndex;
2635
2636 if (mir->dalvikInsn.opCode == OP_INVOKE_VIRTUAL)
2637 genProcessArgsNoRange(cUnit, mir, dInsn, &pcrLabel);
2638 else
2639 genProcessArgsRange(cUnit, mir, dInsn, &pcrLabel);
2640
Ben Cheng38329f52009-07-07 14:19:20 -07002641 genInvokeVirtualCommon(cUnit, mir, methodIndex,
2642 retChainingCell,
2643 predChainingCell,
2644 pcrLabel);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002645 break;
2646 }
2647 /*
2648 * calleeMethod = method->clazz->super->vtable[method->clazz->pDvmDex
2649 * ->pResMethods[BBBB]->methodIndex]
2650 */
2651 /* TODO - not excersized in RunPerf.jar */
2652 case OP_INVOKE_SUPER:
2653 case OP_INVOKE_SUPER_RANGE: {
2654 int mIndex = cUnit->method->clazz->pDvmDex->
2655 pResMethods[dInsn->vB]->methodIndex;
2656 const Method *calleeMethod =
2657 cUnit->method->clazz->super->vtable[mIndex];
2658
2659 if (mir->dalvikInsn.opCode == OP_INVOKE_SUPER)
2660 genProcessArgsNoRange(cUnit, mir, dInsn, &pcrLabel);
2661 else
2662 genProcessArgsRange(cUnit, mir, dInsn, &pcrLabel);
2663
2664 /* r0 = calleeMethod */
2665 loadConstant(cUnit, r0, (int) calleeMethod);
2666
Ben Cheng38329f52009-07-07 14:19:20 -07002667 genInvokeSingletonCommon(cUnit, mir, bb, labelList, pcrLabel,
2668 calleeMethod);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002669 break;
2670 }
2671 /* calleeMethod = method->clazz->pDvmDex->pResMethods[BBBB] */
2672 case OP_INVOKE_DIRECT:
2673 case OP_INVOKE_DIRECT_RANGE: {
2674 const Method *calleeMethod =
2675 cUnit->method->clazz->pDvmDex->pResMethods[dInsn->vB];
2676
2677 if (mir->dalvikInsn.opCode == OP_INVOKE_DIRECT)
2678 genProcessArgsNoRange(cUnit, mir, dInsn, &pcrLabel);
2679 else
2680 genProcessArgsRange(cUnit, mir, dInsn, &pcrLabel);
2681
2682 /* r0 = calleeMethod */
2683 loadConstant(cUnit, r0, (int) calleeMethod);
2684
Ben Cheng38329f52009-07-07 14:19:20 -07002685 genInvokeSingletonCommon(cUnit, mir, bb, labelList, pcrLabel,
2686 calleeMethod);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002687 break;
2688 }
2689 /* calleeMethod = method->clazz->pDvmDex->pResMethods[BBBB] */
2690 case OP_INVOKE_STATIC:
2691 case OP_INVOKE_STATIC_RANGE: {
2692 const Method *calleeMethod =
2693 cUnit->method->clazz->pDvmDex->pResMethods[dInsn->vB];
2694
2695 if (mir->dalvikInsn.opCode == OP_INVOKE_STATIC)
2696 genProcessArgsNoRange(cUnit, mir, dInsn,
2697 NULL /* no null check */);
2698 else
2699 genProcessArgsRange(cUnit, mir, dInsn,
2700 NULL /* no null check */);
2701
2702 /* r0 = calleeMethod */
2703 loadConstant(cUnit, r0, (int) calleeMethod);
2704
Ben Cheng38329f52009-07-07 14:19:20 -07002705 genInvokeSingletonCommon(cUnit, mir, bb, labelList, pcrLabel,
2706 calleeMethod);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002707 break;
2708 }
Bill Buzbee1465db52009-09-23 17:17:35 -07002709 /*
Ben Chengba4fc8b2009-06-01 13:00:29 -07002710 * calleeMethod = dvmFindInterfaceMethodInCache(this->clazz,
2711 * BBBB, method, method->clazz->pDvmDex)
Ben Cheng38329f52009-07-07 14:19:20 -07002712 *
2713 * Given "invoke-interface {v0}", the following is the generated code:
2714 *
2715 * 0x426a9abe : ldr r0, [r5, #0] --+
2716 * 0x426a9ac0 : mov r7, r5 |
2717 * 0x426a9ac2 : sub r7, #24 |
2718 * 0x426a9ac4 : cmp r0, #0 | genProcessArgsNoRange
2719 * 0x426a9ac6 : beq 0x426a9afe |
2720 * 0x426a9ac8 : stmia r7, <r0> --+
2721 * 0x426a9aca : ldr r4, [pc, #104] --> r4 <- dalvikPC of this invoke
2722 * 0x426a9acc : add r1, pc, #52 --> r1 <- &retChainingCell
2723 * 0x426a9ace : add r2, pc, #60 --> r2 <- &predictedChainingCell
2724 * 0x426a9ad0 : blx_1 0x426a918c --+ TEMPLATE_INVOKE_METHOD_
2725 * 0x426a9ad2 : blx_2 see above --+ PREDICTED_CHAIN
2726 * 0x426a9ad4 : b 0x426a9b0c --> off to the predicted chain
2727 * 0x426a9ad6 : b 0x426a9afe --> punt to the interpreter
Ben Chenga8e64a72009-10-20 13:01:36 -07002728 * 0x426a9ad8 : mov r8, r1 --+
2729 * 0x426a9ada : mov r9, r2 |
2730 * 0x426a9adc : mov r10, r3 |
Ben Cheng38329f52009-07-07 14:19:20 -07002731 * 0x426a9ade : mov r0, r3 |
2732 * 0x426a9ae0 : mov r1, #74 | dvmFindInterfaceMethodInCache
2733 * 0x426a9ae2 : ldr r2, [pc, #76] |
2734 * 0x426a9ae4 : ldr r3, [pc, #68] |
2735 * 0x426a9ae6 : ldr r7, [pc, #64] |
2736 * 0x426a9ae8 : blx r7 --+
Ben Chenga8e64a72009-10-20 13:01:36 -07002737 * 0x426a9aea : mov r1, r8 --> r1 <- rechain count
Ben Cheng38329f52009-07-07 14:19:20 -07002738 * 0x426a9aec : cmp r1, #0 --> compare against 0
2739 * 0x426a9aee : bgt 0x426a9af8 --> >=0? don't rechain
2740 * 0x426a9af0 : ldr r7, [r6, #96] --+
Ben Chenga8e64a72009-10-20 13:01:36 -07002741 * 0x426a9af2 : mov r2, r9 | dvmJitToPatchPredictedChain
2742 * 0x426a9af4 : mov r3, r10 |
Ben Cheng38329f52009-07-07 14:19:20 -07002743 * 0x426a9af6 : blx r7 --+
2744 * 0x426a9af8 : add r1, pc, #8 --> r1 <- &retChainingCell
2745 * 0x426a9afa : blx_1 0x426a9098 --+ TEMPLATE_INVOKE_METHOD_NO_OPT
2746 * 0x426a9afc : blx_2 see above --+
2747 * -------- reconstruct dalvik PC : 0x428b786c @ +0x001e
2748 * 0x426a9afe (0042): ldr r0, [pc, #52]
2749 * Exception_Handling:
2750 * 0x426a9b00 (0044): ldr r1, [r6, #84]
2751 * 0x426a9b02 (0046): blx r1
2752 * 0x426a9b04 (0048): .align4
2753 * -------- chaining cell (hot): 0x0021
2754 * 0x426a9b04 (0048): ldr r0, [r6, #92]
2755 * 0x426a9b06 (004a): blx r0
2756 * 0x426a9b08 (004c): data 0x7872(30834)
2757 * 0x426a9b0a (004e): data 0x428b(17035)
2758 * 0x426a9b0c (0050): .align4
2759 * -------- chaining cell (predicted)
2760 * 0x426a9b0c (0050): data 0x0000(0) --> will be patched into bx
2761 * 0x426a9b0e (0052): data 0x0000(0)
2762 * 0x426a9b10 (0054): data 0x0000(0) --> class
2763 * 0x426a9b12 (0056): data 0x0000(0)
2764 * 0x426a9b14 (0058): data 0x0000(0) --> method
2765 * 0x426a9b16 (005a): data 0x0000(0)
2766 * 0x426a9b18 (005c): data 0x0000(0) --> reset count
2767 * 0x426a9b1a (005e): data 0x0000(0)
2768 * 0x426a9b28 (006c): .word (0xad0392a5)
2769 * 0x426a9b2c (0070): .word (0x6e750)
2770 * 0x426a9b30 (0074): .word (0x4109a618)
2771 * 0x426a9b34 (0078): .word (0x428b786c)
Ben Chengba4fc8b2009-06-01 13:00:29 -07002772 */
2773 case OP_INVOKE_INTERFACE:
2774 case OP_INVOKE_INTERFACE_RANGE: {
Bill Buzbee89efc3d2009-07-28 11:22:22 -07002775 ArmLIR *predChainingCell = &labelList[bb->taken->id];
Ben Chengba4fc8b2009-06-01 13:00:29 -07002776 int methodIndex = dInsn->vB;
2777
Bill Buzbee1465db52009-09-23 17:17:35 -07002778 /* Ensure that nothing is both live and dirty */
Bill Buzbeec6f10662010-02-09 11:16:15 -08002779 dvmCompilerFlushAllRegs(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07002780
Ben Chengba4fc8b2009-06-01 13:00:29 -07002781 if (mir->dalvikInsn.opCode == OP_INVOKE_INTERFACE)
2782 genProcessArgsNoRange(cUnit, mir, dInsn, &pcrLabel);
2783 else
2784 genProcessArgsRange(cUnit, mir, dInsn, &pcrLabel);
2785
Ben Cheng38329f52009-07-07 14:19:20 -07002786 /* "this" is already left in r0 by genProcessArgs* */
2787
2788 /* r4PC = dalvikCallsite */
2789 loadConstant(cUnit, r4PC,
2790 (int) (cUnit->method->insns + mir->offset));
2791
2792 /* r1 = &retChainingCell */
Bill Buzbee270c1d62009-08-13 16:58:07 -07002793 ArmLIR *addrRetChain =
Bill Buzbee1465db52009-09-23 17:17:35 -07002794 opRegRegImm(cUnit, kOpAdd, r1, rpc, 0);
Ben Cheng38329f52009-07-07 14:19:20 -07002795 addrRetChain->generic.target = (LIR *) retChainingCell;
2796
2797 /* r2 = &predictedChainingCell */
Bill Buzbee89efc3d2009-07-28 11:22:22 -07002798 ArmLIR *predictedChainingCell =
Bill Buzbee1465db52009-09-23 17:17:35 -07002799 opRegRegImm(cUnit, kOpAdd, r2, rpc, 0);
Ben Cheng38329f52009-07-07 14:19:20 -07002800 predictedChainingCell->generic.target = (LIR *) predChainingCell;
2801
2802 genDispatchToHandler(cUnit, TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN);
2803
2804 /* return through lr - jump to the chaining cell */
2805 genUnconditionalBranch(cUnit, predChainingCell);
2806
2807 /*
2808 * null-check on "this" may have been eliminated, but we still need
2809 * a PC-reconstruction label for stack overflow bailout.
2810 */
2811 if (pcrLabel == NULL) {
2812 int dPC = (int) (cUnit->method->insns + mir->offset);
Bill Buzbee89efc3d2009-07-28 11:22:22 -07002813 pcrLabel = dvmCompilerNew(sizeof(ArmLIR), true);
Bill Buzbee1465db52009-09-23 17:17:35 -07002814 pcrLabel->opCode = ARM_PSEUDO_kPCReconstruction_CELL;
Ben Cheng38329f52009-07-07 14:19:20 -07002815 pcrLabel->operands[0] = dPC;
2816 pcrLabel->operands[1] = mir->offset;
2817 /* Insert the place holder to the growable list */
2818 dvmInsertGrowableList(&cUnit->pcReconstructionList, pcrLabel);
2819 }
2820
2821 /* return through lr+2 - punt to the interpreter */
2822 genUnconditionalBranch(cUnit, pcrLabel);
2823
2824 /*
2825 * return through lr+4 - fully resolve the callee method.
2826 * r1 <- count
2827 * r2 <- &predictedChainCell
2828 * r3 <- this->class
2829 * r4 <- dPC
2830 * r7 <- this->class->vtable
2831 */
2832
2833 /* Save count, &predictedChainCell, and class to high regs first */
Bill Buzbee1465db52009-09-23 17:17:35 -07002834 genRegCopy(cUnit, r8, r1);
2835 genRegCopy(cUnit, r9, r2);
2836 genRegCopy(cUnit, r10, r3);
Ben Cheng38329f52009-07-07 14:19:20 -07002837
Ben Chengba4fc8b2009-06-01 13:00:29 -07002838 /* r0 now contains this->clazz */
Bill Buzbee1465db52009-09-23 17:17:35 -07002839 genRegCopy(cUnit, r0, r3);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002840
2841 /* r1 = BBBB */
2842 loadConstant(cUnit, r1, dInsn->vB);
2843
2844 /* r2 = method (caller) */
2845 loadConstant(cUnit, r2, (int) cUnit->method);
2846
2847 /* r3 = pDvmDex */
2848 loadConstant(cUnit, r3, (int) cUnit->method->clazz->pDvmDex);
2849
2850 loadConstant(cUnit, r7,
2851 (intptr_t) dvmFindInterfaceMethodInCache);
Bill Buzbee1465db52009-09-23 17:17:35 -07002852 opReg(cUnit, kOpBlx, r7);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002853
2854 /* r0 = calleeMethod (returned from dvmFindInterfaceMethodInCache */
2855
Bill Buzbee1465db52009-09-23 17:17:35 -07002856 genRegCopy(cUnit, r1, r8);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002857
Ben Cheng38329f52009-07-07 14:19:20 -07002858 /* Check if rechain limit is reached */
Bill Buzbee1465db52009-09-23 17:17:35 -07002859 opRegImm(cUnit, kOpCmp, r1, 0);
Ben Cheng38329f52009-07-07 14:19:20 -07002860
Bill Buzbee1465db52009-09-23 17:17:35 -07002861 ArmLIR *bypassRechaining = opCondBranch(cUnit, kArmCondGt);
Ben Cheng38329f52009-07-07 14:19:20 -07002862
Bill Buzbee270c1d62009-08-13 16:58:07 -07002863 loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
2864 jitToInterpEntries.dvmJitToPatchPredictedChain), r7);
Ben Cheng38329f52009-07-07 14:19:20 -07002865
Bill Buzbee1465db52009-09-23 17:17:35 -07002866 genRegCopy(cUnit, r2, r9);
2867 genRegCopy(cUnit, r3, r10);
Ben Cheng38329f52009-07-07 14:19:20 -07002868
2869 /*
2870 * r0 = calleeMethod
2871 * r2 = &predictedChainingCell
2872 * r3 = class
2873 *
2874 * &returnChainingCell has been loaded into r1 but is not needed
2875 * when patching the chaining cell and will be clobbered upon
2876 * returning so it will be reconstructed again.
2877 */
Bill Buzbee1465db52009-09-23 17:17:35 -07002878 opReg(cUnit, kOpBlx, r7);
Ben Cheng38329f52009-07-07 14:19:20 -07002879
2880 /* r1 = &retChainingCell */
Bill Buzbee1465db52009-09-23 17:17:35 -07002881 addrRetChain = opRegRegImm(cUnit, kOpAdd, r1, rpc, 0);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002882 addrRetChain->generic.target = (LIR *) retChainingCell;
Ben Cheng38329f52009-07-07 14:19:20 -07002883
2884 bypassRechaining->generic.target = (LIR *) addrRetChain;
2885
Ben Chengba4fc8b2009-06-01 13:00:29 -07002886 /*
2887 * r0 = this, r1 = calleeMethod,
2888 * r1 = &ChainingCell,
2889 * r4PC = callsiteDPC,
2890 */
2891 genDispatchToHandler(cUnit, TEMPLATE_INVOKE_METHOD_NO_OPT);
Ben Cheng86717f72010-03-05 15:27:21 -08002892#if defined(JIT_STATS)
2893 gDvmJit.invokePolymorphic++;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002894#endif
2895 /* Handle exceptions using the interpreter */
2896 genTrap(cUnit, mir->offset, pcrLabel);
2897 break;
2898 }
2899 /* NOP */
2900 case OP_INVOKE_DIRECT_EMPTY: {
2901 return false;
2902 }
2903 case OP_FILLED_NEW_ARRAY:
2904 case OP_FILLED_NEW_ARRAY_RANGE: {
2905 /* Just let the interpreter deal with these */
2906 genInterpSingleStep(cUnit, mir);
2907 break;
2908 }
2909 default:
2910 return true;
2911 }
2912 return false;
2913}
2914
2915static bool handleFmt35ms_3rms(CompilationUnit *cUnit, MIR *mir,
Bill Buzbee89efc3d2009-07-28 11:22:22 -07002916 BasicBlock *bb, ArmLIR *labelList)
Ben Chengba4fc8b2009-06-01 13:00:29 -07002917{
Bill Buzbee89efc3d2009-07-28 11:22:22 -07002918 ArmLIR *retChainingCell = &labelList[bb->fallThrough->id];
2919 ArmLIR *predChainingCell = &labelList[bb->taken->id];
2920 ArmLIR *pcrLabel = NULL;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002921
2922 DecodedInstruction *dInsn = &mir->dalvikInsn;
2923 switch (mir->dalvikInsn.opCode) {
2924 /* calleeMethod = this->clazz->vtable[BBBB] */
2925 case OP_INVOKE_VIRTUAL_QUICK_RANGE:
2926 case OP_INVOKE_VIRTUAL_QUICK: {
2927 int methodIndex = dInsn->vB;
2928 if (mir->dalvikInsn.opCode == OP_INVOKE_VIRTUAL_QUICK)
2929 genProcessArgsNoRange(cUnit, mir, dInsn, &pcrLabel);
2930 else
2931 genProcessArgsRange(cUnit, mir, dInsn, &pcrLabel);
2932
Ben Cheng38329f52009-07-07 14:19:20 -07002933 genInvokeVirtualCommon(cUnit, mir, methodIndex,
2934 retChainingCell,
2935 predChainingCell,
2936 pcrLabel);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002937 break;
2938 }
2939 /* calleeMethod = method->clazz->super->vtable[BBBB] */
2940 case OP_INVOKE_SUPER_QUICK:
2941 case OP_INVOKE_SUPER_QUICK_RANGE: {
2942 const Method *calleeMethod =
2943 cUnit->method->clazz->super->vtable[dInsn->vB];
2944
2945 if (mir->dalvikInsn.opCode == OP_INVOKE_SUPER_QUICK)
2946 genProcessArgsNoRange(cUnit, mir, dInsn, &pcrLabel);
2947 else
2948 genProcessArgsRange(cUnit, mir, dInsn, &pcrLabel);
2949
2950 /* r0 = calleeMethod */
2951 loadConstant(cUnit, r0, (int) calleeMethod);
2952
Ben Cheng38329f52009-07-07 14:19:20 -07002953 genInvokeSingletonCommon(cUnit, mir, bb, labelList, pcrLabel,
2954 calleeMethod);
2955 /* Handle exceptions using the interpreter */
2956 genTrap(cUnit, mir->offset, pcrLabel);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002957 break;
2958 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07002959 default:
2960 return true;
2961 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07002962 return false;
2963}
2964
2965/*
Bill Buzbeefd023aa2009-11-02 09:23:49 -08002966 * This operation is complex enough that we'll do it partly inline
2967 * and partly with a handler. NOTE: the handler uses hardcoded
2968 * values for string object offsets and must be revisitied if the
2969 * layout changes.
2970 */
2971static bool genInlinedCompareTo(CompilationUnit *cUnit, MIR *mir)
2972{
2973#if defined(USE_GLOBAL_STRING_DEFS)
2974 return false;
2975#else
2976 ArmLIR *rollback;
Bill Buzbeec6f10662010-02-09 11:16:15 -08002977 RegLocation rlThis = dvmCompilerGetSrc(cUnit, mir, 0);
2978 RegLocation rlComp = dvmCompilerGetSrc(cUnit, mir, 1);
Bill Buzbeefd023aa2009-11-02 09:23:49 -08002979
2980 loadValueDirectFixed(cUnit, rlThis, r0);
2981 loadValueDirectFixed(cUnit, rlComp, r1);
2982 /* Test objects for NULL */
2983 rollback = genNullCheck(cUnit, rlThis.sRegLow, r0, mir->offset, NULL);
2984 genNullCheck(cUnit, rlComp.sRegLow, r1, mir->offset, rollback);
2985 /*
2986 * TUNING: we could check for object pointer equality before invoking
2987 * handler. Unclear whether the gain would be worth the added code size
2988 * expansion.
2989 */
2990 genDispatchToHandler(cUnit, TEMPLATE_STRING_COMPARETO);
Bill Buzbeec6f10662010-02-09 11:16:15 -08002991 storeValue(cUnit, inlinedTarget(cUnit, mir, false),
2992 dvmCompilerGetReturn(cUnit));
Bill Buzbeefd023aa2009-11-02 09:23:49 -08002993 return true;
2994#endif
2995}
2996
2997static bool genInlinedIndexOf(CompilationUnit *cUnit, MIR *mir, bool singleI)
2998{
2999#if defined(USE_GLOBAL_STRING_DEFS)
3000 return false;
3001#else
Bill Buzbeec6f10662010-02-09 11:16:15 -08003002 RegLocation rlThis = dvmCompilerGetSrc(cUnit, mir, 0);
3003 RegLocation rlChar = dvmCompilerGetSrc(cUnit, mir, 1);
Bill Buzbeefd023aa2009-11-02 09:23:49 -08003004
3005 loadValueDirectFixed(cUnit, rlThis, r0);
3006 loadValueDirectFixed(cUnit, rlChar, r1);
3007 if (!singleI) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08003008 RegLocation rlStart = dvmCompilerGetSrc(cUnit, mir, 2);
Bill Buzbeefd023aa2009-11-02 09:23:49 -08003009 loadValueDirectFixed(cUnit, rlStart, r2);
3010 } else {
3011 loadConstant(cUnit, r2, 0);
3012 }
3013 /* Test objects for NULL */
3014 genNullCheck(cUnit, rlThis.sRegLow, r0, mir->offset, NULL);
3015 genDispatchToHandler(cUnit, TEMPLATE_STRING_INDEXOF);
Bill Buzbeec6f10662010-02-09 11:16:15 -08003016 storeValue(cUnit, inlinedTarget(cUnit, mir, false),
3017 dvmCompilerGetReturn(cUnit));
Bill Buzbeefd023aa2009-11-02 09:23:49 -08003018 return true;
3019#endif
3020}
3021
Bill Buzbee1f748632010-03-02 16:14:41 -08003022static bool genInlinedStringLength(CompilationUnit *cUnit, MIR *mir)
3023{
3024 RegLocation rlObj = dvmCompilerGetSrc(cUnit, mir, 0);
3025 RegLocation rlDest = inlinedTarget(cUnit, mir, false);
3026 rlObj = loadValue(cUnit, rlObj, kCoreReg);
3027 RegLocation rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
3028 genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset, NULL);
3029 loadWordDisp(cUnit, rlObj.lowReg, gDvm.offJavaLangString_count,
3030 rlResult.lowReg);
3031 storeValue(cUnit, rlDest, rlResult);
3032 return false;
3033}
3034
3035static bool genInlinedStringCharAt(CompilationUnit *cUnit, MIR *mir)
3036{
3037 int contents = offsetof(ArrayObject, contents);
3038 RegLocation rlObj = dvmCompilerGetSrc(cUnit, mir, 0);
3039 RegLocation rlIdx = dvmCompilerGetSrc(cUnit, mir, 1);
3040 RegLocation rlDest = inlinedTarget(cUnit, mir, false);
3041 RegLocation rlResult;
3042 rlObj = loadValue(cUnit, rlObj, kCoreReg);
3043 rlIdx = loadValue(cUnit, rlIdx, kCoreReg);
3044 int regMax = dvmCompilerAllocTemp(cUnit);
3045 int regOff = dvmCompilerAllocTemp(cUnit);
3046 int regPtr = dvmCompilerAllocTemp(cUnit);
3047 ArmLIR *pcrLabel = genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg,
3048 mir->offset, NULL);
3049 loadWordDisp(cUnit, rlObj.lowReg, gDvm.offJavaLangString_count, regMax);
3050 loadWordDisp(cUnit, rlObj.lowReg, gDvm.offJavaLangString_offset, regOff);
3051 loadWordDisp(cUnit, rlObj.lowReg, gDvm.offJavaLangString_value, regPtr);
3052 genBoundsCheck(cUnit, rlIdx.lowReg, regMax, mir->offset, pcrLabel);
3053 dvmCompilerFreeTemp(cUnit, regMax);
3054 opRegImm(cUnit, kOpAdd, regPtr, contents);
3055 opRegReg(cUnit, kOpAdd, regOff, rlIdx.lowReg);
3056 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
3057 loadBaseIndexed(cUnit, regPtr, regOff, rlResult.lowReg, 1, kUnsignedHalf);
3058 storeValue(cUnit, rlDest, rlResult);
3059 return false;
3060}
3061
3062static bool genInlinedAbsInt(CompilationUnit *cUnit, MIR *mir)
3063{
3064 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
3065 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
3066 RegLocation rlDest = inlinedTarget(cUnit, mir, false);;
3067 RegLocation rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
3068 int signReg = dvmCompilerAllocTemp(cUnit);
3069 /*
3070 * abs(x) = y<=x>>31, (x+y)^y.
3071 * Thumb2's IT block also yields 3 instructions, but imposes
3072 * scheduling constraints.
3073 */
3074 opRegRegImm(cUnit, kOpAsr, signReg, rlSrc.lowReg, 31);
3075 opRegRegReg(cUnit, kOpAdd, rlResult.lowReg, rlSrc.lowReg, signReg);
3076 opRegReg(cUnit, kOpXor, rlResult.lowReg, signReg);
3077 storeValue(cUnit, rlDest, rlResult);
3078 return false;
3079}
3080
3081static bool genInlinedAbsLong(CompilationUnit *cUnit, MIR *mir)
3082{
3083 RegLocation rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
3084 RegLocation rlDest = inlinedTargetWide(cUnit, mir, false);
3085 rlSrc = loadValueWide(cUnit, rlSrc, kCoreReg);
3086 RegLocation rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
3087 int signReg = dvmCompilerAllocTemp(cUnit);
3088 /*
3089 * abs(x) = y<=x>>31, (x+y)^y.
3090 * Thumb2 IT block allows slightly shorter sequence,
3091 * but introduces a scheduling barrier. Stick with this
3092 * mechanism for now.
3093 */
3094 opRegRegImm(cUnit, kOpAsr, signReg, rlSrc.highReg, 31);
3095 opRegRegReg(cUnit, kOpAdd, rlResult.lowReg, rlSrc.lowReg, signReg);
3096 opRegRegReg(cUnit, kOpAdc, rlResult.highReg, rlSrc.highReg, signReg);
3097 opRegReg(cUnit, kOpXor, rlResult.lowReg, signReg);
3098 opRegReg(cUnit, kOpXor, rlResult.highReg, signReg);
3099 storeValueWide(cUnit, rlDest, rlResult);
3100 return false;
3101}
Bill Buzbeefd023aa2009-11-02 09:23:49 -08003102
3103/*
Bill Buzbeece46c942009-11-20 15:41:34 -08003104 * NOTE: Handles both range and non-range versions (arguments
3105 * have already been normalized by this point).
Ben Chengba4fc8b2009-06-01 13:00:29 -07003106 */
Bill Buzbeece46c942009-11-20 15:41:34 -08003107static bool handleExecuteInline(CompilationUnit *cUnit, MIR *mir)
Ben Chengba4fc8b2009-06-01 13:00:29 -07003108{
3109 DecodedInstruction *dInsn = &mir->dalvikInsn;
3110 switch( mir->dalvikInsn.opCode) {
Bill Buzbeece46c942009-11-20 15:41:34 -08003111 case OP_EXECUTE_INLINE_RANGE:
Ben Chengba4fc8b2009-06-01 13:00:29 -07003112 case OP_EXECUTE_INLINE: {
3113 unsigned int i;
3114 const InlineOperation* inLineTable = dvmGetInlineOpsTable();
Bill Buzbee50a6bf22009-07-08 13:08:04 -07003115 int offset = offsetof(InterpState, retval);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003116 int operation = dInsn->vB;
Bill Buzbee1465db52009-09-23 17:17:35 -07003117 int tReg1;
3118 int tReg2;
Bill Buzbee50a6bf22009-07-08 13:08:04 -07003119 switch (operation) {
3120 case INLINE_EMPTYINLINEMETHOD:
3121 return false; /* Nop */
3122 case INLINE_STRING_LENGTH:
3123 return genInlinedStringLength(cUnit, mir);
3124 case INLINE_MATH_ABS_INT:
3125 return genInlinedAbsInt(cUnit, mir);
3126 case INLINE_MATH_ABS_LONG:
3127 return genInlinedAbsLong(cUnit, mir);
3128 case INLINE_MATH_MIN_INT:
3129 return genInlinedMinMaxInt(cUnit, mir, true);
3130 case INLINE_MATH_MAX_INT:
3131 return genInlinedMinMaxInt(cUnit, mir, false);
3132 case INLINE_STRING_CHARAT:
3133 return genInlinedStringCharAt(cUnit, mir);
3134 case INLINE_MATH_SQRT:
3135 if (genInlineSqrt(cUnit, mir))
Bill Buzbee9727c3d2009-08-01 11:32:36 -07003136 return false;
Bill Buzbee50a6bf22009-07-08 13:08:04 -07003137 else
3138 break; /* Handle with C routine */
Bill Buzbee50a6bf22009-07-08 13:08:04 -07003139 case INLINE_MATH_ABS_FLOAT:
Bill Buzbee1465db52009-09-23 17:17:35 -07003140 if (genInlinedAbsFloat(cUnit, mir))
3141 return false;
3142 else
3143 break;
Bill Buzbee50a6bf22009-07-08 13:08:04 -07003144 case INLINE_MATH_ABS_DOUBLE:
Bill Buzbee1465db52009-09-23 17:17:35 -07003145 if (genInlinedAbsDouble(cUnit, mir))
3146 return false;
3147 else
3148 break;
Bill Buzbee50a6bf22009-07-08 13:08:04 -07003149 case INLINE_STRING_COMPARETO:
Bill Buzbeefd023aa2009-11-02 09:23:49 -08003150 if (genInlinedCompareTo(cUnit, mir))
3151 return false;
3152 else
3153 break;
Bill Buzbee12ba0152009-09-03 14:03:09 -07003154 case INLINE_STRING_INDEXOF_I:
Bill Buzbeefd023aa2009-11-02 09:23:49 -08003155 if (genInlinedIndexOf(cUnit, mir, true /* I */))
3156 return false;
3157 else
3158 break;
Bill Buzbee12ba0152009-09-03 14:03:09 -07003159 case INLINE_STRING_INDEXOF_II:
Bill Buzbeefd023aa2009-11-02 09:23:49 -08003160 if (genInlinedIndexOf(cUnit, mir, false /* I */))
3161 return false;
3162 else
3163 break;
3164 case INLINE_STRING_EQUALS:
3165 case INLINE_MATH_COS:
3166 case INLINE_MATH_SIN:
3167 break; /* Handle with C routine */
Bill Buzbee50a6bf22009-07-08 13:08:04 -07003168 default:
Bill Buzbeefc519dc2010-03-06 23:30:57 -08003169 dvmCompilerAbort(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003170 }
Bill Buzbeec6f10662010-02-09 11:16:15 -08003171 dvmCompilerFlushAllRegs(cUnit); /* Everything to home location */
Elliott Hughes6a555132010-02-25 15:41:42 -08003172 dvmCompilerClobberCallRegs(cUnit);
Bill Buzbeec6f10662010-02-09 11:16:15 -08003173 dvmCompilerClobber(cUnit, r4PC);
3174 dvmCompilerClobber(cUnit, r7);
Bill Buzbee1465db52009-09-23 17:17:35 -07003175 opRegRegImm(cUnit, kOpAdd, r4PC, rGLUE, offset);
3176 opImm(cUnit, kOpPush, (1<<r4PC) | (1<<r7));
Ben Chengba4fc8b2009-06-01 13:00:29 -07003177 loadConstant(cUnit, r4PC, (int)inLineTable[operation].func);
Bill Buzbee1465db52009-09-23 17:17:35 -07003178 genExportPC(cUnit, mir);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003179 for (i=0; i < dInsn->vA; i++) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08003180 loadValueDirect(cUnit, dvmCompilerGetSrc(cUnit, mir, i), i);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003181 }
Bill Buzbee1465db52009-09-23 17:17:35 -07003182 opReg(cUnit, kOpBlx, r4PC);
3183 opRegImm(cUnit, kOpAdd, r13, 8);
Bill Buzbeece46c942009-11-20 15:41:34 -08003184 opRegImm(cUnit, kOpCmp, r0, 0); /* NULL? */
3185 ArmLIR *branchOver = opCondBranch(cUnit, kArmCondNe);
3186 loadConstant(cUnit, r0,
3187 (int) (cUnit->method->insns + mir->offset));
3188 genDispatchToHandler(cUnit, TEMPLATE_THROW_EXCEPTION_COMMON);
3189 ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel);
3190 target->defMask = ENCODE_ALL;
3191 branchOver->generic.target = (LIR *) target;
Ben Chengba4fc8b2009-06-01 13:00:29 -07003192 break;
3193 }
3194 default:
3195 return true;
3196 }
3197 return false;
3198}
3199
3200static bool handleFmt51l(CompilationUnit *cUnit, MIR *mir)
3201{
Bill Buzbee1465db52009-09-23 17:17:35 -07003202 //TUNING: We're using core regs here - not optimal when target is a double
Bill Buzbeec6f10662010-02-09 11:16:15 -08003203 RegLocation rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
3204 RegLocation rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07003205 loadConstantValue(cUnit, rlResult.lowReg,
3206 mir->dalvikInsn.vB_wide & 0xFFFFFFFFUL);
3207 loadConstantValue(cUnit, rlResult.highReg,
3208 (mir->dalvikInsn.vB_wide>>32) & 0xFFFFFFFFUL);
3209 storeValueWide(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003210 return false;
3211}
3212
Ben Chengba4fc8b2009-06-01 13:00:29 -07003213/*
3214 * The following are special processing routines that handle transfer of
3215 * controls between compiled code and the interpreter. Certain VM states like
3216 * Dalvik PC and special-purpose registers are reconstructed here.
3217 */
3218
Ben Cheng1efc9c52009-06-08 18:25:27 -07003219/* Chaining cell for code that may need warmup. */
3220static void handleNormalChainingCell(CompilationUnit *cUnit,
3221 unsigned int offset)
Ben Chengba4fc8b2009-06-01 13:00:29 -07003222{
Ben Cheng11d8f142010-03-24 15:24:19 -07003223 /*
3224 * Use raw instruction constructors to guarantee that the generated
3225 * instructions fit the predefined cell size.
3226 */
3227 newLIR3(cUnit, kThumbLdrRRI5, r0, rGLUE,
3228 offsetof(InterpState,
3229 jitToInterpEntries.dvmJitToInterpNormal) >> 2);
3230 newLIR1(cUnit, kThumbBlxR, r0);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003231 addWordData(cUnit, (int) (cUnit->method->insns + offset), true);
3232}
3233
3234/*
Ben Cheng1efc9c52009-06-08 18:25:27 -07003235 * Chaining cell for instructions that immediately following already translated
3236 * code.
Ben Chengba4fc8b2009-06-01 13:00:29 -07003237 */
Ben Cheng1efc9c52009-06-08 18:25:27 -07003238static void handleHotChainingCell(CompilationUnit *cUnit,
3239 unsigned int offset)
Ben Chengba4fc8b2009-06-01 13:00:29 -07003240{
Ben Cheng11d8f142010-03-24 15:24:19 -07003241 /*
3242 * Use raw instruction constructors to guarantee that the generated
3243 * instructions fit the predefined cell size.
3244 */
3245 newLIR3(cUnit, kThumbLdrRRI5, r0, rGLUE,
3246 offsetof(InterpState,
3247 jitToInterpEntries.dvmJitToInterpTraceSelect) >> 2);
3248 newLIR1(cUnit, kThumbBlxR, r0);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003249 addWordData(cUnit, (int) (cUnit->method->insns + offset), true);
3250}
3251
Bill Buzbee9c4b7c82009-09-10 10:10:38 -07003252#if defined(WITH_SELF_VERIFICATION) || defined(WITH_JIT_TUNING)
Jeff Hao97319a82009-08-12 16:57:15 -07003253/* Chaining cell for branches that branch back into the same basic block */
3254static void handleBackwardBranchChainingCell(CompilationUnit *cUnit,
3255 unsigned int offset)
3256{
Ben Cheng11d8f142010-03-24 15:24:19 -07003257 /*
3258 * Use raw instruction constructors to guarantee that the generated
3259 * instructions fit the predefined cell size.
3260 */
Bill Buzbee9c4b7c82009-09-10 10:10:38 -07003261#if defined(WITH_SELF_VERIFICATION)
Bill Buzbee1465db52009-09-23 17:17:35 -07003262 newLIR3(cUnit, kThumbLdrRRI5, r0, rGLUE,
Ben Cheng40094c12010-02-24 20:58:44 -08003263 offsetof(InterpState,
3264 jitToInterpEntries.dvmJitToInterpBackwardBranch) >> 2);
Bill Buzbee9c4b7c82009-09-10 10:10:38 -07003265#else
Bill Buzbee1465db52009-09-23 17:17:35 -07003266 newLIR3(cUnit, kThumbLdrRRI5, r0, rGLUE,
Bill Buzbee9c4b7c82009-09-10 10:10:38 -07003267 offsetof(InterpState, jitToInterpEntries.dvmJitToInterpNormal) >> 2);
3268#endif
Bill Buzbee1465db52009-09-23 17:17:35 -07003269 newLIR1(cUnit, kThumbBlxR, r0);
Jeff Hao97319a82009-08-12 16:57:15 -07003270 addWordData(cUnit, (int) (cUnit->method->insns + offset), true);
3271}
3272
3273#endif
Ben Chengba4fc8b2009-06-01 13:00:29 -07003274/* Chaining cell for monomorphic method invocations. */
Ben Cheng38329f52009-07-07 14:19:20 -07003275static void handleInvokeSingletonChainingCell(CompilationUnit *cUnit,
3276 const Method *callee)
Ben Chengba4fc8b2009-06-01 13:00:29 -07003277{
Ben Cheng11d8f142010-03-24 15:24:19 -07003278 /*
3279 * Use raw instruction constructors to guarantee that the generated
3280 * instructions fit the predefined cell size.
3281 */
3282 newLIR3(cUnit, kThumbLdrRRI5, r0, rGLUE,
3283 offsetof(InterpState,
3284 jitToInterpEntries.dvmJitToInterpTraceSelect) >> 2);
3285 newLIR1(cUnit, kThumbBlxR, r0);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003286 addWordData(cUnit, (int) (callee->insns), true);
3287}
3288
Ben Cheng38329f52009-07-07 14:19:20 -07003289/* Chaining cell for monomorphic method invocations. */
3290static void handleInvokePredictedChainingCell(CompilationUnit *cUnit)
3291{
3292
3293 /* Should not be executed in the initial state */
3294 addWordData(cUnit, PREDICTED_CHAIN_BX_PAIR_INIT, true);
3295 /* To be filled: class */
3296 addWordData(cUnit, PREDICTED_CHAIN_CLAZZ_INIT, true);
3297 /* To be filled: method */
3298 addWordData(cUnit, PREDICTED_CHAIN_METHOD_INIT, true);
3299 /*
3300 * Rechain count. The initial value of 0 here will trigger chaining upon
3301 * the first invocation of this callsite.
3302 */
3303 addWordData(cUnit, PREDICTED_CHAIN_COUNTER_INIT, true);
3304}
3305
Ben Chengba4fc8b2009-06-01 13:00:29 -07003306/* Load the Dalvik PC into r0 and jump to the specified target */
3307static void handlePCReconstruction(CompilationUnit *cUnit,
Bill Buzbee89efc3d2009-07-28 11:22:22 -07003308 ArmLIR *targetLabel)
Ben Chengba4fc8b2009-06-01 13:00:29 -07003309{
Bill Buzbee89efc3d2009-07-28 11:22:22 -07003310 ArmLIR **pcrLabel =
3311 (ArmLIR **) cUnit->pcReconstructionList.elemList;
Ben Chengba4fc8b2009-06-01 13:00:29 -07003312 int numElems = cUnit->pcReconstructionList.numUsed;
3313 int i;
3314 for (i = 0; i < numElems; i++) {
3315 dvmCompilerAppendLIR(cUnit, (LIR *) pcrLabel[i]);
3316 /* r0 = dalvik PC */
3317 loadConstant(cUnit, r0, pcrLabel[i]->operands[0]);
3318 genUnconditionalBranch(cUnit, targetLabel);
3319 }
3320}
3321
Bill Buzbee1465db52009-09-23 17:17:35 -07003322static char *extendedMIROpNames[kMirOpLast - kMirOpFirst] = {
3323 "kMirOpPhi",
3324 "kMirOpNullNRangeUpCheck",
3325 "kMirOpNullNRangeDownCheck",
3326 "kMirOpLowerBound",
3327 "kMirOpPunt",
Ben Cheng4238ec22009-08-24 16:32:22 -07003328};
3329
3330/*
3331 * vA = arrayReg;
3332 * vB = idxReg;
3333 * vC = endConditionReg;
3334 * arg[0] = maxC
3335 * arg[1] = minC
3336 * arg[2] = loopBranchConditionCode
3337 */
3338static void genHoistedChecksForCountUpLoop(CompilationUnit *cUnit, MIR *mir)
3339{
Bill Buzbee1465db52009-09-23 17:17:35 -07003340 /*
3341 * NOTE: these synthesized blocks don't have ssa names assigned
3342 * for Dalvik registers. However, because they dominate the following
3343 * blocks we can simply use the Dalvik name w/ subscript 0 as the
3344 * ssa name.
3345 */
Ben Cheng4238ec22009-08-24 16:32:22 -07003346 DecodedInstruction *dInsn = &mir->dalvikInsn;
3347 const int lenOffset = offsetof(ArrayObject, length);
Ben Cheng4238ec22009-08-24 16:32:22 -07003348 const int maxC = dInsn->arg[0];
3349 const int minC = dInsn->arg[1];
Bill Buzbee1465db52009-09-23 17:17:35 -07003350 int regLength;
3351 RegLocation rlArray = cUnit->regLocation[mir->dalvikInsn.vA];
3352 RegLocation rlIdxEnd = cUnit->regLocation[mir->dalvikInsn.vC];
Ben Cheng4238ec22009-08-24 16:32:22 -07003353
3354 /* regArray <- arrayRef */
Bill Buzbee1465db52009-09-23 17:17:35 -07003355 rlArray = loadValue(cUnit, rlArray, kCoreReg);
3356 rlIdxEnd = loadValue(cUnit, rlIdxEnd, kCoreReg);
3357 genRegImmCheck(cUnit, kArmCondEq, rlArray.lowReg, 0, 0,
Ben Cheng4238ec22009-08-24 16:32:22 -07003358 (ArmLIR *) cUnit->loopAnalysis->branchToPCR);
3359
3360 /* regLength <- len(arrayRef) */
Bill Buzbeec6f10662010-02-09 11:16:15 -08003361 regLength = dvmCompilerAllocTemp(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07003362 loadWordDisp(cUnit, rlArray.lowReg, lenOffset, regLength);
Ben Cheng4238ec22009-08-24 16:32:22 -07003363
3364 int delta = maxC;
3365 /*
3366 * If the loop end condition is ">=" instead of ">", then the largest value
3367 * of the index is "endCondition - 1".
3368 */
3369 if (dInsn->arg[2] == OP_IF_GE) {
3370 delta--;
3371 }
3372
3373 if (delta) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08003374 int tReg = dvmCompilerAllocTemp(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07003375 opRegRegImm(cUnit, kOpAdd, tReg, rlIdxEnd.lowReg, delta);
3376 rlIdxEnd.lowReg = tReg;
Bill Buzbeec6f10662010-02-09 11:16:15 -08003377 dvmCompilerFreeTemp(cUnit, tReg);
Ben Cheng4238ec22009-08-24 16:32:22 -07003378 }
3379 /* Punt if "regIdxEnd < len(Array)" is false */
Bill Buzbee1465db52009-09-23 17:17:35 -07003380 genRegRegCheck(cUnit, kArmCondGe, rlIdxEnd.lowReg, regLength, 0,
Ben Cheng0fd31e42009-09-03 14:40:16 -07003381 (ArmLIR *) cUnit->loopAnalysis->branchToPCR);
Ben Cheng4238ec22009-08-24 16:32:22 -07003382}
3383
3384/*
3385 * vA = arrayReg;
3386 * vB = idxReg;
3387 * vC = endConditionReg;
3388 * arg[0] = maxC
3389 * arg[1] = minC
3390 * arg[2] = loopBranchConditionCode
3391 */
3392static void genHoistedChecksForCountDownLoop(CompilationUnit *cUnit, MIR *mir)
3393{
3394 DecodedInstruction *dInsn = &mir->dalvikInsn;
3395 const int lenOffset = offsetof(ArrayObject, length);
Bill Buzbeec6f10662010-02-09 11:16:15 -08003396 const int regLength = dvmCompilerAllocTemp(cUnit);
Ben Cheng4238ec22009-08-24 16:32:22 -07003397 const int maxC = dInsn->arg[0];
3398 const int minC = dInsn->arg[1];
Bill Buzbee1465db52009-09-23 17:17:35 -07003399 RegLocation rlArray = cUnit->regLocation[mir->dalvikInsn.vA];
3400 RegLocation rlIdxInit = cUnit->regLocation[mir->dalvikInsn.vB];
Ben Cheng4238ec22009-08-24 16:32:22 -07003401
3402 /* regArray <- arrayRef */
Bill Buzbee1465db52009-09-23 17:17:35 -07003403 rlArray = loadValue(cUnit, rlArray, kCoreReg);
3404 rlIdxInit = loadValue(cUnit, rlIdxInit, kCoreReg);
3405 genRegImmCheck(cUnit, kArmCondEq, rlArray.lowReg, 0, 0,
Ben Cheng4238ec22009-08-24 16:32:22 -07003406 (ArmLIR *) cUnit->loopAnalysis->branchToPCR);
3407
3408 /* regLength <- len(arrayRef) */
Bill Buzbee1465db52009-09-23 17:17:35 -07003409 loadWordDisp(cUnit, rlArray.lowReg, lenOffset, regLength);
Ben Cheng4238ec22009-08-24 16:32:22 -07003410
3411 if (maxC) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08003412 int tReg = dvmCompilerAllocTemp(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07003413 opRegRegImm(cUnit, kOpAdd, tReg, rlIdxInit.lowReg, maxC);
3414 rlIdxInit.lowReg = tReg;
Bill Buzbeec6f10662010-02-09 11:16:15 -08003415 dvmCompilerFreeTemp(cUnit, tReg);
Ben Cheng4238ec22009-08-24 16:32:22 -07003416 }
3417
3418 /* Punt if "regIdxInit < len(Array)" is false */
Bill Buzbee1465db52009-09-23 17:17:35 -07003419 genRegRegCheck(cUnit, kArmCondGe, rlIdxInit.lowReg, regLength, 0,
Ben Cheng0fd31e42009-09-03 14:40:16 -07003420 (ArmLIR *) cUnit->loopAnalysis->branchToPCR);
Ben Cheng4238ec22009-08-24 16:32:22 -07003421}
3422
3423/*
3424 * vA = idxReg;
3425 * vB = minC;
3426 */
3427static void genHoistedLowerBoundCheck(CompilationUnit *cUnit, MIR *mir)
3428{
3429 DecodedInstruction *dInsn = &mir->dalvikInsn;
Ben Cheng4238ec22009-08-24 16:32:22 -07003430 const int minC = dInsn->vB;
Bill Buzbee1465db52009-09-23 17:17:35 -07003431 RegLocation rlIdx = cUnit->regLocation[mir->dalvikInsn.vA];
Ben Cheng4238ec22009-08-24 16:32:22 -07003432
3433 /* regIdx <- initial index value */
Bill Buzbee1465db52009-09-23 17:17:35 -07003434 rlIdx = loadValue(cUnit, rlIdx, kCoreReg);
Ben Cheng4238ec22009-08-24 16:32:22 -07003435
3436 /* Punt if "regIdxInit + minC >= 0" is false */
Bill Buzbee1465db52009-09-23 17:17:35 -07003437 genRegImmCheck(cUnit, kArmCondLt, rlIdx.lowReg, -minC, 0,
Ben Cheng4238ec22009-08-24 16:32:22 -07003438 (ArmLIR *) cUnit->loopAnalysis->branchToPCR);
3439}
3440
3441/* Extended MIR instructions like PHI */
3442static void handleExtendedMIR(CompilationUnit *cUnit, MIR *mir)
3443{
Bill Buzbee1465db52009-09-23 17:17:35 -07003444 int opOffset = mir->dalvikInsn.opCode - kMirOpFirst;
Ben Cheng4238ec22009-08-24 16:32:22 -07003445 char *msg = dvmCompilerNew(strlen(extendedMIROpNames[opOffset]) + 1,
3446 false);
3447 strcpy(msg, extendedMIROpNames[opOffset]);
Bill Buzbee1465db52009-09-23 17:17:35 -07003448 newLIR1(cUnit, kArmPseudoExtended, (int) msg);
Ben Cheng4238ec22009-08-24 16:32:22 -07003449
3450 switch (mir->dalvikInsn.opCode) {
Bill Buzbee1465db52009-09-23 17:17:35 -07003451 case kMirOpPhi: {
Ben Cheng4238ec22009-08-24 16:32:22 -07003452 char *ssaString = dvmCompilerGetSSAString(cUnit, mir->ssaRep);
Bill Buzbee1465db52009-09-23 17:17:35 -07003453 newLIR1(cUnit, kArmPseudoSSARep, (int) ssaString);
Ben Cheng4238ec22009-08-24 16:32:22 -07003454 break;
3455 }
Bill Buzbee1465db52009-09-23 17:17:35 -07003456 case kMirOpNullNRangeUpCheck: {
Ben Cheng4238ec22009-08-24 16:32:22 -07003457 genHoistedChecksForCountUpLoop(cUnit, mir);
3458 break;
3459 }
Bill Buzbee1465db52009-09-23 17:17:35 -07003460 case kMirOpNullNRangeDownCheck: {
Ben Cheng4238ec22009-08-24 16:32:22 -07003461 genHoistedChecksForCountDownLoop(cUnit, mir);
3462 break;
3463 }
Bill Buzbee1465db52009-09-23 17:17:35 -07003464 case kMirOpLowerBound: {
Ben Cheng4238ec22009-08-24 16:32:22 -07003465 genHoistedLowerBoundCheck(cUnit, mir);
3466 break;
3467 }
Bill Buzbee1465db52009-09-23 17:17:35 -07003468 case kMirOpPunt: {
Ben Cheng4238ec22009-08-24 16:32:22 -07003469 genUnconditionalBranch(cUnit,
3470 (ArmLIR *) cUnit->loopAnalysis->branchToPCR);
3471 break;
3472 }
3473 default:
3474 break;
3475 }
3476}
3477
3478/*
3479 * Create a PC-reconstruction cell for the starting offset of this trace.
3480 * Since the PCR cell is placed near the end of the compiled code which is
3481 * usually out of range for a conditional branch, we put two branches (one
3482 * branch over to the loop body and one layover branch to the actual PCR) at the
3483 * end of the entry block.
3484 */
3485static void setupLoopEntryBlock(CompilationUnit *cUnit, BasicBlock *entry,
3486 ArmLIR *bodyLabel)
3487{
3488 /* Set up the place holder to reconstruct this Dalvik PC */
3489 ArmLIR *pcrLabel = dvmCompilerNew(sizeof(ArmLIR), true);
Bill Buzbee1465db52009-09-23 17:17:35 -07003490 pcrLabel->opCode = ARM_PSEUDO_kPCReconstruction_CELL;
Ben Cheng4238ec22009-08-24 16:32:22 -07003491 pcrLabel->operands[0] =
3492 (int) (cUnit->method->insns + entry->startOffset);
3493 pcrLabel->operands[1] = entry->startOffset;
3494 /* Insert the place holder to the growable list */
3495 dvmInsertGrowableList(&cUnit->pcReconstructionList, pcrLabel);
3496
3497 /*
3498 * Next, create two branches - one branch over to the loop body and the
3499 * other branch to the PCR cell to punt.
3500 */
3501 ArmLIR *branchToBody = dvmCompilerNew(sizeof(ArmLIR), true);
Bill Buzbee1465db52009-09-23 17:17:35 -07003502 branchToBody->opCode = kThumbBUncond;
Ben Cheng4238ec22009-08-24 16:32:22 -07003503 branchToBody->generic.target = (LIR *) bodyLabel;
Ben Chengdcf3e5d2009-09-11 13:42:05 -07003504 setupResourceMasks(branchToBody);
Ben Cheng4238ec22009-08-24 16:32:22 -07003505 cUnit->loopAnalysis->branchToBody = (LIR *) branchToBody;
3506
3507 ArmLIR *branchToPCR = dvmCompilerNew(sizeof(ArmLIR), true);
Bill Buzbee1465db52009-09-23 17:17:35 -07003508 branchToPCR->opCode = kThumbBUncond;
Ben Cheng4238ec22009-08-24 16:32:22 -07003509 branchToPCR->generic.target = (LIR *) pcrLabel;
Ben Chengdcf3e5d2009-09-11 13:42:05 -07003510 setupResourceMasks(branchToPCR);
Ben Cheng4238ec22009-08-24 16:32:22 -07003511 cUnit->loopAnalysis->branchToPCR = (LIR *) branchToPCR;
3512}
3513
Ben Chengd5adae12010-03-26 17:45:28 -07003514#if defined(WITH_SELF_VERIFICATION)
3515static bool selfVerificationPuntOps(MIR *mir)
3516{
3517 DecodedInstruction *decInsn = &mir->dalvikInsn;
3518 OpCode op = decInsn->opCode;
3519 int flags = dexGetInstrFlags(gDvm.instrFlags, op);
3520 /*
3521 * All opcodes that can throw exceptions and use the
3522 * TEMPLATE_THROW_EXCEPTION_COMMON template should be excluded in the trace
3523 * under self-verification mode.
3524 */
3525 return (op == OP_MONITOR_ENTER || op == OP_MONITOR_EXIT ||
3526 op == OP_NEW_INSTANCE || op == OP_NEW_ARRAY ||
3527 op == OP_CHECK_CAST || op == OP_MOVE_EXCEPTION ||
3528 op == OP_FILL_ARRAY_DATA || op == OP_EXECUTE_INLINE ||
3529 op == OP_EXECUTE_INLINE_RANGE ||
3530 (flags & kInstrInvoke));
3531}
3532#endif
3533
Ben Chengba4fc8b2009-06-01 13:00:29 -07003534void dvmCompilerMIR2LIR(CompilationUnit *cUnit)
3535{
3536 /* Used to hold the labels of each block */
Bill Buzbee89efc3d2009-07-28 11:22:22 -07003537 ArmLIR *labelList =
3538 dvmCompilerNew(sizeof(ArmLIR) * cUnit->numBlocks, true);
Ben Chengcec26f62010-01-15 15:29:33 -08003539 GrowableList chainingListByType[kChainingCellGap];
Ben Chengba4fc8b2009-06-01 13:00:29 -07003540 int i;
3541
3542 /*
Ben Cheng38329f52009-07-07 14:19:20 -07003543 * Initialize various types chaining lists.
Ben Chengba4fc8b2009-06-01 13:00:29 -07003544 */
Ben Chengcec26f62010-01-15 15:29:33 -08003545 for (i = 0; i < kChainingCellGap; i++) {
Ben Chengba4fc8b2009-06-01 13:00:29 -07003546 dvmInitGrowableList(&chainingListByType[i], 2);
3547 }
3548
3549 BasicBlock **blockList = cUnit->blockList;
3550
Bill Buzbee6e963e12009-06-17 16:56:19 -07003551 if (cUnit->executionCount) {
3552 /*
3553 * Reserve 6 bytes at the beginning of the trace
3554 * +----------------------------+
3555 * | execution count (4 bytes) |
3556 * +----------------------------+
3557 * | chain cell offset (2 bytes)|
3558 * +----------------------------+
3559 * ...and then code to increment the execution
3560 * count:
3561 * mov r0, pc @ move adr of "mov r0,pc" + 4 to r0
3562 * sub r0, #10 @ back up to addr of executionCount
3563 * ldr r1, [r0]
3564 * add r1, #1
3565 * str r1, [r0]
3566 */
Bill Buzbee1465db52009-09-23 17:17:35 -07003567 newLIR1(cUnit, kArm16BitData, 0);
3568 newLIR1(cUnit, kArm16BitData, 0);
Ben Chengcc6600c2009-06-22 14:45:16 -07003569 cUnit->chainCellOffsetLIR =
Bill Buzbee1465db52009-09-23 17:17:35 -07003570 (LIR *) newLIR1(cUnit, kArm16BitData, CHAIN_CELL_OFFSET_TAG);
Bill Buzbee6e963e12009-06-17 16:56:19 -07003571 cUnit->headerSize = 6;
Bill Buzbee270c1d62009-08-13 16:58:07 -07003572 /* Thumb instruction used directly here to ensure correct size */
Bill Buzbee1465db52009-09-23 17:17:35 -07003573 newLIR2(cUnit, kThumbMovRR_H2L, r0, rpc);
3574 newLIR2(cUnit, kThumbSubRI8, r0, 10);
3575 newLIR3(cUnit, kThumbLdrRRI5, r1, r0, 0);
3576 newLIR2(cUnit, kThumbAddRI8, r1, 1);
3577 newLIR3(cUnit, kThumbStrRRI5, r1, r0, 0);
Bill Buzbee6e963e12009-06-17 16:56:19 -07003578 } else {
3579 /* Just reserve 2 bytes for the chain cell offset */
Ben Chengcc6600c2009-06-22 14:45:16 -07003580 cUnit->chainCellOffsetLIR =
Bill Buzbee1465db52009-09-23 17:17:35 -07003581 (LIR *) newLIR1(cUnit, kArm16BitData, CHAIN_CELL_OFFSET_TAG);
Bill Buzbee6e963e12009-06-17 16:56:19 -07003582 cUnit->headerSize = 2;
3583 }
Ben Cheng1efc9c52009-06-08 18:25:27 -07003584
Ben Chengba4fc8b2009-06-01 13:00:29 -07003585 /* Handle the content in each basic block */
3586 for (i = 0; i < cUnit->numBlocks; i++) {
3587 blockList[i]->visited = true;
3588 MIR *mir;
3589
3590 labelList[i].operands[0] = blockList[i]->startOffset;
3591
Ben Chengcec26f62010-01-15 15:29:33 -08003592 if (blockList[i]->blockType >= kChainingCellGap) {
Ben Chengba4fc8b2009-06-01 13:00:29 -07003593 /*
3594 * Append the label pseudo LIR first. Chaining cells will be handled
3595 * separately afterwards.
3596 */
3597 dvmCompilerAppendLIR(cUnit, (LIR *) &labelList[i]);
3598 }
3599
Bill Buzbee1465db52009-09-23 17:17:35 -07003600 if (blockList[i]->blockType == kEntryBlock) {
3601 labelList[i].opCode = ARM_PSEUDO_kEntryBlock;
Ben Cheng4238ec22009-08-24 16:32:22 -07003602 if (blockList[i]->firstMIRInsn == NULL) {
3603 continue;
3604 } else {
3605 setupLoopEntryBlock(cUnit, blockList[i],
3606 &labelList[blockList[i]->fallThrough->id]);
3607 }
Bill Buzbee1465db52009-09-23 17:17:35 -07003608 } else if (blockList[i]->blockType == kExitBlock) {
3609 labelList[i].opCode = ARM_PSEUDO_kExitBlock;
Ben Cheng4238ec22009-08-24 16:32:22 -07003610 goto gen_fallthrough;
Bill Buzbee1465db52009-09-23 17:17:35 -07003611 } else if (blockList[i]->blockType == kDalvikByteCode) {
3612 labelList[i].opCode = kArmPseudoNormalBlockLabel;
Ben Chenge9695e52009-06-16 16:11:47 -07003613 /* Reset the register state */
Bill Buzbeec6f10662010-02-09 11:16:15 -08003614 dvmCompilerResetRegPool(cUnit);
3615 dvmCompilerClobberAllRegs(cUnit);
3616 dvmCompilerResetNullCheck(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003617 } else {
3618 switch (blockList[i]->blockType) {
Bill Buzbee1465db52009-09-23 17:17:35 -07003619 case kChainingCellNormal:
3620 labelList[i].opCode = ARM_PSEUDO_kChainingCellNormal;
Ben Chengba4fc8b2009-06-01 13:00:29 -07003621 /* handle the codegen later */
3622 dvmInsertGrowableList(
Bill Buzbee1465db52009-09-23 17:17:35 -07003623 &chainingListByType[kChainingCellNormal], (void *) i);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003624 break;
Bill Buzbee1465db52009-09-23 17:17:35 -07003625 case kChainingCellInvokeSingleton:
Ben Cheng38329f52009-07-07 14:19:20 -07003626 labelList[i].opCode =
Bill Buzbee1465db52009-09-23 17:17:35 -07003627 ARM_PSEUDO_kChainingCellInvokeSingleton;
Ben Chengba4fc8b2009-06-01 13:00:29 -07003628 labelList[i].operands[0] =
3629 (int) blockList[i]->containingMethod;
3630 /* handle the codegen later */
3631 dvmInsertGrowableList(
Bill Buzbee1465db52009-09-23 17:17:35 -07003632 &chainingListByType[kChainingCellInvokeSingleton],
Ben Cheng38329f52009-07-07 14:19:20 -07003633 (void *) i);
3634 break;
Bill Buzbee1465db52009-09-23 17:17:35 -07003635 case kChainingCellInvokePredicted:
Ben Cheng38329f52009-07-07 14:19:20 -07003636 labelList[i].opCode =
Bill Buzbee1465db52009-09-23 17:17:35 -07003637 ARM_PSEUDO_kChainingCellInvokePredicted;
Ben Cheng38329f52009-07-07 14:19:20 -07003638 /* handle the codegen later */
3639 dvmInsertGrowableList(
Bill Buzbee1465db52009-09-23 17:17:35 -07003640 &chainingListByType[kChainingCellInvokePredicted],
Ben Cheng38329f52009-07-07 14:19:20 -07003641 (void *) i);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003642 break;
Bill Buzbee1465db52009-09-23 17:17:35 -07003643 case kChainingCellHot:
Ben Chengba4fc8b2009-06-01 13:00:29 -07003644 labelList[i].opCode =
Bill Buzbee1465db52009-09-23 17:17:35 -07003645 ARM_PSEUDO_kChainingCellHot;
Ben Chengba4fc8b2009-06-01 13:00:29 -07003646 /* handle the codegen later */
3647 dvmInsertGrowableList(
Bill Buzbee1465db52009-09-23 17:17:35 -07003648 &chainingListByType[kChainingCellHot],
Ben Chengba4fc8b2009-06-01 13:00:29 -07003649 (void *) i);
3650 break;
Bill Buzbee1465db52009-09-23 17:17:35 -07003651 case kPCReconstruction:
Ben Chengba4fc8b2009-06-01 13:00:29 -07003652 /* Make sure exception handling block is next */
3653 labelList[i].opCode =
Bill Buzbee1465db52009-09-23 17:17:35 -07003654 ARM_PSEUDO_kPCReconstruction_BLOCK_LABEL;
Ben Chengba4fc8b2009-06-01 13:00:29 -07003655 assert (i == cUnit->numBlocks - 2);
3656 handlePCReconstruction(cUnit, &labelList[i+1]);
3657 break;
Bill Buzbee1465db52009-09-23 17:17:35 -07003658 case kExceptionHandling:
3659 labelList[i].opCode = kArmPseudoEHBlockLabel;
Ben Chengba4fc8b2009-06-01 13:00:29 -07003660 if (cUnit->pcReconstructionList.numUsed) {
Bill Buzbee270c1d62009-08-13 16:58:07 -07003661 loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
3662 jitToInterpEntries.dvmJitToInterpPunt),
3663 r1);
Bill Buzbee1465db52009-09-23 17:17:35 -07003664 opReg(cUnit, kOpBlx, r1);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003665 }
3666 break;
Bill Buzbee9c4b7c82009-09-10 10:10:38 -07003667#if defined(WITH_SELF_VERIFICATION) || defined(WITH_JIT_TUNING)
Bill Buzbee1465db52009-09-23 17:17:35 -07003668 case kChainingCellBackwardBranch:
Jeff Hao97319a82009-08-12 16:57:15 -07003669 labelList[i].opCode =
Bill Buzbee1465db52009-09-23 17:17:35 -07003670 ARM_PSEUDO_kChainingCellBackwardBranch;
Jeff Hao97319a82009-08-12 16:57:15 -07003671 /* handle the codegen later */
3672 dvmInsertGrowableList(
Bill Buzbee1465db52009-09-23 17:17:35 -07003673 &chainingListByType[kChainingCellBackwardBranch],
Jeff Hao97319a82009-08-12 16:57:15 -07003674 (void *) i);
3675 break;
3676#endif
Ben Chengba4fc8b2009-06-01 13:00:29 -07003677 default:
3678 break;
3679 }
3680 continue;
3681 }
Ben Chenge9695e52009-06-16 16:11:47 -07003682
Bill Buzbee89efc3d2009-07-28 11:22:22 -07003683 ArmLIR *headLIR = NULL;
Ben Chenge9695e52009-06-16 16:11:47 -07003684
Ben Chengba4fc8b2009-06-01 13:00:29 -07003685 for (mir = blockList[i]->firstMIRInsn; mir; mir = mir->next) {
Bill Buzbee1465db52009-09-23 17:17:35 -07003686
Bill Buzbeec6f10662010-02-09 11:16:15 -08003687 dvmCompilerResetRegPool(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07003688 if (gDvmJit.disableOpt & (1 << kTrackLiveTemps)) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08003689 dvmCompilerClobberAllRegs(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07003690 }
3691
3692 if (gDvmJit.disableOpt & (1 << kSuppressLoads)) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08003693 dvmCompilerResetDefTracking(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07003694 }
3695
3696 if (mir->dalvikInsn.opCode >= kMirOpFirst) {
Ben Cheng4238ec22009-08-24 16:32:22 -07003697 handleExtendedMIR(cUnit, mir);
3698 continue;
3699 }
3700
Bill Buzbee1465db52009-09-23 17:17:35 -07003701
Ben Chengba4fc8b2009-06-01 13:00:29 -07003702 OpCode dalvikOpCode = mir->dalvikInsn.opCode;
3703 InstructionFormat dalvikFormat =
3704 dexGetInstrFormat(gDvm.instrFormat, dalvikOpCode);
Bill Buzbee89efc3d2009-07-28 11:22:22 -07003705 ArmLIR *boundaryLIR =
Bill Buzbee1465db52009-09-23 17:17:35 -07003706 newLIR2(cUnit, ARM_PSEUDO_kDalvikByteCode_BOUNDARY,
Ben Chengccd6c012009-10-15 14:52:45 -07003707 mir->offset,
3708 (int) dvmCompilerGetDalvikDisassembly(&mir->dalvikInsn)
3709 );
Ben Cheng4238ec22009-08-24 16:32:22 -07003710 if (mir->ssaRep) {
3711 char *ssaString = dvmCompilerGetSSAString(cUnit, mir->ssaRep);
Bill Buzbee1465db52009-09-23 17:17:35 -07003712 newLIR1(cUnit, kArmPseudoSSARep, (int) ssaString);
Ben Cheng4238ec22009-08-24 16:32:22 -07003713 }
3714
Ben Chenge9695e52009-06-16 16:11:47 -07003715 /* Remember the first LIR for this block */
3716 if (headLIR == NULL) {
3717 headLIR = boundaryLIR;
Ben Chengd7d426a2009-09-22 11:23:36 -07003718 /* Set the first boundaryLIR as a scheduling barrier */
3719 headLIR->defMask = ENCODE_ALL;
Ben Chenge9695e52009-06-16 16:11:47 -07003720 }
Ben Cheng4238ec22009-08-24 16:32:22 -07003721
Ben Chengba4fc8b2009-06-01 13:00:29 -07003722 bool notHandled;
3723 /*
3724 * Debugging: screen the opcode first to see if it is in the
3725 * do[-not]-compile list
3726 */
3727 bool singleStepMe =
3728 gDvmJit.includeSelectedOp !=
3729 ((gDvmJit.opList[dalvikOpCode >> 3] &
3730 (1 << (dalvikOpCode & 0x7))) !=
3731 0);
Ben Chengd5adae12010-03-26 17:45:28 -07003732#if defined(WITH_SELF_VERIFICATION)
3733 if (singleStepMe == false) {
3734 singleStepMe = selfVerificationPuntOps(mir);
3735 }
3736#endif
Ben Chengba4fc8b2009-06-01 13:00:29 -07003737 if (singleStepMe || cUnit->allSingleStep) {
3738 notHandled = false;
3739 genInterpSingleStep(cUnit, mir);
3740 } else {
3741 opcodeCoverage[dalvikOpCode]++;
3742 switch (dalvikFormat) {
3743 case kFmt10t:
3744 case kFmt20t:
3745 case kFmt30t:
3746 notHandled = handleFmt10t_Fmt20t_Fmt30t(cUnit,
3747 mir, blockList[i], labelList);
3748 break;
3749 case kFmt10x:
3750 notHandled = handleFmt10x(cUnit, mir);
3751 break;
3752 case kFmt11n:
3753 case kFmt31i:
3754 notHandled = handleFmt11n_Fmt31i(cUnit, mir);
3755 break;
3756 case kFmt11x:
3757 notHandled = handleFmt11x(cUnit, mir);
3758 break;
3759 case kFmt12x:
3760 notHandled = handleFmt12x(cUnit, mir);
3761 break;
3762 case kFmt20bc:
3763 notHandled = handleFmt20bc(cUnit, mir);
3764 break;
3765 case kFmt21c:
3766 case kFmt31c:
3767 notHandled = handleFmt21c_Fmt31c(cUnit, mir);
3768 break;
3769 case kFmt21h:
3770 notHandled = handleFmt21h(cUnit, mir);
3771 break;
3772 case kFmt21s:
3773 notHandled = handleFmt21s(cUnit, mir);
3774 break;
3775 case kFmt21t:
3776 notHandled = handleFmt21t(cUnit, mir, blockList[i],
3777 labelList);
3778 break;
3779 case kFmt22b:
3780 case kFmt22s:
3781 notHandled = handleFmt22b_Fmt22s(cUnit, mir);
3782 break;
3783 case kFmt22c:
3784 notHandled = handleFmt22c(cUnit, mir);
3785 break;
3786 case kFmt22cs:
3787 notHandled = handleFmt22cs(cUnit, mir);
3788 break;
3789 case kFmt22t:
3790 notHandled = handleFmt22t(cUnit, mir, blockList[i],
3791 labelList);
3792 break;
3793 case kFmt22x:
3794 case kFmt32x:
3795 notHandled = handleFmt22x_Fmt32x(cUnit, mir);
3796 break;
3797 case kFmt23x:
3798 notHandled = handleFmt23x(cUnit, mir);
3799 break;
3800 case kFmt31t:
3801 notHandled = handleFmt31t(cUnit, mir);
3802 break;
3803 case kFmt3rc:
3804 case kFmt35c:
3805 notHandled = handleFmt35c_3rc(cUnit, mir, blockList[i],
3806 labelList);
3807 break;
3808 case kFmt3rms:
3809 case kFmt35ms:
3810 notHandled = handleFmt35ms_3rms(cUnit, mir,blockList[i],
3811 labelList);
3812 break;
3813 case kFmt3inline:
Andy McFaddenb0a05412009-11-19 10:23:41 -08003814 case kFmt3rinline:
Bill Buzbeece46c942009-11-20 15:41:34 -08003815 notHandled = handleExecuteInline(cUnit, mir);
Andy McFaddenb0a05412009-11-19 10:23:41 -08003816 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07003817 case kFmt51l:
3818 notHandled = handleFmt51l(cUnit, mir);
3819 break;
3820 default:
3821 notHandled = true;
3822 break;
3823 }
3824 }
3825 if (notHandled) {
3826 LOGE("%#06x: Opcode 0x%x (%s) / Fmt %d not handled\n",
3827 mir->offset,
3828 dalvikOpCode, getOpcodeName(dalvikOpCode),
3829 dalvikFormat);
Bill Buzbeefc519dc2010-03-06 23:30:57 -08003830 dvmCompilerAbort(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003831 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07003832 }
3833 }
Ben Cheng4238ec22009-08-24 16:32:22 -07003834
Bill Buzbee1465db52009-09-23 17:17:35 -07003835 if (blockList[i]->blockType == kEntryBlock) {
Ben Cheng4238ec22009-08-24 16:32:22 -07003836 dvmCompilerAppendLIR(cUnit,
3837 (LIR *) cUnit->loopAnalysis->branchToBody);
3838 dvmCompilerAppendLIR(cUnit,
3839 (LIR *) cUnit->loopAnalysis->branchToPCR);
3840 }
3841
3842 if (headLIR) {
3843 /*
3844 * Eliminate redundant loads/stores and delay stores into later
3845 * slots
3846 */
3847 dvmCompilerApplyLocalOptimizations(cUnit, (LIR *) headLIR,
3848 cUnit->lastLIRInsn);
3849 }
3850
3851gen_fallthrough:
Ben Cheng1efc9c52009-06-08 18:25:27 -07003852 /*
3853 * Check if the block is terminated due to trace length constraint -
3854 * insert an unconditional branch to the chaining cell.
3855 */
3856 if (blockList[i]->needFallThroughBranch) {
3857 genUnconditionalBranch(cUnit,
3858 &labelList[blockList[i]->fallThrough->id]);
3859 }
3860
Ben Chengba4fc8b2009-06-01 13:00:29 -07003861 }
3862
Ben Chenge9695e52009-06-16 16:11:47 -07003863 /* Handle the chaining cells in predefined order */
Ben Chengcec26f62010-01-15 15:29:33 -08003864 for (i = 0; i < kChainingCellGap; i++) {
Ben Chengba4fc8b2009-06-01 13:00:29 -07003865 size_t j;
3866 int *blockIdList = (int *) chainingListByType[i].elemList;
3867
3868 cUnit->numChainingCells[i] = chainingListByType[i].numUsed;
3869
3870 /* No chaining cells of this type */
3871 if (cUnit->numChainingCells[i] == 0)
3872 continue;
3873
3874 /* Record the first LIR for a new type of chaining cell */
3875 cUnit->firstChainingLIR[i] = (LIR *) &labelList[blockIdList[0]];
3876
3877 for (j = 0; j < chainingListByType[i].numUsed; j++) {
3878 int blockId = blockIdList[j];
3879
3880 /* Align this chaining cell first */
Bill Buzbee1465db52009-09-23 17:17:35 -07003881 newLIR0(cUnit, kArmPseudoPseudoAlign4);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003882
3883 /* Insert the pseudo chaining instruction */
3884 dvmCompilerAppendLIR(cUnit, (LIR *) &labelList[blockId]);
3885
3886
3887 switch (blockList[blockId]->blockType) {
Bill Buzbee1465db52009-09-23 17:17:35 -07003888 case kChainingCellNormal:
Ben Cheng1efc9c52009-06-08 18:25:27 -07003889 handleNormalChainingCell(cUnit,
Ben Chengba4fc8b2009-06-01 13:00:29 -07003890 blockList[blockId]->startOffset);
3891 break;
Bill Buzbee1465db52009-09-23 17:17:35 -07003892 case kChainingCellInvokeSingleton:
Ben Cheng38329f52009-07-07 14:19:20 -07003893 handleInvokeSingletonChainingCell(cUnit,
Ben Chengba4fc8b2009-06-01 13:00:29 -07003894 blockList[blockId]->containingMethod);
3895 break;
Bill Buzbee1465db52009-09-23 17:17:35 -07003896 case kChainingCellInvokePredicted:
Ben Cheng38329f52009-07-07 14:19:20 -07003897 handleInvokePredictedChainingCell(cUnit);
3898 break;
Bill Buzbee1465db52009-09-23 17:17:35 -07003899 case kChainingCellHot:
Ben Cheng1efc9c52009-06-08 18:25:27 -07003900 handleHotChainingCell(cUnit,
Ben Chengba4fc8b2009-06-01 13:00:29 -07003901 blockList[blockId]->startOffset);
3902 break;
Bill Buzbee9c4b7c82009-09-10 10:10:38 -07003903#if defined(WITH_SELF_VERIFICATION) || defined(WITH_JIT_TUNING)
Bill Buzbee1465db52009-09-23 17:17:35 -07003904 case kChainingCellBackwardBranch:
Jeff Hao97319a82009-08-12 16:57:15 -07003905 handleBackwardBranchChainingCell(cUnit,
3906 blockList[blockId]->startOffset);
3907 break;
3908#endif
Ben Chengba4fc8b2009-06-01 13:00:29 -07003909 default:
Bill Buzbee1465db52009-09-23 17:17:35 -07003910 LOGE("Bad blocktype %d", blockList[blockId]->blockType);
Bill Buzbeefc519dc2010-03-06 23:30:57 -08003911 dvmCompilerAbort(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003912 }
3913 }
3914 }
Ben Chenge9695e52009-06-16 16:11:47 -07003915
Ben Chengcec26f62010-01-15 15:29:33 -08003916 /* Mark the bottom of chaining cells */
3917 cUnit->chainingCellBottom = (LIR *) newLIR0(cUnit, kArmChainingCellBottom);
3918
Ben Cheng6c10a972009-10-29 14:39:18 -07003919 /*
3920 * Generate the branch to the dvmJitToInterpNoChain entry point at the end
3921 * of all chaining cells for the overflow cases.
3922 */
3923 if (cUnit->switchOverflowPad) {
3924 loadConstant(cUnit, r0, (int) cUnit->switchOverflowPad);
3925 loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
3926 jitToInterpEntries.dvmJitToInterpNoChain), r2);
3927 opRegReg(cUnit, kOpAdd, r1, r1);
3928 opRegRegReg(cUnit, kOpAdd, r4PC, r0, r1);
Ben Cheng86717f72010-03-05 15:27:21 -08003929#if defined(JIT_STATS)
Ben Cheng6c10a972009-10-29 14:39:18 -07003930 loadConstant(cUnit, r0, kSwitchOverflow);
3931#endif
3932 opReg(cUnit, kOpBlx, r2);
3933 }
3934
Ben Chenge9695e52009-06-16 16:11:47 -07003935 dvmCompilerApplyGlobalOptimizations(cUnit);
jeffhao9e45c0b2010-02-03 10:24:05 -08003936
3937#if defined(WITH_SELF_VERIFICATION)
3938 selfVerificationBranchInsertPass(cUnit);
3939#endif
Ben Chengba4fc8b2009-06-01 13:00:29 -07003940}
3941
3942/* Accept the work and start compiling */
Bill Buzbee716f1202009-07-23 13:22:09 -07003943bool dvmCompilerDoWork(CompilerWorkOrder *work)
Ben Chengba4fc8b2009-06-01 13:00:29 -07003944{
Ben Chengccd6c012009-10-15 14:52:45 -07003945 bool res;
Ben Chengba4fc8b2009-06-01 13:00:29 -07003946
Ben Cheng6999d842010-01-26 16:46:15 -08003947 if (gDvmJit.codeCacheFull) {
Ben Chengccd6c012009-10-15 14:52:45 -07003948 return false;
3949 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07003950
Ben Chengccd6c012009-10-15 14:52:45 -07003951 switch (work->kind) {
3952 case kWorkOrderMethod:
3953 res = dvmCompileMethod(work->info, &work->result);
3954 break;
3955 case kWorkOrderTrace:
3956 /* Start compilation with maximally allowed trace length */
Bill Buzbeefc519dc2010-03-06 23:30:57 -08003957 res = dvmCompileTrace(work->info, JIT_MAX_TRACE_LEN, &work->result,
3958 work->bailPtr);
Ben Chengccd6c012009-10-15 14:52:45 -07003959 break;
3960 case kWorkOrderTraceDebug: {
3961 bool oldPrintMe = gDvmJit.printMe;
3962 gDvmJit.printMe = true;
3963 /* Start compilation with maximally allowed trace length */
Bill Buzbeefc519dc2010-03-06 23:30:57 -08003964 res = dvmCompileTrace(work->info, JIT_MAX_TRACE_LEN, &work->result,
3965 work->bailPtr);
Ben Chengccd6c012009-10-15 14:52:45 -07003966 gDvmJit.printMe = oldPrintMe;;
3967 break;
3968 }
3969 default:
3970 res = false;
Bill Buzbeefc519dc2010-03-06 23:30:57 -08003971 LOGE("Jit: unknown work order type");
3972 assert(0); // Bail if debug build, discard oteherwise
Ben Chengccd6c012009-10-15 14:52:45 -07003973 }
3974 return res;
Ben Chengba4fc8b2009-06-01 13:00:29 -07003975}
3976
Ben Chengba4fc8b2009-06-01 13:00:29 -07003977/* Architectural-specific debugging helpers go here */
3978void dvmCompilerArchDump(void)
3979{
3980 /* Print compiled opcode in this VM instance */
3981 int i, start, streak;
3982 char buf[1024];
3983
3984 streak = i = 0;
3985 buf[0] = 0;
3986 while (opcodeCoverage[i] == 0 && i < 256) {
3987 i++;
3988 }
3989 if (i == 256) {
3990 return;
3991 }
3992 for (start = i++, streak = 1; i < 256; i++) {
3993 if (opcodeCoverage[i]) {
3994 streak++;
3995 } else {
3996 if (streak == 1) {
3997 sprintf(buf+strlen(buf), "%x,", start);
3998 } else {
3999 sprintf(buf+strlen(buf), "%x-%x,", start, start + streak - 1);
4000 }
4001 streak = 0;
4002 while (opcodeCoverage[i] == 0 && i < 256) {
4003 i++;
4004 }
4005 if (i < 256) {
4006 streak = 1;
4007 start = i;
4008 }
4009 }
4010 }
4011 if (streak) {
4012 if (streak == 1) {
4013 sprintf(buf+strlen(buf), "%x", start);
4014 } else {
4015 sprintf(buf+strlen(buf), "%x-%x", start, start + streak - 1);
4016 }
4017 }
4018 if (strlen(buf)) {
Ben Cheng8b258bf2009-06-24 17:27:07 -07004019 LOGD("dalvik.vm.jit.op = %s", buf);
Ben Chengba4fc8b2009-06-01 13:00:29 -07004020 }
4021}
Ben Chengd7d426a2009-09-22 11:23:36 -07004022
4023/* Common initialization routine for an architecture family */
4024bool dvmCompilerArchInit()
4025{
4026 int i;
4027
Bill Buzbee1465db52009-09-23 17:17:35 -07004028 for (i = 0; i < kArmLast; i++) {
Ben Chengd7d426a2009-09-22 11:23:36 -07004029 if (EncodingMap[i].opCode != i) {
4030 LOGE("Encoding order for %s is wrong: expecting %d, seeing %d",
4031 EncodingMap[i].name, i, EncodingMap[i].opCode);
Bill Buzbeefc519dc2010-03-06 23:30:57 -08004032 dvmAbort(); // OK to dvmAbort - build error
Ben Chengd7d426a2009-09-22 11:23:36 -07004033 }
4034 }
4035
Ben Cheng5d90c202009-11-22 23:31:11 -08004036 return dvmCompilerArchVariantInit();
4037}
4038
4039void *dvmCompilerGetInterpretTemplate()
4040{
4041 return (void*) ((int)gDvmJit.codeCache +
4042 templateEntryOffsets[TEMPLATE_INTERPRET]);
4043}
4044
4045/* Needed by the ld/st optmizatons */
4046ArmLIR* dvmCompilerRegCopyNoInsert(CompilationUnit *cUnit, int rDest, int rSrc)
4047{
4048 return genRegCopyNoInsert(cUnit, rDest, rSrc);
4049}
4050
4051/* Needed by the register allocator */
4052ArmLIR* dvmCompilerRegCopy(CompilationUnit *cUnit, int rDest, int rSrc)
4053{
4054 return genRegCopy(cUnit, rDest, rSrc);
4055}
4056
4057/* Needed by the register allocator */
4058void dvmCompilerRegCopyWide(CompilationUnit *cUnit, int destLo, int destHi,
4059 int srcLo, int srcHi)
4060{
4061 genRegCopyWide(cUnit, destLo, destHi, srcLo, srcHi);
4062}
4063
4064void dvmCompilerFlushRegImpl(CompilationUnit *cUnit, int rBase,
4065 int displacement, int rSrc, OpSize size)
4066{
4067 storeBaseDisp(cUnit, rBase, displacement, rSrc, size);
4068}
4069
4070void dvmCompilerFlushRegWideImpl(CompilationUnit *cUnit, int rBase,
4071 int displacement, int rSrcLo, int rSrcHi)
4072{
4073 storeBaseDispWide(cUnit, rBase, displacement, rSrcLo, rSrcHi);
Ben Chengd7d426a2009-09-22 11:23:36 -07004074}