blob: 79a9fb3f848ea56948b9ed1518b7d52a9106f172 [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);
jeffhao9e45c0b2010-02-03 10:24:05 -0800278#if defined(WITH_SELF_VERIFICATION)
279 cUnit->heapMemOp = true;
280#endif
Bill Buzbee1465db52009-09-23 17:17:35 -0700281 loadPair(cUnit, regPtr, rlResult.lowReg, rlResult.highReg);
jeffhao9e45c0b2010-02-03 10:24:05 -0800282#if defined(WITH_SELF_VERIFICATION)
283 cUnit->heapMemOp = false;
Jeff Hao97319a82009-08-12 16:57:15 -0700284#endif
Bill Buzbeec6f10662010-02-09 11:16:15 -0800285 dvmCompilerFreeTemp(cUnit, regPtr);
Bill Buzbee1465db52009-09-23 17:17:35 -0700286 storeValueWide(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700287}
288
289/* Store a wide field to an object instance */
290static void genIPutWide(CompilationUnit *cUnit, MIR *mir, int fieldOffset)
291{
292 DecodedInstruction *dInsn = &mir->dalvikInsn;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800293 RegLocation rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
294 RegLocation rlObj = dvmCompilerGetSrc(cUnit, mir, 2);
Bill Buzbee1465db52009-09-23 17:17:35 -0700295 rlObj = loadValue(cUnit, rlObj, kCoreReg);
296 int regPtr;
297 rlSrc = loadValueWide(cUnit, rlSrc, kAnyReg);
298 genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset,
299 NULL);/* null object? */
Bill Buzbeec6f10662010-02-09 11:16:15 -0800300 regPtr = dvmCompilerAllocTemp(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700301 opRegRegImm(cUnit, kOpAdd, regPtr, rlObj.lowReg, fieldOffset);
jeffhao9e45c0b2010-02-03 10:24:05 -0800302#if defined(WITH_SELF_VERIFICATION)
303 cUnit->heapMemOp = true;
304#endif
Bill Buzbee1465db52009-09-23 17:17:35 -0700305 storePair(cUnit, regPtr, rlSrc.lowReg, rlSrc.highReg);
jeffhao9e45c0b2010-02-03 10:24:05 -0800306#if defined(WITH_SELF_VERIFICATION)
307 cUnit->heapMemOp = false;
Jeff Hao97319a82009-08-12 16:57:15 -0700308#endif
Bill Buzbeec6f10662010-02-09 11:16:15 -0800309 dvmCompilerFreeTemp(cUnit, regPtr);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700310}
311
312/*
313 * Load a field from an object instance
314 *
Ben Chengba4fc8b2009-06-01 13:00:29 -0700315 */
Bill Buzbee270c1d62009-08-13 16:58:07 -0700316static void genIGet(CompilationUnit *cUnit, MIR *mir, OpSize size,
Ben Chengba4fc8b2009-06-01 13:00:29 -0700317 int fieldOffset)
318{
Bill Buzbee1465db52009-09-23 17:17:35 -0700319 int regPtr;
320 RegLocation rlResult;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700321 DecodedInstruction *dInsn = &mir->dalvikInsn;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800322 RegLocation rlObj = dvmCompilerGetSrc(cUnit, mir, 0);
323 RegLocation rlDest = dvmCompilerGetDest(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -0700324 rlObj = loadValue(cUnit, rlObj, kCoreReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800325 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -0700326 genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset,
327 NULL);/* null object? */
jeffhao9e45c0b2010-02-03 10:24:05 -0800328#if defined(WITH_SELF_VERIFICATION)
329 cUnit->heapMemOp = true;
330#endif
Ben Cheng5d90c202009-11-22 23:31:11 -0800331 loadBaseDisp(cUnit, mir, rlObj.lowReg, fieldOffset, rlResult.lowReg,
332 size, rlObj.sRegLow);
jeffhao9e45c0b2010-02-03 10:24:05 -0800333#if defined(WITH_SELF_VERIFICATION)
334 cUnit->heapMemOp = false;
Jeff Hao97319a82009-08-12 16:57:15 -0700335#endif
Bill Buzbee1465db52009-09-23 17:17:35 -0700336 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700337}
338
339/*
340 * Store a field to an object instance
341 *
Ben Chengba4fc8b2009-06-01 13:00:29 -0700342 */
Bill Buzbee270c1d62009-08-13 16:58:07 -0700343static void genIPut(CompilationUnit *cUnit, MIR *mir, OpSize size,
Ben Chengba4fc8b2009-06-01 13:00:29 -0700344 int fieldOffset)
345{
346 DecodedInstruction *dInsn = &mir->dalvikInsn;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800347 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
348 RegLocation rlObj = dvmCompilerGetSrc(cUnit, mir, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -0700349 rlObj = loadValue(cUnit, rlObj, kCoreReg);
350 rlSrc = loadValue(cUnit, rlSrc, kAnyReg);
351 int regPtr;
352 genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset,
353 NULL);/* null object? */
jeffhao9e45c0b2010-02-03 10:24:05 -0800354#if defined(WITH_SELF_VERIFICATION)
355 cUnit->heapMemOp = true;
356#endif
Bill Buzbee1465db52009-09-23 17:17:35 -0700357 storeBaseDisp(cUnit, rlObj.lowReg, fieldOffset, rlSrc.lowReg, size);
jeffhao9e45c0b2010-02-03 10:24:05 -0800358#if defined(WITH_SELF_VERIFICATION)
359 cUnit->heapMemOp = false;
Jeff Hao97319a82009-08-12 16:57:15 -0700360#endif
Ben Chengba4fc8b2009-06-01 13:00:29 -0700361}
362
363
Ben Chengba4fc8b2009-06-01 13:00:29 -0700364/*
365 * Generate array load
Ben Chengba4fc8b2009-06-01 13:00:29 -0700366 */
Bill Buzbee270c1d62009-08-13 16:58:07 -0700367static void genArrayGet(CompilationUnit *cUnit, MIR *mir, OpSize size,
Bill Buzbee1465db52009-09-23 17:17:35 -0700368 RegLocation rlArray, RegLocation rlIndex,
369 RegLocation rlDest, int scale)
Ben Chengba4fc8b2009-06-01 13:00:29 -0700370{
371 int lenOffset = offsetof(ArrayObject, length);
372 int dataOffset = offsetof(ArrayObject, contents);
Bill Buzbee1465db52009-09-23 17:17:35 -0700373 RegLocation rlResult;
374 rlArray = loadValue(cUnit, rlArray, kCoreReg);
375 rlIndex = loadValue(cUnit, rlIndex, kCoreReg);
376 int regPtr;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700377
378 /* null object? */
Ben Cheng4238ec22009-08-24 16:32:22 -0700379 ArmLIR * pcrLabel = NULL;
380
381 if (!(mir->OptimizationFlags & MIR_IGNORE_NULL_CHECK)) {
Bill Buzbee1465db52009-09-23 17:17:35 -0700382 pcrLabel = genNullCheck(cUnit, rlArray.sRegLow,
383 rlArray.lowReg, mir->offset, NULL);
Ben Cheng4238ec22009-08-24 16:32:22 -0700384 }
385
Bill Buzbeec6f10662010-02-09 11:16:15 -0800386 regPtr = dvmCompilerAllocTemp(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700387
Ben Cheng4238ec22009-08-24 16:32:22 -0700388 if (!(mir->OptimizationFlags & MIR_IGNORE_RANGE_CHECK)) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800389 int regLen = dvmCompilerAllocTemp(cUnit);
Ben Cheng4238ec22009-08-24 16:32:22 -0700390 /* Get len */
Bill Buzbee1465db52009-09-23 17:17:35 -0700391 loadWordDisp(cUnit, rlArray.lowReg, lenOffset, regLen);
392 /* regPtr -> array data */
393 opRegRegImm(cUnit, kOpAdd, regPtr, rlArray.lowReg, dataOffset);
394 genBoundsCheck(cUnit, rlIndex.lowReg, regLen, mir->offset,
395 pcrLabel);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800396 dvmCompilerFreeTemp(cUnit, regLen);
Ben Cheng4238ec22009-08-24 16:32:22 -0700397 } else {
Bill Buzbee1465db52009-09-23 17:17:35 -0700398 /* regPtr -> array data */
399 opRegRegImm(cUnit, kOpAdd, regPtr, rlArray.lowReg, dataOffset);
Ben Cheng4238ec22009-08-24 16:32:22 -0700400 }
Bill Buzbee1465db52009-09-23 17:17:35 -0700401 if ((size == kLong) || (size == kDouble)) {
402 if (scale) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800403 int rNewIndex = dvmCompilerAllocTemp(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700404 opRegRegImm(cUnit, kOpLsl, rNewIndex, rlIndex.lowReg, scale);
405 opRegReg(cUnit, kOpAdd, regPtr, rNewIndex);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800406 dvmCompilerFreeTemp(cUnit, rNewIndex);
Bill Buzbee1465db52009-09-23 17:17:35 -0700407 } else {
408 opRegReg(cUnit, kOpAdd, regPtr, rlIndex.lowReg);
409 }
Bill Buzbeec6f10662010-02-09 11:16:15 -0800410 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
jeffhao9e45c0b2010-02-03 10:24:05 -0800411#if defined(WITH_SELF_VERIFICATION)
412 cUnit->heapMemOp = true;
413#endif
Bill Buzbee1465db52009-09-23 17:17:35 -0700414 loadPair(cUnit, regPtr, rlResult.lowReg, rlResult.highReg);
jeffhao9e45c0b2010-02-03 10:24:05 -0800415#if defined(WITH_SELF_VERIFICATION)
416 cUnit->heapMemOp = false;
417#endif
Bill Buzbeec6f10662010-02-09 11:16:15 -0800418 dvmCompilerFreeTemp(cUnit, regPtr);
Bill Buzbee1465db52009-09-23 17:17:35 -0700419 storeValueWide(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700420 } else {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800421 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
jeffhao9e45c0b2010-02-03 10:24:05 -0800422#if defined(WITH_SELF_VERIFICATION)
423 cUnit->heapMemOp = true;
424#endif
Bill Buzbee1465db52009-09-23 17:17:35 -0700425 loadBaseIndexed(cUnit, regPtr, rlIndex.lowReg, rlResult.lowReg,
426 scale, size);
jeffhao9e45c0b2010-02-03 10:24:05 -0800427#if defined(WITH_SELF_VERIFICATION)
428 cUnit->heapMemOp = false;
429#endif
Bill Buzbeec6f10662010-02-09 11:16:15 -0800430 dvmCompilerFreeTemp(cUnit, regPtr);
Bill Buzbee1465db52009-09-23 17:17:35 -0700431 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700432 }
433}
434
Ben Chengba4fc8b2009-06-01 13:00:29 -0700435/*
436 * Generate array store
437 *
Ben Chengba4fc8b2009-06-01 13:00:29 -0700438 */
Bill Buzbee270c1d62009-08-13 16:58:07 -0700439static void genArrayPut(CompilationUnit *cUnit, MIR *mir, OpSize size,
Bill Buzbee1465db52009-09-23 17:17:35 -0700440 RegLocation rlArray, RegLocation rlIndex,
441 RegLocation rlSrc, int scale)
Ben Chengba4fc8b2009-06-01 13:00:29 -0700442{
443 int lenOffset = offsetof(ArrayObject, length);
444 int dataOffset = offsetof(ArrayObject, contents);
445
Bill Buzbee1465db52009-09-23 17:17:35 -0700446 int regPtr;
447 rlArray = loadValue(cUnit, rlArray, kCoreReg);
448 rlIndex = loadValue(cUnit, rlIndex, kCoreReg);
Ben Chenge9695e52009-06-16 16:11:47 -0700449
Bill Buzbeec6f10662010-02-09 11:16:15 -0800450 if (dvmCompilerIsTemp(cUnit, rlArray.lowReg)) {
451 dvmCompilerClobber(cUnit, rlArray.lowReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700452 regPtr = rlArray.lowReg;
453 } else {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800454 regPtr = dvmCompilerAllocTemp(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700455 genRegCopy(cUnit, regPtr, rlArray.lowReg);
456 }
Ben Chenge9695e52009-06-16 16:11:47 -0700457
Ben Cheng1efc9c52009-06-08 18:25:27 -0700458 /* null object? */
Ben Cheng4238ec22009-08-24 16:32:22 -0700459 ArmLIR * pcrLabel = NULL;
460
461 if (!(mir->OptimizationFlags & MIR_IGNORE_NULL_CHECK)) {
Bill Buzbee1465db52009-09-23 17:17:35 -0700462 pcrLabel = genNullCheck(cUnit, rlArray.sRegLow, rlArray.lowReg,
463 mir->offset, NULL);
Ben Cheng4238ec22009-08-24 16:32:22 -0700464 }
465
466 if (!(mir->OptimizationFlags & MIR_IGNORE_RANGE_CHECK)) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800467 int regLen = dvmCompilerAllocTemp(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700468 //NOTE: max live temps(4) here.
Ben Cheng4238ec22009-08-24 16:32:22 -0700469 /* Get len */
Bill Buzbee1465db52009-09-23 17:17:35 -0700470 loadWordDisp(cUnit, rlArray.lowReg, lenOffset, regLen);
471 /* regPtr -> array data */
472 opRegImm(cUnit, kOpAdd, regPtr, dataOffset);
473 genBoundsCheck(cUnit, rlIndex.lowReg, regLen, mir->offset,
474 pcrLabel);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800475 dvmCompilerFreeTemp(cUnit, regLen);
Ben Cheng4238ec22009-08-24 16:32:22 -0700476 } else {
Bill Buzbee1465db52009-09-23 17:17:35 -0700477 /* regPtr -> array data */
478 opRegImm(cUnit, kOpAdd, regPtr, dataOffset);
Ben Cheng4238ec22009-08-24 16:32:22 -0700479 }
Bill Buzbee1465db52009-09-23 17:17:35 -0700480 /* at this point, regPtr points to array, 2 live temps */
Bill Buzbee1465db52009-09-23 17:17:35 -0700481 if ((size == kLong) || (size == kDouble)) {
482 //TODO: need specific wide routine that can handle fp regs
483 if (scale) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800484 int rNewIndex = dvmCompilerAllocTemp(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700485 opRegRegImm(cUnit, kOpLsl, rNewIndex, rlIndex.lowReg, scale);
486 opRegReg(cUnit, kOpAdd, regPtr, rNewIndex);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800487 dvmCompilerFreeTemp(cUnit, rNewIndex);
Bill Buzbee1465db52009-09-23 17:17:35 -0700488 } else {
489 opRegReg(cUnit, kOpAdd, regPtr, rlIndex.lowReg);
490 }
491 rlSrc = loadValueWide(cUnit, rlSrc, kAnyReg);
jeffhao9e45c0b2010-02-03 10:24:05 -0800492#if defined(WITH_SELF_VERIFICATION)
493 cUnit->heapMemOp = true;
494#endif
Bill Buzbee1465db52009-09-23 17:17:35 -0700495 storePair(cUnit, regPtr, rlSrc.lowReg, rlSrc.highReg);
jeffhao9e45c0b2010-02-03 10:24:05 -0800496#if defined(WITH_SELF_VERIFICATION)
497 cUnit->heapMemOp = false;
498#endif
Bill Buzbeec6f10662010-02-09 11:16:15 -0800499 dvmCompilerFreeTemp(cUnit, regPtr);
Bill Buzbee270c1d62009-08-13 16:58:07 -0700500 } else {
Bill Buzbee1465db52009-09-23 17:17:35 -0700501 rlSrc = loadValue(cUnit, rlSrc, kAnyReg);
jeffhao9e45c0b2010-02-03 10:24:05 -0800502#if defined(WITH_SELF_VERIFICATION)
503 cUnit->heapMemOp = true;
504#endif
Bill Buzbee1465db52009-09-23 17:17:35 -0700505 storeBaseIndexed(cUnit, regPtr, rlIndex.lowReg, rlSrc.lowReg,
506 scale, size);
jeffhao9e45c0b2010-02-03 10:24:05 -0800507#if defined(WITH_SELF_VERIFICATION)
508 cUnit->heapMemOp = false;
Jeff Hao97319a82009-08-12 16:57:15 -0700509#endif
jeffhao9e45c0b2010-02-03 10:24:05 -0800510 }
Ben Chengba4fc8b2009-06-01 13:00:29 -0700511}
512
Bill Buzbeebe6534f2010-03-12 16:01:35 -0800513/*
514 * Generate array object store
515 * Must use explicit register allocation here because of
516 * call-out to dvmCanPutArrayElement
517 */
518static void genArrayObjectPut(CompilationUnit *cUnit, MIR *mir,
519 RegLocation rlArray, RegLocation rlIndex,
520 RegLocation rlSrc, int scale)
521{
522 int lenOffset = offsetof(ArrayObject, length);
523 int dataOffset = offsetof(ArrayObject, contents);
524
525 dvmCompilerFlushAllRegs(cUnit);
526
527 int regLen = r0;
528 int regPtr = r4PC; /* Preserved across call */
529 int regArray = r1;
530 int regIndex = r7; /* Preserved across call */
531
532 loadValueDirectFixed(cUnit, rlArray, regArray);
533 loadValueDirectFixed(cUnit, rlIndex, regIndex);
534
535 /* null object? */
536 ArmLIR * pcrLabel = NULL;
537
538 if (!(mir->OptimizationFlags & MIR_IGNORE_NULL_CHECK)) {
539 pcrLabel = genNullCheck(cUnit, rlArray.sRegLow, regArray,
540 mir->offset, NULL);
541 }
542
543 if (!(mir->OptimizationFlags & MIR_IGNORE_RANGE_CHECK)) {
544 /* Get len */
545 loadWordDisp(cUnit, regArray, lenOffset, regLen);
546 /* regPtr -> array data */
547 opRegRegImm(cUnit, kOpAdd, regPtr, regArray, dataOffset);
548 genBoundsCheck(cUnit, regIndex, regLen, mir->offset,
549 pcrLabel);
550 } else {
551 /* regPtr -> array data */
552 opRegRegImm(cUnit, kOpAdd, regPtr, regArray, dataOffset);
553 }
554
555 /* Get object to store */
556 loadValueDirectFixed(cUnit, rlSrc, r0);
557 loadConstant(cUnit, r2, (int)dvmCanPutArrayElement);
558
559 /* Are we storing null? If so, avoid check */
560 opRegImm(cUnit, kOpCmp, r0, 0);
561 ArmLIR *branchOver = opCondBranch(cUnit, kArmCondEq);
562
563 /* Make sure the types are compatible */
564 loadWordDisp(cUnit, regArray, offsetof(Object, clazz), r1);
565 loadWordDisp(cUnit, r0, offsetof(Object, clazz), r0);
566 opReg(cUnit, kOpBlx, r2);
567 dvmCompilerClobberCallRegs(cUnit);
Bill Buzbee900a3af2010-03-16 12:41:43 -0700568
569 /*
570 * Using fixed registers here, and counting on r4 and r7 being
571 * preserved across the above call. Tell the register allocation
572 * utilities about the regs we are using directly
573 */
574 dvmCompilerLockTemp(cUnit, regPtr); // r4PC
575 dvmCompilerLockTemp(cUnit, regIndex); // r7
576 dvmCompilerLockTemp(cUnit, r0);
577
Bill Buzbeebe6534f2010-03-12 16:01:35 -0800578 /* Bad? - roll back and re-execute if so */
579 genRegImmCheck(cUnit, kArmCondEq, r0, 0, mir->offset, pcrLabel);
580
581 /* Resume here - must reload element, regPtr & index preserved */
582 loadValueDirectFixed(cUnit, rlSrc, r0);
583
584 ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel);
585 target->defMask = ENCODE_ALL;
586 branchOver->generic.target = (LIR *) target;
587
588#if defined(WITH_SELF_VERIFICATION)
589 cUnit->heapMemOp = true;
590#endif
591 storeBaseIndexed(cUnit, regPtr, regIndex, r0,
592 scale, kWord);
593#if defined(WITH_SELF_VERIFICATION)
594 cUnit->heapMemOp = false;
595#endif
596}
597
Ben Cheng5d90c202009-11-22 23:31:11 -0800598static bool genShiftOpLong(CompilationUnit *cUnit, MIR *mir,
599 RegLocation rlDest, RegLocation rlSrc1,
600 RegLocation rlShift)
Ben Chengba4fc8b2009-06-01 13:00:29 -0700601{
Ben Chenge9695e52009-06-16 16:11:47 -0700602 /*
603 * Don't mess with the regsiters here as there is a particular calling
604 * convention to the out-of-line handler.
605 */
Bill Buzbee1465db52009-09-23 17:17:35 -0700606 RegLocation rlResult;
607
608 loadValueDirectWideFixed(cUnit, rlSrc1, r0, r1);
609 loadValueDirect(cUnit, rlShift, r2);
Ben Chenge9695e52009-06-16 16:11:47 -0700610 switch( mir->dalvikInsn.opCode) {
611 case OP_SHL_LONG:
612 case OP_SHL_LONG_2ADDR:
613 genDispatchToHandler(cUnit, TEMPLATE_SHL_LONG);
614 break;
615 case OP_SHR_LONG:
616 case OP_SHR_LONG_2ADDR:
617 genDispatchToHandler(cUnit, TEMPLATE_SHR_LONG);
618 break;
619 case OP_USHR_LONG:
620 case OP_USHR_LONG_2ADDR:
621 genDispatchToHandler(cUnit, TEMPLATE_USHR_LONG);
622 break;
623 default:
624 return true;
625 }
Bill Buzbeec6f10662010-02-09 11:16:15 -0800626 rlResult = dvmCompilerGetReturnWide(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700627 storeValueWide(cUnit, rlDest, rlResult);
Ben Chenge9695e52009-06-16 16:11:47 -0700628 return false;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700629}
Ben Chenge9695e52009-06-16 16:11:47 -0700630
Ben Cheng5d90c202009-11-22 23:31:11 -0800631static bool genArithOpLong(CompilationUnit *cUnit, MIR *mir,
632 RegLocation rlDest, RegLocation rlSrc1,
633 RegLocation rlSrc2)
Ben Chengba4fc8b2009-06-01 13:00:29 -0700634{
Bill Buzbee1465db52009-09-23 17:17:35 -0700635 RegLocation rlResult;
636 OpKind firstOp = kOpBkpt;
637 OpKind secondOp = kOpBkpt;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700638 bool callOut = false;
639 void *callTgt;
640 int retReg = r0;
641 /* TODO - find proper .h file to declare these */
642 long long __aeabi_ldivmod(long long op1, long long op2);
643
644 switch (mir->dalvikInsn.opCode) {
645 case OP_NOT_LONG:
Bill Buzbee1465db52009-09-23 17:17:35 -0700646 rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800647 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -0700648 opRegReg(cUnit, kOpMvn, rlResult.lowReg, rlSrc2.lowReg);
649 opRegReg(cUnit, kOpMvn, rlResult.highReg, rlSrc2.highReg);
650 storeValueWide(cUnit, rlDest, rlResult);
651 return false;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700652 break;
653 case OP_ADD_LONG:
654 case OP_ADD_LONG_2ADDR:
Bill Buzbee1465db52009-09-23 17:17:35 -0700655 firstOp = kOpAdd;
656 secondOp = kOpAdc;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700657 break;
658 case OP_SUB_LONG:
659 case OP_SUB_LONG_2ADDR:
Bill Buzbee1465db52009-09-23 17:17:35 -0700660 firstOp = kOpSub;
661 secondOp = kOpSbc;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700662 break;
663 case OP_MUL_LONG:
664 case OP_MUL_LONG_2ADDR:
Bill Buzbee1465db52009-09-23 17:17:35 -0700665 genMulLong(cUnit, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700666 return false;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700667 case OP_DIV_LONG:
668 case OP_DIV_LONG_2ADDR:
669 callOut = true;
670 retReg = r0;
671 callTgt = (void*)__aeabi_ldivmod;
672 break;
673 /* NOTE - result is in r2/r3 instead of r0/r1 */
674 case OP_REM_LONG:
675 case OP_REM_LONG_2ADDR:
676 callOut = true;
677 callTgt = (void*)__aeabi_ldivmod;
678 retReg = r2;
679 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700680 case OP_AND_LONG_2ADDR:
Bill Buzbee1465db52009-09-23 17:17:35 -0700681 case OP_AND_LONG:
682 firstOp = kOpAnd;
683 secondOp = kOpAnd;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700684 break;
685 case OP_OR_LONG:
686 case OP_OR_LONG_2ADDR:
Bill Buzbee1465db52009-09-23 17:17:35 -0700687 firstOp = kOpOr;
688 secondOp = kOpOr;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700689 break;
690 case OP_XOR_LONG:
691 case OP_XOR_LONG_2ADDR:
Bill Buzbee1465db52009-09-23 17:17:35 -0700692 firstOp = kOpXor;
693 secondOp = kOpXor;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700694 break;
Ben Chenge9695e52009-06-16 16:11:47 -0700695 case OP_NEG_LONG: {
Bill Buzbee51ecf602010-01-14 14:27:52 -0800696 //TUNING: can improve this using Thumb2 code
Bill Buzbeec6f10662010-02-09 11:16:15 -0800697 int tReg = dvmCompilerAllocTemp(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700698 rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800699 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee51ecf602010-01-14 14:27:52 -0800700 loadConstantValue(cUnit, tReg, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -0700701 opRegRegReg(cUnit, kOpSub, rlResult.lowReg,
Bill Buzbee51ecf602010-01-14 14:27:52 -0800702 tReg, rlSrc2.lowReg);
703 opRegReg(cUnit, kOpSbc, tReg, rlSrc2.highReg);
704 genRegCopy(cUnit, rlResult.highReg, tReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700705 storeValueWide(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700706 return false;
Ben Chenge9695e52009-06-16 16:11:47 -0700707 }
Ben Chengba4fc8b2009-06-01 13:00:29 -0700708 default:
709 LOGE("Invalid long arith op");
Bill Buzbeefc519dc2010-03-06 23:30:57 -0800710 dvmCompilerAbort(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700711 }
712 if (!callOut) {
Bill Buzbee1465db52009-09-23 17:17:35 -0700713 genLong3Addr(cUnit, firstOp, secondOp, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700714 } else {
Bill Buzbee1465db52009-09-23 17:17:35 -0700715 // Adjust return regs in to handle case of rem returning r2/r3
Bill Buzbeec6f10662010-02-09 11:16:15 -0800716 dvmCompilerFlushAllRegs(cUnit); /* Send everything to home location */
Bill Buzbee1465db52009-09-23 17:17:35 -0700717 loadValueDirectWideFixed(cUnit, rlSrc1, r0, r1);
718 loadConstant(cUnit, rlr, (int) callTgt);
719 loadValueDirectWideFixed(cUnit, rlSrc2, r2, r3);
720 opReg(cUnit, kOpBlx, rlr);
Elliott Hughes6a555132010-02-25 15:41:42 -0800721 dvmCompilerClobberCallRegs(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700722 if (retReg == r0)
Bill Buzbeec6f10662010-02-09 11:16:15 -0800723 rlResult = dvmCompilerGetReturnWide(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700724 else
Bill Buzbeec6f10662010-02-09 11:16:15 -0800725 rlResult = dvmCompilerGetReturnWideAlt(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700726 storeValueWide(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700727 }
728 return false;
729}
730
Ben Cheng5d90c202009-11-22 23:31:11 -0800731static bool genArithOpInt(CompilationUnit *cUnit, MIR *mir,
732 RegLocation rlDest, RegLocation rlSrc1,
733 RegLocation rlSrc2)
Ben Chengba4fc8b2009-06-01 13:00:29 -0700734{
Bill Buzbee1465db52009-09-23 17:17:35 -0700735 OpKind op = kOpBkpt;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700736 bool callOut = false;
737 bool checkZero = false;
Bill Buzbee1465db52009-09-23 17:17:35 -0700738 bool unary = false;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700739 int retReg = r0;
740 void *callTgt;
Bill Buzbee1465db52009-09-23 17:17:35 -0700741 RegLocation rlResult;
Bill Buzbee0e605272009-12-01 14:28:05 -0800742 bool shiftOp = false;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700743
744 /* TODO - find proper .h file to declare these */
745 int __aeabi_idivmod(int op1, int op2);
746 int __aeabi_idiv(int op1, int op2);
747
748 switch (mir->dalvikInsn.opCode) {
749 case OP_NEG_INT:
Bill Buzbee1465db52009-09-23 17:17:35 -0700750 op = kOpNeg;
751 unary = true;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700752 break;
753 case OP_NOT_INT:
Bill Buzbee1465db52009-09-23 17:17:35 -0700754 op = kOpMvn;
755 unary = true;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700756 break;
757 case OP_ADD_INT:
758 case OP_ADD_INT_2ADDR:
Bill Buzbee1465db52009-09-23 17:17:35 -0700759 op = kOpAdd;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700760 break;
761 case OP_SUB_INT:
762 case OP_SUB_INT_2ADDR:
Bill Buzbee1465db52009-09-23 17:17:35 -0700763 op = kOpSub;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700764 break;
765 case OP_MUL_INT:
766 case OP_MUL_INT_2ADDR:
Bill Buzbee1465db52009-09-23 17:17:35 -0700767 op = kOpMul;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700768 break;
769 case OP_DIV_INT:
770 case OP_DIV_INT_2ADDR:
771 callOut = true;
772 checkZero = true;
773 callTgt = __aeabi_idiv;
774 retReg = r0;
775 break;
776 /* NOTE: returns in r1 */
777 case OP_REM_INT:
778 case OP_REM_INT_2ADDR:
779 callOut = true;
780 checkZero = true;
781 callTgt = __aeabi_idivmod;
782 retReg = r1;
783 break;
784 case OP_AND_INT:
785 case OP_AND_INT_2ADDR:
Bill Buzbee1465db52009-09-23 17:17:35 -0700786 op = kOpAnd;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700787 break;
788 case OP_OR_INT:
789 case OP_OR_INT_2ADDR:
Bill Buzbee1465db52009-09-23 17:17:35 -0700790 op = kOpOr;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700791 break;
792 case OP_XOR_INT:
793 case OP_XOR_INT_2ADDR:
Bill Buzbee1465db52009-09-23 17:17:35 -0700794 op = kOpXor;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700795 break;
796 case OP_SHL_INT:
797 case OP_SHL_INT_2ADDR:
Bill Buzbee0e605272009-12-01 14:28:05 -0800798 shiftOp = true;
Bill Buzbee1465db52009-09-23 17:17:35 -0700799 op = kOpLsl;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700800 break;
801 case OP_SHR_INT:
802 case OP_SHR_INT_2ADDR:
Bill Buzbee0e605272009-12-01 14:28:05 -0800803 shiftOp = true;
Bill Buzbee1465db52009-09-23 17:17:35 -0700804 op = kOpAsr;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700805 break;
806 case OP_USHR_INT:
807 case OP_USHR_INT_2ADDR:
Bill Buzbee0e605272009-12-01 14:28:05 -0800808 shiftOp = true;
Bill Buzbee1465db52009-09-23 17:17:35 -0700809 op = kOpLsr;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700810 break;
811 default:
812 LOGE("Invalid word arith op: 0x%x(%d)",
813 mir->dalvikInsn.opCode, mir->dalvikInsn.opCode);
Bill Buzbeefc519dc2010-03-06 23:30:57 -0800814 dvmCompilerAbort(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700815 }
816 if (!callOut) {
Bill Buzbee1465db52009-09-23 17:17:35 -0700817 rlSrc1 = loadValue(cUnit, rlSrc1, kCoreReg);
818 if (unary) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800819 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -0700820 opRegReg(cUnit, op, rlResult.lowReg,
821 rlSrc1.lowReg);
Ben Chenge9695e52009-06-16 16:11:47 -0700822 } else {
Bill Buzbee1465db52009-09-23 17:17:35 -0700823 rlSrc2 = loadValue(cUnit, rlSrc2, kCoreReg);
Bill Buzbee0e605272009-12-01 14:28:05 -0800824 if (shiftOp) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800825 int tReg = dvmCompilerAllocTemp(cUnit);
Bill Buzbee0e605272009-12-01 14:28:05 -0800826 opRegRegImm(cUnit, kOpAnd, tReg, rlSrc2.lowReg, 31);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800827 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee0e605272009-12-01 14:28:05 -0800828 opRegRegReg(cUnit, op, rlResult.lowReg,
829 rlSrc1.lowReg, tReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800830 dvmCompilerFreeTemp(cUnit, tReg);
Bill Buzbee0e605272009-12-01 14:28:05 -0800831 } else {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800832 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee0e605272009-12-01 14:28:05 -0800833 opRegRegReg(cUnit, op, rlResult.lowReg,
834 rlSrc1.lowReg, rlSrc2.lowReg);
835 }
Ben Chenge9695e52009-06-16 16:11:47 -0700836 }
Bill Buzbee1465db52009-09-23 17:17:35 -0700837 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700838 } else {
Bill Buzbee1465db52009-09-23 17:17:35 -0700839 RegLocation rlResult;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800840 dvmCompilerFlushAllRegs(cUnit); /* Send everything to home location */
Bill Buzbee1465db52009-09-23 17:17:35 -0700841 loadValueDirectFixed(cUnit, rlSrc2, r1);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700842 loadConstant(cUnit, r2, (int) callTgt);
Bill Buzbee1465db52009-09-23 17:17:35 -0700843 loadValueDirectFixed(cUnit, rlSrc1, r0);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700844 if (checkZero) {
Bill Buzbee1465db52009-09-23 17:17:35 -0700845 genNullCheck(cUnit, rlSrc2.sRegLow, r1, mir->offset, NULL);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700846 }
Bill Buzbee1465db52009-09-23 17:17:35 -0700847 opReg(cUnit, kOpBlx, r2);
Elliott Hughes6a555132010-02-25 15:41:42 -0800848 dvmCompilerClobberCallRegs(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700849 if (retReg == r0)
Bill Buzbeec6f10662010-02-09 11:16:15 -0800850 rlResult = dvmCompilerGetReturn(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700851 else
Bill Buzbeec6f10662010-02-09 11:16:15 -0800852 rlResult = dvmCompilerGetReturnAlt(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700853 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700854 }
855 return false;
856}
857
Ben Cheng5d90c202009-11-22 23:31:11 -0800858static bool genArithOp(CompilationUnit *cUnit, MIR *mir)
Ben Chengba4fc8b2009-06-01 13:00:29 -0700859{
860 OpCode opCode = mir->dalvikInsn.opCode;
Bill Buzbee1465db52009-09-23 17:17:35 -0700861 RegLocation rlDest;
862 RegLocation rlSrc1;
863 RegLocation rlSrc2;
864 /* Deduce sizes of operands */
865 if (mir->ssaRep->numUses == 2) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800866 rlSrc1 = dvmCompilerGetSrc(cUnit, mir, 0);
867 rlSrc2 = dvmCompilerGetSrc(cUnit, mir, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -0700868 } else if (mir->ssaRep->numUses == 3) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800869 rlSrc1 = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
870 rlSrc2 = dvmCompilerGetSrc(cUnit, mir, 2);
Bill Buzbee1465db52009-09-23 17:17:35 -0700871 } else {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800872 rlSrc1 = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
873 rlSrc2 = dvmCompilerGetSrcWide(cUnit, mir, 2, 3);
Bill Buzbee1465db52009-09-23 17:17:35 -0700874 assert(mir->ssaRep->numUses == 4);
875 }
876 if (mir->ssaRep->numDefs == 1) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800877 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -0700878 } else {
879 assert(mir->ssaRep->numDefs == 2);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800880 rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -0700881 }
Ben Chengba4fc8b2009-06-01 13:00:29 -0700882
883 if ((opCode >= OP_ADD_LONG_2ADDR) && (opCode <= OP_XOR_LONG_2ADDR)) {
Ben Cheng5d90c202009-11-22 23:31:11 -0800884 return genArithOpLong(cUnit,mir, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700885 }
886 if ((opCode >= OP_ADD_LONG) && (opCode <= OP_XOR_LONG)) {
Ben Cheng5d90c202009-11-22 23:31:11 -0800887 return genArithOpLong(cUnit,mir, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700888 }
889 if ((opCode >= OP_SHL_LONG_2ADDR) && (opCode <= OP_USHR_LONG_2ADDR)) {
Ben Cheng5d90c202009-11-22 23:31:11 -0800890 return genShiftOpLong(cUnit,mir, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700891 }
892 if ((opCode >= OP_SHL_LONG) && (opCode <= OP_USHR_LONG)) {
Ben Cheng5d90c202009-11-22 23:31:11 -0800893 return genShiftOpLong(cUnit,mir, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700894 }
895 if ((opCode >= OP_ADD_INT_2ADDR) && (opCode <= OP_USHR_INT_2ADDR)) {
Ben Cheng5d90c202009-11-22 23:31:11 -0800896 return genArithOpInt(cUnit,mir, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700897 }
898 if ((opCode >= OP_ADD_INT) && (opCode <= OP_USHR_INT)) {
Ben Cheng5d90c202009-11-22 23:31:11 -0800899 return genArithOpInt(cUnit,mir, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700900 }
901 if ((opCode >= OP_ADD_FLOAT_2ADDR) && (opCode <= OP_REM_FLOAT_2ADDR)) {
Ben Cheng5d90c202009-11-22 23:31:11 -0800902 return genArithOpFloat(cUnit,mir, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700903 }
904 if ((opCode >= OP_ADD_FLOAT) && (opCode <= OP_REM_FLOAT)) {
Ben Cheng5d90c202009-11-22 23:31:11 -0800905 return genArithOpFloat(cUnit, mir, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700906 }
907 if ((opCode >= OP_ADD_DOUBLE_2ADDR) && (opCode <= OP_REM_DOUBLE_2ADDR)) {
Ben Cheng5d90c202009-11-22 23:31:11 -0800908 return genArithOpDouble(cUnit,mir, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700909 }
910 if ((opCode >= OP_ADD_DOUBLE) && (opCode <= OP_REM_DOUBLE)) {
Ben Cheng5d90c202009-11-22 23:31:11 -0800911 return genArithOpDouble(cUnit,mir, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700912 }
913 return true;
914}
915
Bill Buzbee1465db52009-09-23 17:17:35 -0700916/* Generate unconditional branch instructions */
917static ArmLIR *genUnconditionalBranch(CompilationUnit *cUnit, ArmLIR *target)
918{
919 ArmLIR *branch = opNone(cUnit, kOpUncondBr);
920 branch->generic.target = (LIR *) target;
921 return branch;
922}
923
Bill Buzbee1465db52009-09-23 17:17:35 -0700924/* Perform the actual operation for OP_RETURN_* */
925static void genReturnCommon(CompilationUnit *cUnit, MIR *mir)
926{
927 genDispatchToHandler(cUnit, TEMPLATE_RETURN);
Ben Cheng86717f72010-03-05 15:27:21 -0800928#if defined(JIT_STATS)
Bill Buzbee1465db52009-09-23 17:17:35 -0700929 gDvmJit.returnOp++;
930#endif
931 int dPC = (int) (cUnit->method->insns + mir->offset);
932 /* Insert branch, but defer setting of target */
933 ArmLIR *branch = genUnconditionalBranch(cUnit, NULL);
934 /* Set up the place holder to reconstruct this Dalvik PC */
935 ArmLIR *pcrLabel = dvmCompilerNew(sizeof(ArmLIR), true);
936 pcrLabel->opCode = ARM_PSEUDO_kPCReconstruction_CELL;
937 pcrLabel->operands[0] = dPC;
938 pcrLabel->operands[1] = mir->offset;
939 /* Insert the place holder to the growable list */
940 dvmInsertGrowableList(&cUnit->pcReconstructionList, pcrLabel);
941 /* Branch to the PC reconstruction code */
942 branch->generic.target = (LIR *) pcrLabel;
943}
944
Ben Chengba4fc8b2009-06-01 13:00:29 -0700945static void genProcessArgsNoRange(CompilationUnit *cUnit, MIR *mir,
946 DecodedInstruction *dInsn,
Bill Buzbee89efc3d2009-07-28 11:22:22 -0700947 ArmLIR **pcrLabel)
Ben Chengba4fc8b2009-06-01 13:00:29 -0700948{
949 unsigned int i;
950 unsigned int regMask = 0;
Bill Buzbee1465db52009-09-23 17:17:35 -0700951 RegLocation rlArg;
952 int numDone = 0;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700953
Bill Buzbee1465db52009-09-23 17:17:35 -0700954 /*
955 * Load arguments to r0..r4. Note that these registers may contain
956 * live values, so we clobber them immediately after loading to prevent
957 * them from being used as sources for subsequent loads.
958 */
Bill Buzbeec6f10662010-02-09 11:16:15 -0800959 dvmCompilerLockAllTemps(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700960 for (i = 0; i < dInsn->vA; i++) {
961 regMask |= 1 << i;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800962 rlArg = dvmCompilerGetSrc(cUnit, mir, numDone++);
Bill Buzbee1465db52009-09-23 17:17:35 -0700963 loadValueDirectFixed(cUnit, rlArg, i);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700964 }
965 if (regMask) {
966 /* Up to 5 args are pushed on top of FP - sizeofStackSaveArea */
Bill Buzbee1465db52009-09-23 17:17:35 -0700967 opRegRegImm(cUnit, kOpSub, r7, rFP,
968 sizeof(StackSaveArea) + (dInsn->vA << 2));
Ben Chengba4fc8b2009-06-01 13:00:29 -0700969 /* generate null check */
970 if (pcrLabel) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800971 *pcrLabel = genNullCheck(cUnit, dvmCompilerSSASrc(mir, 0), r0,
Bill Buzbee1465db52009-09-23 17:17:35 -0700972 mir->offset, NULL);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700973 }
Bill Buzbee270c1d62009-08-13 16:58:07 -0700974 storeMultiple(cUnit, r7, regMask);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700975 }
976}
977
978static void genProcessArgsRange(CompilationUnit *cUnit, MIR *mir,
979 DecodedInstruction *dInsn,
Bill Buzbee89efc3d2009-07-28 11:22:22 -0700980 ArmLIR **pcrLabel)
Ben Chengba4fc8b2009-06-01 13:00:29 -0700981{
982 int srcOffset = dInsn->vC << 2;
983 int numArgs = dInsn->vA;
984 int regMask;
Bill Buzbee1465db52009-09-23 17:17:35 -0700985
986 /*
987 * Note: here, all promoted registers will have been flushed
988 * back to the Dalvik base locations, so register usage restrictins
989 * are lifted. All parms loaded from original Dalvik register
990 * region - even though some might conceivably have valid copies
991 * cached in a preserved register.
992 */
Bill Buzbeec6f10662010-02-09 11:16:15 -0800993 dvmCompilerLockAllTemps(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700994
Ben Chengba4fc8b2009-06-01 13:00:29 -0700995 /*
996 * r4PC : &rFP[vC]
997 * r7: &newFP[0]
998 */
Bill Buzbee1465db52009-09-23 17:17:35 -0700999 opRegRegImm(cUnit, kOpAdd, r4PC, rFP, srcOffset);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001000 /* load [r0 .. min(numArgs,4)] */
1001 regMask = (1 << ((numArgs < 4) ? numArgs : 4)) - 1;
Ben Chengd7d426a2009-09-22 11:23:36 -07001002 /*
1003 * Protect the loadMultiple instruction from being reordered with other
1004 * Dalvik stack accesses.
1005 */
Bill Buzbee270c1d62009-08-13 16:58:07 -07001006 loadMultiple(cUnit, r4PC, regMask);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001007
Bill Buzbee1465db52009-09-23 17:17:35 -07001008 opRegRegImm(cUnit, kOpSub, r7, rFP,
1009 sizeof(StackSaveArea) + (numArgs << 2));
Ben Chengba4fc8b2009-06-01 13:00:29 -07001010 /* generate null check */
1011 if (pcrLabel) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001012 *pcrLabel = genNullCheck(cUnit, dvmCompilerSSASrc(mir, 0), r0,
Bill Buzbee1465db52009-09-23 17:17:35 -07001013 mir->offset, NULL);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001014 }
1015
1016 /*
1017 * Handle remaining 4n arguments:
1018 * store previously loaded 4 values and load the next 4 values
1019 */
1020 if (numArgs >= 8) {
Bill Buzbee89efc3d2009-07-28 11:22:22 -07001021 ArmLIR *loopLabel = NULL;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001022 /*
1023 * r0 contains "this" and it will be used later, so push it to the stack
Bill Buzbee270c1d62009-08-13 16:58:07 -07001024 * first. Pushing r5 (rFP) is just for stack alignment purposes.
Ben Chengba4fc8b2009-06-01 13:00:29 -07001025 */
Bill Buzbee1465db52009-09-23 17:17:35 -07001026 opImm(cUnit, kOpPush, (1 << r0 | 1 << rFP));
Ben Chengba4fc8b2009-06-01 13:00:29 -07001027 /* No need to generate the loop structure if numArgs <= 11 */
1028 if (numArgs > 11) {
1029 loadConstant(cUnit, 5, ((numArgs - 4) >> 2) << 2);
Bill Buzbee1465db52009-09-23 17:17:35 -07001030 loopLabel = newLIR0(cUnit, kArmPseudoTargetLabel);
Ben Chengd7d426a2009-09-22 11:23:36 -07001031 loopLabel->defMask = ENCODE_ALL;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001032 }
Bill Buzbee270c1d62009-08-13 16:58:07 -07001033 storeMultiple(cUnit, r7, regMask);
Ben Chengd7d426a2009-09-22 11:23:36 -07001034 /*
1035 * Protect the loadMultiple instruction from being reordered with other
1036 * Dalvik stack accesses.
1037 */
Bill Buzbee270c1d62009-08-13 16:58:07 -07001038 loadMultiple(cUnit, r4PC, regMask);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001039 /* No need to generate the loop structure if numArgs <= 11 */
1040 if (numArgs > 11) {
Bill Buzbee1465db52009-09-23 17:17:35 -07001041 opRegImm(cUnit, kOpSub, rFP, 4);
1042 genConditionalBranch(cUnit, kArmCondNe, loopLabel);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001043 }
1044 }
1045
1046 /* Save the last batch of loaded values */
Bill Buzbee270c1d62009-08-13 16:58:07 -07001047 storeMultiple(cUnit, r7, regMask);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001048
1049 /* Generate the loop epilogue - don't use r0 */
1050 if ((numArgs > 4) && (numArgs % 4)) {
1051 regMask = ((1 << (numArgs & 0x3)) - 1) << 1;
Ben Chengd7d426a2009-09-22 11:23:36 -07001052 /*
1053 * Protect the loadMultiple instruction from being reordered with other
1054 * Dalvik stack accesses.
1055 */
Bill Buzbee270c1d62009-08-13 16:58:07 -07001056 loadMultiple(cUnit, r4PC, regMask);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001057 }
1058 if (numArgs >= 8)
Bill Buzbee1465db52009-09-23 17:17:35 -07001059 opImm(cUnit, kOpPop, (1 << r0 | 1 << rFP));
Ben Chengba4fc8b2009-06-01 13:00:29 -07001060
1061 /* Save the modulo 4 arguments */
1062 if ((numArgs > 4) && (numArgs % 4)) {
Bill Buzbee270c1d62009-08-13 16:58:07 -07001063 storeMultiple(cUnit, r7, regMask);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001064 }
1065}
1066
Ben Cheng38329f52009-07-07 14:19:20 -07001067/*
1068 * Generate code to setup the call stack then jump to the chaining cell if it
1069 * is not a native method.
1070 */
1071static void genInvokeSingletonCommon(CompilationUnit *cUnit, MIR *mir,
Bill Buzbee89efc3d2009-07-28 11:22:22 -07001072 BasicBlock *bb, ArmLIR *labelList,
1073 ArmLIR *pcrLabel,
Ben Cheng38329f52009-07-07 14:19:20 -07001074 const Method *calleeMethod)
Ben Chengba4fc8b2009-06-01 13:00:29 -07001075{
Bill Buzbee1465db52009-09-23 17:17:35 -07001076 /*
1077 * Note: all Dalvik register state should be flushed to
1078 * memory by the point, so register usage restrictions no
1079 * longer apply. All temp & preserved registers may be used.
1080 */
Bill Buzbeec6f10662010-02-09 11:16:15 -08001081 dvmCompilerLockAllTemps(cUnit);
Bill Buzbee89efc3d2009-07-28 11:22:22 -07001082 ArmLIR *retChainingCell = &labelList[bb->fallThrough->id];
Ben Chengba4fc8b2009-06-01 13:00:29 -07001083
1084 /* r1 = &retChainingCell */
Bill Buzbeec6f10662010-02-09 11:16:15 -08001085 dvmCompilerLockTemp(cUnit, r1);
Bill Buzbee1465db52009-09-23 17:17:35 -07001086 ArmLIR *addrRetChain = opRegRegImm(cUnit, kOpAdd, r1, rpc, 0);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001087 /* r4PC = dalvikCallsite */
1088 loadConstant(cUnit, r4PC,
1089 (int) (cUnit->method->insns + mir->offset));
1090 addrRetChain->generic.target = (LIR *) retChainingCell;
1091 /*
Ben Cheng38329f52009-07-07 14:19:20 -07001092 * r0 = calleeMethod (loaded upon calling genInvokeSingletonCommon)
Ben Chengba4fc8b2009-06-01 13:00:29 -07001093 * r1 = &ChainingCell
1094 * r4PC = callsiteDPC
1095 */
1096 if (dvmIsNativeMethod(calleeMethod)) {
Ben Cheng38329f52009-07-07 14:19:20 -07001097 genDispatchToHandler(cUnit, TEMPLATE_INVOKE_METHOD_NATIVE);
Ben Cheng86717f72010-03-05 15:27:21 -08001098#if defined(JIT_STATS)
Ben Cheng38329f52009-07-07 14:19:20 -07001099 gDvmJit.invokeNative++;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001100#endif
1101 } else {
1102 genDispatchToHandler(cUnit, TEMPLATE_INVOKE_METHOD_CHAIN);
Ben Cheng86717f72010-03-05 15:27:21 -08001103#if defined(JIT_STATS)
1104 gDvmJit.invokeMonomorphic++;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001105#endif
Ben Cheng38329f52009-07-07 14:19:20 -07001106 /* Branch to the chaining cell */
Ben Chengba4fc8b2009-06-01 13:00:29 -07001107 genUnconditionalBranch(cUnit, &labelList[bb->taken->id]);
1108 }
1109 /* Handle exceptions using the interpreter */
1110 genTrap(cUnit, mir->offset, pcrLabel);
1111}
1112
Ben Cheng38329f52009-07-07 14:19:20 -07001113/*
1114 * Generate code to check the validity of a predicted chain and take actions
1115 * based on the result.
1116 *
1117 * 0x426a99aa : ldr r4, [pc, #72] --> r4 <- dalvikPC of this invoke
1118 * 0x426a99ac : add r1, pc, #32 --> r1 <- &retChainingCell
1119 * 0x426a99ae : add r2, pc, #40 --> r2 <- &predictedChainingCell
1120 * 0x426a99b0 : blx_1 0x426a918c --+ TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN
1121 * 0x426a99b2 : blx_2 see above --+
1122 * 0x426a99b4 : b 0x426a99d8 --> off to the predicted chain
1123 * 0x426a99b6 : b 0x426a99c8 --> punt to the interpreter
1124 * 0x426a99b8 : ldr r0, [r7, #44] --> r0 <- this->class->vtable[methodIdx]
1125 * 0x426a99ba : cmp r1, #0 --> compare r1 (rechain count) against 0
1126 * 0x426a99bc : bgt 0x426a99c2 --> >=0? don't rechain
1127 * 0x426a99be : ldr r7, [r6, #96] --+ dvmJitToPatchPredictedChain
1128 * 0x426a99c0 : blx r7 --+
1129 * 0x426a99c2 : add r1, pc, #12 --> r1 <- &retChainingCell
1130 * 0x426a99c4 : blx_1 0x426a9098 --+ TEMPLATE_INVOKE_METHOD_NO_OPT
1131 * 0x426a99c6 : blx_2 see above --+
1132 */
1133static void genInvokeVirtualCommon(CompilationUnit *cUnit, MIR *mir,
1134 int methodIndex,
Bill Buzbee89efc3d2009-07-28 11:22:22 -07001135 ArmLIR *retChainingCell,
1136 ArmLIR *predChainingCell,
1137 ArmLIR *pcrLabel)
Ben Cheng38329f52009-07-07 14:19:20 -07001138{
Bill Buzbee1465db52009-09-23 17:17:35 -07001139 /*
1140 * Note: all Dalvik register state should be flushed to
1141 * memory by the point, so register usage restrictions no
1142 * longer apply. Lock temps to prevent them from being
1143 * allocated by utility routines.
1144 */
Bill Buzbeec6f10662010-02-09 11:16:15 -08001145 dvmCompilerLockAllTemps(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07001146
Ben Cheng38329f52009-07-07 14:19:20 -07001147 /* "this" is already left in r0 by genProcessArgs* */
1148
1149 /* r4PC = dalvikCallsite */
1150 loadConstant(cUnit, r4PC,
1151 (int) (cUnit->method->insns + mir->offset));
1152
1153 /* r1 = &retChainingCell */
Bill Buzbee1465db52009-09-23 17:17:35 -07001154 ArmLIR *addrRetChain = opRegRegImm(cUnit, kOpAdd, r1, rpc, 0);
Ben Cheng38329f52009-07-07 14:19:20 -07001155 addrRetChain->generic.target = (LIR *) retChainingCell;
1156
1157 /* r2 = &predictedChainingCell */
Bill Buzbee1465db52009-09-23 17:17:35 -07001158 ArmLIR *predictedChainingCell = opRegRegImm(cUnit, kOpAdd, r2, rpc, 0);
Ben Cheng38329f52009-07-07 14:19:20 -07001159 predictedChainingCell->generic.target = (LIR *) predChainingCell;
1160
1161 genDispatchToHandler(cUnit, TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN);
1162
1163 /* return through lr - jump to the chaining cell */
1164 genUnconditionalBranch(cUnit, predChainingCell);
1165
1166 /*
1167 * null-check on "this" may have been eliminated, but we still need a PC-
1168 * reconstruction label for stack overflow bailout.
1169 */
1170 if (pcrLabel == NULL) {
1171 int dPC = (int) (cUnit->method->insns + mir->offset);
Bill Buzbee89efc3d2009-07-28 11:22:22 -07001172 pcrLabel = dvmCompilerNew(sizeof(ArmLIR), true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001173 pcrLabel->opCode = ARM_PSEUDO_kPCReconstruction_CELL;
Ben Cheng38329f52009-07-07 14:19:20 -07001174 pcrLabel->operands[0] = dPC;
1175 pcrLabel->operands[1] = mir->offset;
1176 /* Insert the place holder to the growable list */
1177 dvmInsertGrowableList(&cUnit->pcReconstructionList, pcrLabel);
1178 }
1179
1180 /* return through lr+2 - punt to the interpreter */
1181 genUnconditionalBranch(cUnit, pcrLabel);
1182
1183 /*
1184 * return through lr+4 - fully resolve the callee method.
1185 * r1 <- count
1186 * r2 <- &predictedChainCell
1187 * r3 <- this->class
1188 * r4 <- dPC
1189 * r7 <- this->class->vtable
1190 */
1191
1192 /* r0 <- calleeMethod */
Bill Buzbee270c1d62009-08-13 16:58:07 -07001193 loadWordDisp(cUnit, r7, methodIndex * 4, r0);
Ben Cheng38329f52009-07-07 14:19:20 -07001194
1195 /* Check if rechain limit is reached */
Bill Buzbee1465db52009-09-23 17:17:35 -07001196 opRegImm(cUnit, kOpCmp, r1, 0);
Ben Cheng38329f52009-07-07 14:19:20 -07001197
Bill Buzbee1465db52009-09-23 17:17:35 -07001198 ArmLIR *bypassRechaining = opCondBranch(cUnit, kArmCondGt);
Ben Cheng38329f52009-07-07 14:19:20 -07001199
Bill Buzbee270c1d62009-08-13 16:58:07 -07001200 loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
1201 jitToInterpEntries.dvmJitToPatchPredictedChain), r7);
Ben Cheng38329f52009-07-07 14:19:20 -07001202
1203 /*
1204 * r0 = calleeMethod
1205 * r2 = &predictedChainingCell
1206 * r3 = class
1207 *
1208 * &returnChainingCell has been loaded into r1 but is not needed
1209 * when patching the chaining cell and will be clobbered upon
1210 * returning so it will be reconstructed again.
1211 */
Bill Buzbee1465db52009-09-23 17:17:35 -07001212 opReg(cUnit, kOpBlx, r7);
Ben Cheng38329f52009-07-07 14:19:20 -07001213
1214 /* r1 = &retChainingCell */
Bill Buzbee1465db52009-09-23 17:17:35 -07001215 addrRetChain = opRegRegImm(cUnit, kOpAdd, r1, rpc, 0);
Ben Cheng38329f52009-07-07 14:19:20 -07001216 addrRetChain->generic.target = (LIR *) retChainingCell;
1217
1218 bypassRechaining->generic.target = (LIR *) addrRetChain;
1219 /*
1220 * r0 = calleeMethod,
1221 * r1 = &ChainingCell,
1222 * r4PC = callsiteDPC,
1223 */
1224 genDispatchToHandler(cUnit, TEMPLATE_INVOKE_METHOD_NO_OPT);
Ben Cheng86717f72010-03-05 15:27:21 -08001225#if defined(JIT_STATS)
1226 gDvmJit.invokePolymorphic++;
Ben Cheng38329f52009-07-07 14:19:20 -07001227#endif
1228 /* Handle exceptions using the interpreter */
1229 genTrap(cUnit, mir->offset, pcrLabel);
1230}
1231
1232/*
1233 * Up calling this function, "this" is stored in r0. The actual class will be
1234 * chased down off r0 and the predicted one will be retrieved through
1235 * predictedChainingCell then a comparison is performed to see whether the
1236 * previously established chaining is still valid.
1237 *
1238 * The return LIR is a branch based on the comparison result. The actual branch
1239 * target will be setup in the caller.
1240 */
Bill Buzbee89efc3d2009-07-28 11:22:22 -07001241static ArmLIR *genCheckPredictedChain(CompilationUnit *cUnit,
1242 ArmLIR *predChainingCell,
1243 ArmLIR *retChainingCell,
Ben Cheng38329f52009-07-07 14:19:20 -07001244 MIR *mir)
1245{
Bill Buzbee1465db52009-09-23 17:17:35 -07001246 /*
1247 * Note: all Dalvik register state should be flushed to
1248 * memory by the point, so register usage restrictions no
1249 * longer apply. All temp & preserved registers may be used.
1250 */
Bill Buzbeec6f10662010-02-09 11:16:15 -08001251 dvmCompilerLockAllTemps(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07001252
Ben Cheng38329f52009-07-07 14:19:20 -07001253 /* r3 now contains this->clazz */
Bill Buzbee270c1d62009-08-13 16:58:07 -07001254 loadWordDisp(cUnit, r0, offsetof(Object, clazz), r3);
Ben Cheng38329f52009-07-07 14:19:20 -07001255
1256 /*
1257 * r2 now contains predicted class. The starting offset of the
1258 * cached value is 4 bytes into the chaining cell.
1259 */
Bill Buzbee89efc3d2009-07-28 11:22:22 -07001260 ArmLIR *getPredictedClass =
Bill Buzbee270c1d62009-08-13 16:58:07 -07001261 loadWordDisp(cUnit, rpc, offsetof(PredictedChainingCell, clazz), r2);
Ben Cheng38329f52009-07-07 14:19:20 -07001262 getPredictedClass->generic.target = (LIR *) predChainingCell;
1263
1264 /*
1265 * r0 now contains predicted method. The starting offset of the
1266 * cached value is 8 bytes into the chaining cell.
1267 */
Bill Buzbee89efc3d2009-07-28 11:22:22 -07001268 ArmLIR *getPredictedMethod =
Bill Buzbee270c1d62009-08-13 16:58:07 -07001269 loadWordDisp(cUnit, rpc, offsetof(PredictedChainingCell, method), r0);
Ben Cheng38329f52009-07-07 14:19:20 -07001270 getPredictedMethod->generic.target = (LIR *) predChainingCell;
1271
1272 /* Load the stats counter to see if it is time to unchain and refresh */
Bill Buzbee89efc3d2009-07-28 11:22:22 -07001273 ArmLIR *getRechainingRequestCount =
Bill Buzbee270c1d62009-08-13 16:58:07 -07001274 loadWordDisp(cUnit, rpc, offsetof(PredictedChainingCell, counter), r7);
Ben Cheng38329f52009-07-07 14:19:20 -07001275 getRechainingRequestCount->generic.target =
1276 (LIR *) predChainingCell;
1277
1278 /* r4PC = dalvikCallsite */
1279 loadConstant(cUnit, r4PC,
1280 (int) (cUnit->method->insns + mir->offset));
1281
1282 /* r1 = &retChainingCell */
Bill Buzbee1465db52009-09-23 17:17:35 -07001283 ArmLIR *addrRetChain = opRegRegImm(cUnit, kOpAdd, r1, rpc, 0);
Ben Cheng38329f52009-07-07 14:19:20 -07001284 addrRetChain->generic.target = (LIR *) retChainingCell;
1285
1286 /* Check if r2 (predicted class) == r3 (actual class) */
Bill Buzbee1465db52009-09-23 17:17:35 -07001287 opRegReg(cUnit, kOpCmp, r2, r3);
Ben Cheng38329f52009-07-07 14:19:20 -07001288
Bill Buzbee1465db52009-09-23 17:17:35 -07001289 return opCondBranch(cUnit, kArmCondEq);
Ben Cheng38329f52009-07-07 14:19:20 -07001290}
1291
Ben Chengba4fc8b2009-06-01 13:00:29 -07001292/* Geneate a branch to go back to the interpreter */
1293static void genPuntToInterp(CompilationUnit *cUnit, unsigned int offset)
1294{
1295 /* r0 = dalvik pc */
Bill Buzbeec6f10662010-02-09 11:16:15 -08001296 dvmCompilerFlushAllRegs(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001297 loadConstant(cUnit, r0, (int) (cUnit->method->insns + offset));
Bill Buzbee270c1d62009-08-13 16:58:07 -07001298 loadWordDisp(cUnit, r0, offsetof(Object, clazz), r3);
1299 loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
1300 jitToInterpEntries.dvmJitToInterpPunt), r1);
Bill Buzbee1465db52009-09-23 17:17:35 -07001301 opReg(cUnit, kOpBlx, r1);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001302}
1303
1304/*
1305 * Attempt to single step one instruction using the interpreter and return
1306 * to the compiled code for the next Dalvik instruction
1307 */
1308static void genInterpSingleStep(CompilationUnit *cUnit, MIR *mir)
1309{
1310 int flags = dexGetInstrFlags(gDvm.instrFlags, mir->dalvikInsn.opCode);
1311 int flagsToCheck = kInstrCanBranch | kInstrCanSwitch | kInstrCanReturn |
1312 kInstrCanThrow;
Bill Buzbee1465db52009-09-23 17:17:35 -07001313
Bill Buzbee45273872010-03-11 11:12:15 -08001314 //If already optimized out, just ignore
1315 if (mir->dalvikInsn.opCode == OP_NOP)
1316 return;
1317
Bill Buzbee1465db52009-09-23 17:17:35 -07001318 //Ugly, but necessary. Flush all Dalvik regs so Interp can find them
Bill Buzbeec6f10662010-02-09 11:16:15 -08001319 dvmCompilerFlushAllRegs(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07001320
Ben Chengba4fc8b2009-06-01 13:00:29 -07001321 if ((mir->next == NULL) || (flags & flagsToCheck)) {
1322 genPuntToInterp(cUnit, mir->offset);
1323 return;
1324 }
1325 int entryAddr = offsetof(InterpState,
1326 jitToInterpEntries.dvmJitToInterpSingleStep);
Bill Buzbee270c1d62009-08-13 16:58:07 -07001327 loadWordDisp(cUnit, rGLUE, entryAddr, r2);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001328 /* r0 = dalvik pc */
1329 loadConstant(cUnit, r0, (int) (cUnit->method->insns + mir->offset));
1330 /* r1 = dalvik pc of following instruction */
1331 loadConstant(cUnit, r1, (int) (cUnit->method->insns + mir->next->offset));
Bill Buzbee1465db52009-09-23 17:17:35 -07001332 opReg(cUnit, kOpBlx, r2);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001333}
1334
Bill Buzbeec1d9ed42010-02-02 11:04:33 -08001335/*
1336 * To prevent a thread in a monitor wait from blocking the Jit from
1337 * resetting the code cache, heavyweight monitor lock will not
1338 * be allowed to return to an existing translation. Instead, we will
1339 * handle them by branching to a handler, which will in turn call the
1340 * runtime lock routine and then branch directly back to the
1341 * interpreter main loop. Given the high cost of the heavyweight
1342 * lock operation, this additional cost should be slight (especially when
1343 * considering that we expect the vast majority of lock operations to
1344 * use the fast-path thin lock bypass).
1345 */
Ben Cheng5d90c202009-11-22 23:31:11 -08001346static void genMonitorPortable(CompilationUnit *cUnit, MIR *mir)
Bill Buzbee270c1d62009-08-13 16:58:07 -07001347{
Bill Buzbeeefbd3c52009-11-04 22:18:40 -08001348 bool isEnter = (mir->dalvikInsn.opCode == OP_MONITOR_ENTER);
Bill Buzbee1465db52009-09-23 17:17:35 -07001349 genExportPC(cUnit, mir);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001350 dvmCompilerFlushAllRegs(cUnit); /* Send everything to home location */
1351 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001352 loadValueDirectFixed(cUnit, rlSrc, r1);
1353 loadWordDisp(cUnit, rGLUE, offsetof(InterpState, self), r0);
Bill Buzbeec1d9ed42010-02-02 11:04:33 -08001354 genNullCheck(cUnit, rlSrc.sRegLow, r1, mir->offset, NULL);
Bill Buzbeeefbd3c52009-11-04 22:18:40 -08001355 if (isEnter) {
Bill Buzbeec1d9ed42010-02-02 11:04:33 -08001356 /* Get dPC of next insn */
1357 loadConstant(cUnit, r4PC, (int)(cUnit->method->insns + mir->offset +
1358 dexGetInstrWidthAbs(gDvm.instrWidth, OP_MONITOR_ENTER)));
1359#if defined(WITH_DEADLOCK_PREDICTION)
1360 genDispatchToHandler(cUnit, TEMPLATE_MONITOR_ENTER_DEBUG);
1361#else
1362 genDispatchToHandler(cUnit, TEMPLATE_MONITOR_ENTER);
1363#endif
Bill Buzbee1465db52009-09-23 17:17:35 -07001364 } else {
1365 loadConstant(cUnit, r2, (int)dvmUnlockObject);
Bill Buzbeec1d9ed42010-02-02 11:04:33 -08001366 /* Do the call */
1367 opReg(cUnit, kOpBlx, r2);
Bill Buzbee6bbdd6b2010-02-16 14:40:01 -08001368 opRegImm(cUnit, kOpCmp, r0, 0); /* Did we throw? */
1369 ArmLIR *branchOver = opCondBranch(cUnit, kArmCondNe);
1370 loadConstant(cUnit, r0,
1371 (int) (cUnit->method->insns + mir->offset +
1372 dexGetInstrWidthAbs(gDvm.instrWidth, OP_MONITOR_EXIT)));
1373 genDispatchToHandler(cUnit, TEMPLATE_THROW_EXCEPTION_COMMON);
1374 ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel);
1375 target->defMask = ENCODE_ALL;
1376 branchOver->generic.target = (LIR *) target;
Elliott Hughes6a555132010-02-25 15:41:42 -08001377 dvmCompilerClobberCallRegs(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07001378 }
Bill Buzbee270c1d62009-08-13 16:58:07 -07001379}
1380
Ben Chengba4fc8b2009-06-01 13:00:29 -07001381/*
1382 * The following are the first-level codegen routines that analyze the format
1383 * of each bytecode then either dispatch special purpose codegen routines
1384 * or produce corresponding Thumb instructions directly.
1385 */
1386
1387static bool handleFmt10t_Fmt20t_Fmt30t(CompilationUnit *cUnit, MIR *mir,
Bill Buzbee89efc3d2009-07-28 11:22:22 -07001388 BasicBlock *bb, ArmLIR *labelList)
Ben Chengba4fc8b2009-06-01 13:00:29 -07001389{
1390 /* For OP_GOTO, OP_GOTO_16, and OP_GOTO_32 */
1391 genUnconditionalBranch(cUnit, &labelList[bb->taken->id]);
1392 return false;
1393}
1394
1395static bool handleFmt10x(CompilationUnit *cUnit, MIR *mir)
1396{
1397 OpCode dalvikOpCode = mir->dalvikInsn.opCode;
1398 if (((dalvikOpCode >= OP_UNUSED_3E) && (dalvikOpCode <= OP_UNUSED_43)) ||
Andy McFadden96516932009-10-28 17:39:02 -07001399 ((dalvikOpCode >= OP_UNUSED_E3) && (dalvikOpCode <= OP_UNUSED_EB))) {
Ben Chengba4fc8b2009-06-01 13:00:29 -07001400 LOGE("Codegen: got unused opcode 0x%x\n",dalvikOpCode);
1401 return true;
1402 }
1403 switch (dalvikOpCode) {
1404 case OP_RETURN_VOID:
1405 genReturnCommon(cUnit,mir);
1406 break;
1407 case OP_UNUSED_73:
1408 case OP_UNUSED_79:
1409 case OP_UNUSED_7A:
1410 LOGE("Codegen: got unused opcode 0x%x\n",dalvikOpCode);
1411 return true;
1412 case OP_NOP:
1413 break;
1414 default:
1415 return true;
1416 }
1417 return false;
1418}
1419
1420static bool handleFmt11n_Fmt31i(CompilationUnit *cUnit, MIR *mir)
1421{
Bill Buzbee1465db52009-09-23 17:17:35 -07001422 RegLocation rlDest;
1423 RegLocation rlResult;
1424 if (mir->ssaRep->numDefs == 2) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001425 rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -07001426 } else {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001427 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001428 }
Ben Chenge9695e52009-06-16 16:11:47 -07001429
Ben Chengba4fc8b2009-06-01 13:00:29 -07001430 switch (mir->dalvikInsn.opCode) {
1431 case OP_CONST:
Ben Chenge9695e52009-06-16 16:11:47 -07001432 case OP_CONST_4: {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001433 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001434 loadConstantValue(cUnit, rlResult.lowReg, mir->dalvikInsn.vB);
1435 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001436 break;
Ben Chenge9695e52009-06-16 16:11:47 -07001437 }
1438 case OP_CONST_WIDE_32: {
Bill Buzbee1465db52009-09-23 17:17:35 -07001439 //TUNING: single routine to load constant pair for support doubles
Bill Buzbee964a7b02010-01-28 12:54:19 -08001440 //TUNING: load 0/-1 separately to avoid load dependency
Bill Buzbeec6f10662010-02-09 11:16:15 -08001441 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001442 loadConstantValue(cUnit, rlResult.lowReg, mir->dalvikInsn.vB);
1443 opRegRegImm(cUnit, kOpAsr, rlResult.highReg,
1444 rlResult.lowReg, 31);
1445 storeValueWide(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001446 break;
Ben Chenge9695e52009-06-16 16:11:47 -07001447 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07001448 default:
1449 return true;
1450 }
1451 return false;
1452}
1453
1454static bool handleFmt21h(CompilationUnit *cUnit, MIR *mir)
1455{
Bill Buzbee1465db52009-09-23 17:17:35 -07001456 RegLocation rlDest;
1457 RegLocation rlResult;
1458 if (mir->ssaRep->numDefs == 2) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001459 rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -07001460 } else {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001461 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001462 }
Bill Buzbeec6f10662010-02-09 11:16:15 -08001463 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
Ben Chenge9695e52009-06-16 16:11:47 -07001464
Ben Chengba4fc8b2009-06-01 13:00:29 -07001465 switch (mir->dalvikInsn.opCode) {
Ben Chenge9695e52009-06-16 16:11:47 -07001466 case OP_CONST_HIGH16: {
Bill Buzbee1465db52009-09-23 17:17:35 -07001467 loadConstantValue(cUnit, rlResult.lowReg, mir->dalvikInsn.vB << 16);
1468 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001469 break;
Ben Chenge9695e52009-06-16 16:11:47 -07001470 }
1471 case OP_CONST_WIDE_HIGH16: {
Bill Buzbee1465db52009-09-23 17:17:35 -07001472 loadConstantValueWide(cUnit, rlResult.lowReg, rlResult.highReg,
1473 0, mir->dalvikInsn.vB << 16);
1474 storeValueWide(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001475 break;
Ben Chenge9695e52009-06-16 16:11:47 -07001476 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07001477 default:
1478 return true;
1479 }
1480 return false;
1481}
1482
1483static bool handleFmt20bc(CompilationUnit *cUnit, MIR *mir)
1484{
1485 /* For OP_THROW_VERIFICATION_ERROR */
1486 genInterpSingleStep(cUnit, mir);
1487 return false;
1488}
1489
1490static bool handleFmt21c_Fmt31c(CompilationUnit *cUnit, MIR *mir)
1491{
Bill Buzbee1465db52009-09-23 17:17:35 -07001492 RegLocation rlResult;
1493 RegLocation rlDest;
1494 RegLocation rlSrc;
Ben Chenge9695e52009-06-16 16:11:47 -07001495
Ben Chengba4fc8b2009-06-01 13:00:29 -07001496 switch (mir->dalvikInsn.opCode) {
Ben Chengba4fc8b2009-06-01 13:00:29 -07001497 case OP_CONST_STRING_JUMBO:
1498 case OP_CONST_STRING: {
1499 void *strPtr = (void*)
1500 (cUnit->method->clazz->pDvmDex->pResStrings[mir->dalvikInsn.vB]);
1501 assert(strPtr != NULL);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001502 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
1503 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001504 loadConstantValue(cUnit, rlResult.lowReg, (int) strPtr );
1505 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001506 break;
1507 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07001508 case OP_CONST_CLASS: {
1509 void *classPtr = (void*)
1510 (cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vB]);
1511 assert(classPtr != NULL);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001512 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
1513 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001514 loadConstantValue(cUnit, rlResult.lowReg, (int) classPtr );
1515 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001516 break;
1517 }
1518 case OP_SGET_OBJECT:
1519 case OP_SGET_BOOLEAN:
1520 case OP_SGET_CHAR:
1521 case OP_SGET_BYTE:
1522 case OP_SGET_SHORT:
1523 case OP_SGET: {
Bill Buzbee50a6bf22009-07-08 13:08:04 -07001524 int valOffset = offsetof(StaticField, value);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001525 int tReg = dvmCompilerAllocTemp(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001526 void *fieldPtr = (void*)
1527 (cUnit->method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vB]);
1528 assert(fieldPtr != NULL);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001529 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
1530 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001531 loadConstant(cUnit, tReg, (int) fieldPtr + valOffset);
jeffhao9e45c0b2010-02-03 10:24:05 -08001532#if defined(WITH_SELF_VERIFICATION)
1533 cUnit->heapMemOp = true;
1534#endif
Bill Buzbee1465db52009-09-23 17:17:35 -07001535 loadWordDisp(cUnit, tReg, 0, rlResult.lowReg);
jeffhao9e45c0b2010-02-03 10:24:05 -08001536#if defined(WITH_SELF_VERIFICATION)
1537 cUnit->heapMemOp = false;
Jeff Hao97319a82009-08-12 16:57:15 -07001538#endif
Bill Buzbee1465db52009-09-23 17:17:35 -07001539 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001540 break;
1541 }
1542 case OP_SGET_WIDE: {
Bill Buzbee50a6bf22009-07-08 13:08:04 -07001543 int valOffset = offsetof(StaticField, value);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001544 void *fieldPtr = (void*)
1545 (cUnit->method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vB]);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001546 int tReg = dvmCompilerAllocTemp(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001547 assert(fieldPtr != NULL);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001548 rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
1549 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001550 loadConstant(cUnit, tReg, (int) fieldPtr + valOffset);
jeffhao9e45c0b2010-02-03 10:24:05 -08001551#if defined(WITH_SELF_VERIFICATION)
1552 cUnit->heapMemOp = true;
1553#endif
Bill Buzbee1465db52009-09-23 17:17:35 -07001554 loadPair(cUnit, tReg, rlResult.lowReg, rlResult.highReg);
jeffhao9e45c0b2010-02-03 10:24:05 -08001555#if defined(WITH_SELF_VERIFICATION)
1556 cUnit->heapMemOp = false;
Jeff Hao97319a82009-08-12 16:57:15 -07001557#endif
Bill Buzbee1465db52009-09-23 17:17:35 -07001558 storeValueWide(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001559 break;
1560 }
1561 case OP_SPUT_OBJECT:
1562 case OP_SPUT_BOOLEAN:
1563 case OP_SPUT_CHAR:
1564 case OP_SPUT_BYTE:
1565 case OP_SPUT_SHORT:
1566 case OP_SPUT: {
Bill Buzbee50a6bf22009-07-08 13:08:04 -07001567 int valOffset = offsetof(StaticField, value);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001568 int tReg = dvmCompilerAllocTemp(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001569 void *fieldPtr = (void*)
1570 (cUnit->method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vB]);
Ben Chenge9695e52009-06-16 16:11:47 -07001571
Ben Chengba4fc8b2009-06-01 13:00:29 -07001572 assert(fieldPtr != NULL);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001573 rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001574 rlSrc = loadValue(cUnit, rlSrc, kAnyReg);
1575 loadConstant(cUnit, tReg, (int) fieldPtr + valOffset);
jeffhao9e45c0b2010-02-03 10:24:05 -08001576#if defined(WITH_SELF_VERIFICATION)
1577 cUnit->heapMemOp = true;
1578#endif
Bill Buzbee1465db52009-09-23 17:17:35 -07001579 storeWordDisp(cUnit, tReg, 0 ,rlSrc.lowReg);
jeffhao9e45c0b2010-02-03 10:24:05 -08001580#if defined(WITH_SELF_VERIFICATION)
1581 cUnit->heapMemOp = false;
Jeff Hao97319a82009-08-12 16:57:15 -07001582#endif
Ben Chengba4fc8b2009-06-01 13:00:29 -07001583 break;
1584 }
1585 case OP_SPUT_WIDE: {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001586 int tReg = dvmCompilerAllocTemp(cUnit);
Bill Buzbee50a6bf22009-07-08 13:08:04 -07001587 int valOffset = offsetof(StaticField, value);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001588 void *fieldPtr = (void*)
1589 (cUnit->method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vB]);
Ben Chenge9695e52009-06-16 16:11:47 -07001590
Ben Chengba4fc8b2009-06-01 13:00:29 -07001591 assert(fieldPtr != NULL);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001592 rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -07001593 rlSrc = loadValueWide(cUnit, rlSrc, kAnyReg);
1594 loadConstant(cUnit, tReg, (int) fieldPtr + valOffset);
jeffhao9e45c0b2010-02-03 10:24:05 -08001595#if defined(WITH_SELF_VERIFICATION)
1596 cUnit->heapMemOp = true;
1597#endif
Bill Buzbee1465db52009-09-23 17:17:35 -07001598 storePair(cUnit, tReg, rlSrc.lowReg, rlSrc.highReg);
jeffhao9e45c0b2010-02-03 10:24:05 -08001599#if defined(WITH_SELF_VERIFICATION)
1600 cUnit->heapMemOp = false;
Jeff Hao97319a82009-08-12 16:57:15 -07001601#endif
Ben Chengba4fc8b2009-06-01 13:00:29 -07001602 break;
1603 }
1604 case OP_NEW_INSTANCE: {
Ben Chenge9695e52009-06-16 16:11:47 -07001605 /*
1606 * Obey the calling convention and don't mess with the register
1607 * usage.
1608 */
Ben Chengba4fc8b2009-06-01 13:00:29 -07001609 ClassObject *classPtr = (void*)
1610 (cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vB]);
1611 assert(classPtr != NULL);
1612 assert(classPtr->status & CLASS_INITIALIZED);
Ben Cheng79d173c2009-09-29 16:12:51 -07001613 /*
1614 * If it is going to throw, it should not make to the trace to begin
Bill Buzbee1465db52009-09-23 17:17:35 -07001615 * with. However, Alloc might throw, so we need to genExportPC()
Ben Cheng79d173c2009-09-29 16:12:51 -07001616 */
1617 assert((classPtr->accessFlags & (ACC_INTERFACE|ACC_ABSTRACT)) == 0);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001618 dvmCompilerFlushAllRegs(cUnit); /* Everything to home location */
Bill Buzbee1465db52009-09-23 17:17:35 -07001619 genExportPC(cUnit, mir);
1620 loadConstant(cUnit, r2, (int)dvmAllocObject);
Ben Chenge9695e52009-06-16 16:11:47 -07001621 loadConstant(cUnit, r0, (int) classPtr);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001622 loadConstant(cUnit, r1, ALLOC_DONT_TRACK);
Bill Buzbee1465db52009-09-23 17:17:35 -07001623 opReg(cUnit, kOpBlx, r2);
Elliott Hughes6a555132010-02-25 15:41:42 -08001624 dvmCompilerClobberCallRegs(cUnit);
Ben Cheng4f489172009-09-27 17:08:35 -07001625 /* generate a branch over if allocation is successful */
Bill Buzbee1465db52009-09-23 17:17:35 -07001626 opRegImm(cUnit, kOpCmp, r0, 0); /* NULL? */
1627 ArmLIR *branchOver = opCondBranch(cUnit, kArmCondNe);
Ben Cheng4f489172009-09-27 17:08:35 -07001628 /*
1629 * OOM exception needs to be thrown here and cannot re-execute
1630 */
1631 loadConstant(cUnit, r0,
1632 (int) (cUnit->method->insns + mir->offset));
1633 genDispatchToHandler(cUnit, TEMPLATE_THROW_EXCEPTION_COMMON);
1634 /* noreturn */
1635
Bill Buzbee1465db52009-09-23 17:17:35 -07001636 ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel);
Ben Cheng4f489172009-09-27 17:08:35 -07001637 target->defMask = ENCODE_ALL;
1638 branchOver->generic.target = (LIR *) target;
Bill Buzbeec6f10662010-02-09 11:16:15 -08001639 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
1640 rlResult = dvmCompilerGetReturn(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07001641 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001642 break;
1643 }
1644 case OP_CHECK_CAST: {
Ben Chenge9695e52009-06-16 16:11:47 -07001645 /*
1646 * Obey the calling convention and don't mess with the register
1647 * usage.
1648 */
Ben Chengba4fc8b2009-06-01 13:00:29 -07001649 ClassObject *classPtr =
1650 (cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vB]);
Bill Buzbee4df41a52009-11-12 17:07:16 -08001651 /*
1652 * Note: It is possible that classPtr is NULL at this point,
1653 * even though this instruction has been successfully interpreted.
1654 * If the previous interpretation had a null source, the
1655 * interpreter would not have bothered to resolve the clazz.
1656 * Bail out to the interpreter in this case, and log it
1657 * so that we can tell if it happens frequently.
1658 */
1659 if (classPtr == NULL) {
1660 LOGD("null clazz in OP_CHECK_CAST, single-stepping");
1661 genInterpSingleStep(cUnit, mir);
1662 return false;
1663 }
Bill Buzbeec6f10662010-02-09 11:16:15 -08001664 dvmCompilerFlushAllRegs(cUnit); /* Everything to home location */
Ben Chengba4fc8b2009-06-01 13:00:29 -07001665 loadConstant(cUnit, r1, (int) classPtr );
Bill Buzbeec6f10662010-02-09 11:16:15 -08001666 rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001667 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
1668 opRegImm(cUnit, kOpCmp, rlSrc.lowReg, 0); /* Null? */
1669 ArmLIR *branch1 = opCondBranch(cUnit, kArmCondEq);
1670 /*
1671 * rlSrc.lowReg now contains object->clazz. Note that
1672 * it could have been allocated r0, but we're okay so long
1673 * as we don't do anything desctructive until r0 is loaded
1674 * with clazz.
1675 */
Ben Chengba4fc8b2009-06-01 13:00:29 -07001676 /* r0 now contains object->clazz */
Bill Buzbee1465db52009-09-23 17:17:35 -07001677 loadWordDisp(cUnit, rlSrc.lowReg, offsetof(Object, clazz), r0);
1678 loadConstant(cUnit, r2, (int)dvmInstanceofNonTrivial);
1679 opRegReg(cUnit, kOpCmp, r0, r1);
1680 ArmLIR *branch2 = opCondBranch(cUnit, kArmCondEq);
1681 opReg(cUnit, kOpBlx, r2);
Elliott Hughes6a555132010-02-25 15:41:42 -08001682 dvmCompilerClobberCallRegs(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07001683 /*
1684 * If null, check cast failed - punt to the interpreter. Because
1685 * interpreter will be the one throwing, we don't need to
1686 * genExportPC() here.
1687 */
Bill Buzbee270c1d62009-08-13 16:58:07 -07001688 genZeroCheck(cUnit, r0, mir->offset, NULL);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001689 /* check cast passed - branch target here */
Bill Buzbee1465db52009-09-23 17:17:35 -07001690 ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel);
Ben Chengd7d426a2009-09-22 11:23:36 -07001691 target->defMask = ENCODE_ALL;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001692 branch1->generic.target = (LIR *)target;
1693 branch2->generic.target = (LIR *)target;
1694 break;
1695 }
1696 default:
1697 return true;
1698 }
1699 return false;
1700}
1701
1702static bool handleFmt11x(CompilationUnit *cUnit, MIR *mir)
1703{
1704 OpCode dalvikOpCode = mir->dalvikInsn.opCode;
Bill Buzbee1465db52009-09-23 17:17:35 -07001705 RegLocation rlResult;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001706 switch (dalvikOpCode) {
1707 case OP_MOVE_EXCEPTION: {
1708 int offset = offsetof(InterpState, self);
1709 int exOffset = offsetof(Thread, exception);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001710 int selfReg = dvmCompilerAllocTemp(cUnit);
1711 int resetReg = dvmCompilerAllocTemp(cUnit);
1712 RegLocation rlDest = dvmCompilerGetDest(cUnit, mir, 0);
1713 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001714 loadWordDisp(cUnit, rGLUE, offset, selfReg);
Bill Buzbeef9f33282009-11-22 12:45:30 -08001715 loadConstant(cUnit, resetReg, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001716 loadWordDisp(cUnit, selfReg, exOffset, rlResult.lowReg);
Bill Buzbeef9f33282009-11-22 12:45:30 -08001717 storeWordDisp(cUnit, selfReg, exOffset, resetReg);
Bill Buzbee1465db52009-09-23 17:17:35 -07001718 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001719 break;
1720 }
1721 case OP_MOVE_RESULT:
1722 case OP_MOVE_RESULT_OBJECT: {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001723 RegLocation rlDest = dvmCompilerGetDest(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001724 RegLocation rlSrc = LOC_DALVIK_RETURN_VAL;
1725 rlSrc.fp = rlDest.fp;
1726 storeValue(cUnit, rlDest, rlSrc);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001727 break;
1728 }
1729 case OP_MOVE_RESULT_WIDE: {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001730 RegLocation rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -07001731 RegLocation rlSrc = LOC_DALVIK_RETURN_VAL_WIDE;
1732 rlSrc.fp = rlDest.fp;
1733 storeValueWide(cUnit, rlDest, rlSrc);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001734 break;
1735 }
1736 case OP_RETURN_WIDE: {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001737 RegLocation rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -07001738 RegLocation rlDest = LOC_DALVIK_RETURN_VAL_WIDE;
1739 rlDest.fp = rlSrc.fp;
1740 storeValueWide(cUnit, rlDest, rlSrc);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001741 genReturnCommon(cUnit,mir);
1742 break;
1743 }
1744 case OP_RETURN:
1745 case OP_RETURN_OBJECT: {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001746 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001747 RegLocation rlDest = LOC_DALVIK_RETURN_VAL;
1748 rlDest.fp = rlSrc.fp;
1749 storeValue(cUnit, rlDest, rlSrc);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001750 genReturnCommon(cUnit,mir);
1751 break;
1752 }
Bill Buzbee1465db52009-09-23 17:17:35 -07001753 case OP_MONITOR_EXIT:
Ben Chengba4fc8b2009-06-01 13:00:29 -07001754 case OP_MONITOR_ENTER:
Bill Buzbeed0937ef2009-12-22 16:15:39 -08001755#if defined(WITH_DEADLOCK_PREDICTION) || defined(WITH_MONITOR_TRACKING)
Ben Cheng5d90c202009-11-22 23:31:11 -08001756 genMonitorPortable(cUnit, mir);
Bill Buzbee1465db52009-09-23 17:17:35 -07001757#else
Ben Cheng5d90c202009-11-22 23:31:11 -08001758 genMonitor(cUnit, mir);
Bill Buzbee1465db52009-09-23 17:17:35 -07001759#endif
Ben Chengba4fc8b2009-06-01 13:00:29 -07001760 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001761 case OP_THROW: {
1762 genInterpSingleStep(cUnit, mir);
1763 break;
1764 }
1765 default:
1766 return true;
1767 }
1768 return false;
1769}
1770
Bill Buzbeed45ba372009-06-15 17:00:57 -07001771static bool handleFmt12x(CompilationUnit *cUnit, MIR *mir)
1772{
1773 OpCode opCode = mir->dalvikInsn.opCode;
Bill Buzbee1465db52009-09-23 17:17:35 -07001774 RegLocation rlDest;
1775 RegLocation rlSrc;
1776 RegLocation rlResult;
Bill Buzbeed45ba372009-06-15 17:00:57 -07001777
Ben Chengba4fc8b2009-06-01 13:00:29 -07001778 if ( (opCode >= OP_ADD_INT_2ADDR) && (opCode <= OP_REM_DOUBLE_2ADDR)) {
Ben Cheng5d90c202009-11-22 23:31:11 -08001779 return genArithOp( cUnit, mir );
Ben Chengba4fc8b2009-06-01 13:00:29 -07001780 }
1781
Bill Buzbee1465db52009-09-23 17:17:35 -07001782 if (mir->ssaRep->numUses == 2)
Bill Buzbeec6f10662010-02-09 11:16:15 -08001783 rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -07001784 else
Bill Buzbeec6f10662010-02-09 11:16:15 -08001785 rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001786 if (mir->ssaRep->numDefs == 2)
Bill Buzbeec6f10662010-02-09 11:16:15 -08001787 rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -07001788 else
Bill Buzbeec6f10662010-02-09 11:16:15 -08001789 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
Ben Chenge9695e52009-06-16 16:11:47 -07001790
Ben Chengba4fc8b2009-06-01 13:00:29 -07001791 switch (opCode) {
Bill Buzbee1465db52009-09-23 17:17:35 -07001792 case OP_DOUBLE_TO_INT:
Ben Chengba4fc8b2009-06-01 13:00:29 -07001793 case OP_INT_TO_FLOAT:
Ben Chengba4fc8b2009-06-01 13:00:29 -07001794 case OP_FLOAT_TO_INT:
Ben Chengba4fc8b2009-06-01 13:00:29 -07001795 case OP_DOUBLE_TO_FLOAT:
Ben Chengba4fc8b2009-06-01 13:00:29 -07001796 case OP_FLOAT_TO_DOUBLE:
Ben Chengba4fc8b2009-06-01 13:00:29 -07001797 case OP_INT_TO_DOUBLE:
Ben Chengba4fc8b2009-06-01 13:00:29 -07001798 case OP_FLOAT_TO_LONG:
Ben Chengba4fc8b2009-06-01 13:00:29 -07001799 case OP_LONG_TO_FLOAT:
Ben Chengba4fc8b2009-06-01 13:00:29 -07001800 case OP_DOUBLE_TO_LONG:
Ben Chengba4fc8b2009-06-01 13:00:29 -07001801 case OP_LONG_TO_DOUBLE:
Ben Cheng5d90c202009-11-22 23:31:11 -08001802 return genConversion(cUnit, mir);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001803 case OP_NEG_INT:
1804 case OP_NOT_INT:
Ben Cheng5d90c202009-11-22 23:31:11 -08001805 return genArithOpInt(cUnit, mir, rlDest, rlSrc, rlSrc);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001806 case OP_NEG_LONG:
1807 case OP_NOT_LONG:
Ben Cheng5d90c202009-11-22 23:31:11 -08001808 return genArithOpLong(cUnit, mir, rlDest, rlSrc, rlSrc);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001809 case OP_NEG_FLOAT:
Ben Cheng5d90c202009-11-22 23:31:11 -08001810 return genArithOpFloat(cUnit, mir, rlDest, rlSrc, rlSrc);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001811 case OP_NEG_DOUBLE:
Ben Cheng5d90c202009-11-22 23:31:11 -08001812 return genArithOpDouble(cUnit, mir, rlDest, rlSrc, rlSrc);
Bill Buzbee1465db52009-09-23 17:17:35 -07001813 case OP_MOVE_WIDE:
1814 storeValueWide(cUnit, rlDest, rlSrc);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001815 break;
Bill Buzbee1465db52009-09-23 17:17:35 -07001816 case OP_INT_TO_LONG:
Bill Buzbeec6f10662010-02-09 11:16:15 -08001817 rlSrc = dvmCompilerUpdateLoc(cUnit, rlSrc);
1818 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee964a7b02010-01-28 12:54:19 -08001819 //TUNING: shouldn't loadValueDirect already check for phys reg?
Bill Buzbee1465db52009-09-23 17:17:35 -07001820 if (rlSrc.location == kLocPhysReg) {
1821 genRegCopy(cUnit, rlResult.lowReg, rlSrc.lowReg);
1822 } else {
1823 loadValueDirect(cUnit, rlSrc, rlResult.lowReg);
1824 }
1825 opRegRegImm(cUnit, kOpAsr, rlResult.highReg,
1826 rlResult.lowReg, 31);
1827 storeValueWide(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001828 break;
Bill Buzbee1465db52009-09-23 17:17:35 -07001829 case OP_LONG_TO_INT:
Bill Buzbeec6f10662010-02-09 11:16:15 -08001830 rlSrc = dvmCompilerUpdateLocWide(cUnit, rlSrc);
1831 rlSrc = dvmCompilerWideToNarrow(cUnit, rlSrc);
Bill Buzbee1465db52009-09-23 17:17:35 -07001832 // Intentional fallthrough
Ben Chengba4fc8b2009-06-01 13:00:29 -07001833 case OP_MOVE:
1834 case OP_MOVE_OBJECT:
Bill Buzbee1465db52009-09-23 17:17:35 -07001835 storeValue(cUnit, rlDest, rlSrc);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001836 break;
1837 case OP_INT_TO_BYTE:
Bill Buzbee1465db52009-09-23 17:17:35 -07001838 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001839 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001840 opRegReg(cUnit, kOp2Byte, rlResult.lowReg, rlSrc.lowReg);
1841 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001842 break;
1843 case OP_INT_TO_SHORT:
Bill Buzbee1465db52009-09-23 17:17:35 -07001844 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001845 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001846 opRegReg(cUnit, kOp2Short, rlResult.lowReg, rlSrc.lowReg);
1847 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001848 break;
1849 case OP_INT_TO_CHAR:
Bill Buzbee1465db52009-09-23 17:17:35 -07001850 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001851 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001852 opRegReg(cUnit, kOp2Char, rlResult.lowReg, rlSrc.lowReg);
1853 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001854 break;
1855 case OP_ARRAY_LENGTH: {
1856 int lenOffset = offsetof(ArrayObject, length);
Bill Buzbee1465db52009-09-23 17:17:35 -07001857 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
1858 genNullCheck(cUnit, rlSrc.sRegLow, rlSrc.lowReg,
1859 mir->offset, NULL);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001860 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001861 loadWordDisp(cUnit, rlSrc.lowReg, lenOffset,
1862 rlResult.lowReg);
1863 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001864 break;
1865 }
1866 default:
1867 return true;
1868 }
1869 return false;
1870}
1871
1872static bool handleFmt21s(CompilationUnit *cUnit, MIR *mir)
1873{
1874 OpCode dalvikOpCode = mir->dalvikInsn.opCode;
Bill Buzbee1465db52009-09-23 17:17:35 -07001875 RegLocation rlDest;
1876 RegLocation rlResult;
1877 int BBBB = mir->dalvikInsn.vB;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001878 if (dalvikOpCode == OP_CONST_WIDE_16) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001879 rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
1880 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001881 loadConstantValue(cUnit, rlResult.lowReg, BBBB);
Bill Buzbee964a7b02010-01-28 12:54:19 -08001882 //TUNING: do high separately to avoid load dependency
Bill Buzbee1465db52009-09-23 17:17:35 -07001883 opRegRegImm(cUnit, kOpAsr, rlResult.highReg, rlResult.lowReg, 31);
1884 storeValueWide(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001885 } else if (dalvikOpCode == OP_CONST_16) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001886 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
1887 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001888 loadConstantValue(cUnit, rlResult.lowReg, BBBB);
1889 storeValue(cUnit, rlDest, rlResult);
1890 } else
Ben Chengba4fc8b2009-06-01 13:00:29 -07001891 return true;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001892 return false;
1893}
1894
1895/* Compare agaist zero */
1896static bool handleFmt21t(CompilationUnit *cUnit, MIR *mir, BasicBlock *bb,
Bill Buzbee89efc3d2009-07-28 11:22:22 -07001897 ArmLIR *labelList)
Ben Chengba4fc8b2009-06-01 13:00:29 -07001898{
1899 OpCode dalvikOpCode = mir->dalvikInsn.opCode;
Bill Buzbee89efc3d2009-07-28 11:22:22 -07001900 ArmConditionCode cond;
Bill Buzbeec6f10662010-02-09 11:16:15 -08001901 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001902 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
1903 opRegImm(cUnit, kOpCmp, rlSrc.lowReg, 0);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001904
Bill Buzbee270c1d62009-08-13 16:58:07 -07001905//TUNING: break this out to allow use of Thumb2 CB[N]Z
Ben Chengba4fc8b2009-06-01 13:00:29 -07001906 switch (dalvikOpCode) {
1907 case OP_IF_EQZ:
Bill Buzbee1465db52009-09-23 17:17:35 -07001908 cond = kArmCondEq;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001909 break;
1910 case OP_IF_NEZ:
Bill Buzbee1465db52009-09-23 17:17:35 -07001911 cond = kArmCondNe;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001912 break;
1913 case OP_IF_LTZ:
Bill Buzbee1465db52009-09-23 17:17:35 -07001914 cond = kArmCondLt;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001915 break;
1916 case OP_IF_GEZ:
Bill Buzbee1465db52009-09-23 17:17:35 -07001917 cond = kArmCondGe;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001918 break;
1919 case OP_IF_GTZ:
Bill Buzbee1465db52009-09-23 17:17:35 -07001920 cond = kArmCondGt;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001921 break;
1922 case OP_IF_LEZ:
Bill Buzbee1465db52009-09-23 17:17:35 -07001923 cond = kArmCondLe;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001924 break;
1925 default:
1926 cond = 0;
1927 LOGE("Unexpected opcode (%d) for Fmt21t\n", dalvikOpCode);
Bill Buzbeefc519dc2010-03-06 23:30:57 -08001928 dvmCompilerAbort(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001929 }
1930 genConditionalBranch(cUnit, cond, &labelList[bb->taken->id]);
1931 /* This mostly likely will be optimized away in a later phase */
1932 genUnconditionalBranch(cUnit, &labelList[bb->fallThrough->id]);
1933 return false;
1934}
1935
Elliott Hughesb4c05972010-02-24 16:36:18 -08001936static bool isPowerOfTwo(int x)
1937{
1938 return (x & (x - 1)) == 0;
1939}
1940
1941// Returns true if no more than two bits are set in 'x'.
1942static bool isPopCountLE2(unsigned int x)
1943{
1944 x &= x - 1;
1945 return (x & (x - 1)) == 0;
1946}
1947
1948// Returns the index of the lowest set bit in 'x'.
1949static int lowestSetBit(unsigned int x) {
1950 int bit_posn = 0;
1951 while ((x & 0xf) == 0) {
1952 bit_posn += 4;
1953 x >>= 4;
Bill Buzbee78cb0e22010-02-11 14:04:53 -08001954 }
Elliott Hughesb4c05972010-02-24 16:36:18 -08001955 while ((x & 1) == 0) {
1956 bit_posn++;
1957 x >>= 1;
1958 }
1959 return bit_posn;
1960}
1961
1962// Returns true if it added instructions to 'cUnit' to multiply 'rlSrc' by 'lit'
1963// and store the result in 'rlDest'.
1964static bool handleEasyMultiply(CompilationUnit *cUnit,
1965 RegLocation rlSrc, RegLocation rlDest, int lit)
1966{
1967 // Can we simplify this multiplication?
1968 bool powerOfTwo = false;
1969 bool popCountLE2 = false;
1970 bool powerOfTwoMinusOne = false;
1971 if (lit < 2) {
1972 // Avoid special cases.
1973 return false;
1974 } else if (isPowerOfTwo(lit)) {
1975 powerOfTwo = true;
1976 } else if (isPopCountLE2(lit)) {
1977 popCountLE2 = true;
1978 } else if (isPowerOfTwo(lit + 1)) {
1979 powerOfTwoMinusOne = true;
1980 } else {
1981 return false;
1982 }
1983 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
1984 RegLocation rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
1985 if (powerOfTwo) {
1986 // Shift.
1987 opRegRegImm(cUnit, kOpLsl, rlResult.lowReg, rlSrc.lowReg,
1988 lowestSetBit(lit));
1989 } else if (popCountLE2) {
1990 // Shift and add and shift.
1991 int firstBit = lowestSetBit(lit);
1992 int secondBit = lowestSetBit(lit ^ (1 << firstBit));
1993 genMultiplyByTwoBitMultiplier(cUnit, rlSrc, rlResult, lit,
1994 firstBit, secondBit);
1995 } else {
1996 // Reverse subtract: (src << (shift + 1)) - src.
1997 assert(powerOfTwoMinusOne);
1998 // TODO: rsb dst, src, src lsl#lowestSetBit(lit + 1)
1999 int tReg = dvmCompilerAllocTemp(cUnit);
2000 opRegRegImm(cUnit, kOpLsl, tReg, rlSrc.lowReg, lowestSetBit(lit + 1));
2001 opRegRegReg(cUnit, kOpSub, rlResult.lowReg, tReg, rlSrc.lowReg);
2002 }
2003 storeValue(cUnit, rlDest, rlResult);
2004 return true;
Bill Buzbee78cb0e22010-02-11 14:04:53 -08002005}
2006
Ben Chengba4fc8b2009-06-01 13:00:29 -07002007static bool handleFmt22b_Fmt22s(CompilationUnit *cUnit, MIR *mir)
2008{
2009 OpCode dalvikOpCode = mir->dalvikInsn.opCode;
Bill Buzbeec6f10662010-02-09 11:16:15 -08002010 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
2011 RegLocation rlDest = dvmCompilerGetDest(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07002012 RegLocation rlResult;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002013 int lit = mir->dalvikInsn.vC;
Ben Cheng4f489172009-09-27 17:08:35 -07002014 OpKind op = 0; /* Make gcc happy */
Bill Buzbee1465db52009-09-23 17:17:35 -07002015 int shiftOp = false;
2016 bool isDiv = false;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002017
Ben Chengba4fc8b2009-06-01 13:00:29 -07002018 int __aeabi_idivmod(int op1, int op2);
2019 int __aeabi_idiv(int op1, int op2);
2020
2021 switch (dalvikOpCode) {
Bill Buzbee1465db52009-09-23 17:17:35 -07002022 case OP_RSUB_INT_LIT8:
2023 case OP_RSUB_INT: {
2024 int tReg;
2025 //TUNING: add support for use of Arm rsub op
2026 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -08002027 tReg = dvmCompilerAllocTemp(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07002028 loadConstant(cUnit, tReg, lit);
Bill Buzbeec6f10662010-02-09 11:16:15 -08002029 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07002030 opRegRegReg(cUnit, kOpSub, rlResult.lowReg,
2031 tReg, rlSrc.lowReg);
2032 storeValue(cUnit, rlDest, rlResult);
2033 return false;
2034 break;
2035 }
2036
Ben Chengba4fc8b2009-06-01 13:00:29 -07002037 case OP_ADD_INT_LIT8:
2038 case OP_ADD_INT_LIT16:
Bill Buzbee1465db52009-09-23 17:17:35 -07002039 op = kOpAdd;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002040 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002041 case OP_MUL_INT_LIT8:
Bill Buzbee78cb0e22010-02-11 14:04:53 -08002042 case OP_MUL_INT_LIT16: {
Elliott Hughesb4c05972010-02-24 16:36:18 -08002043 if (handleEasyMultiply(cUnit, rlSrc, rlDest, lit)) {
2044 return false;
Bill Buzbee78cb0e22010-02-11 14:04:53 -08002045 }
Elliott Hughesb4c05972010-02-24 16:36:18 -08002046 op = kOpMul;
Bill Buzbee1465db52009-09-23 17:17:35 -07002047 break;
Bill Buzbee78cb0e22010-02-11 14:04:53 -08002048 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07002049 case OP_AND_INT_LIT8:
2050 case OP_AND_INT_LIT16:
Bill Buzbee1465db52009-09-23 17:17:35 -07002051 op = kOpAnd;
2052 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002053 case OP_OR_INT_LIT8:
2054 case OP_OR_INT_LIT16:
Bill Buzbee1465db52009-09-23 17:17:35 -07002055 op = kOpOr;
2056 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002057 case OP_XOR_INT_LIT8:
2058 case OP_XOR_INT_LIT16:
Bill Buzbee1465db52009-09-23 17:17:35 -07002059 op = kOpXor;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002060 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002061 case OP_SHL_INT_LIT8:
Bill Buzbee0e605272009-12-01 14:28:05 -08002062 lit &= 31;
Bill Buzbee1465db52009-09-23 17:17:35 -07002063 shiftOp = true;
2064 op = kOpLsl;
2065 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002066 case OP_SHR_INT_LIT8:
Bill Buzbee0e605272009-12-01 14:28:05 -08002067 lit &= 31;
Bill Buzbee1465db52009-09-23 17:17:35 -07002068 shiftOp = true;
2069 op = kOpAsr;
2070 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002071 case OP_USHR_INT_LIT8:
Bill Buzbee0e605272009-12-01 14:28:05 -08002072 lit &= 31;
Bill Buzbee1465db52009-09-23 17:17:35 -07002073 shiftOp = true;
2074 op = kOpLsr;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002075 break;
2076
2077 case OP_DIV_INT_LIT8:
2078 case OP_DIV_INT_LIT16:
Ben Chengba4fc8b2009-06-01 13:00:29 -07002079 case OP_REM_INT_LIT8:
2080 case OP_REM_INT_LIT16:
2081 if (lit == 0) {
2082 /* Let the interpreter deal with div by 0 */
2083 genInterpSingleStep(cUnit, mir);
2084 return false;
2085 }
Bill Buzbeec6f10662010-02-09 11:16:15 -08002086 dvmCompilerFlushAllRegs(cUnit); /* Everything to home location */
Bill Buzbee1465db52009-09-23 17:17:35 -07002087 loadValueDirectFixed(cUnit, rlSrc, r0);
Bill Buzbeec6f10662010-02-09 11:16:15 -08002088 dvmCompilerClobber(cUnit, r0);
Bill Buzbee1465db52009-09-23 17:17:35 -07002089 if ((dalvikOpCode == OP_DIV_INT_LIT8) ||
2090 (dalvikOpCode == OP_DIV_INT_LIT16)) {
2091 loadConstant(cUnit, r2, (int)__aeabi_idiv);
2092 isDiv = true;
2093 } else {
2094 loadConstant(cUnit, r2, (int)__aeabi_idivmod);
2095 isDiv = false;
2096 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07002097 loadConstant(cUnit, r1, lit);
Bill Buzbee1465db52009-09-23 17:17:35 -07002098 opReg(cUnit, kOpBlx, r2);
Elliott Hughes6a555132010-02-25 15:41:42 -08002099 dvmCompilerClobberCallRegs(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07002100 if (isDiv)
Bill Buzbeec6f10662010-02-09 11:16:15 -08002101 rlResult = dvmCompilerGetReturn(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07002102 else
Bill Buzbeec6f10662010-02-09 11:16:15 -08002103 rlResult = dvmCompilerGetReturnAlt(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07002104 storeValue(cUnit, rlDest, rlResult);
2105 return false;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002106 break;
2107 default:
2108 return true;
2109 }
Bill Buzbee1465db52009-09-23 17:17:35 -07002110 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -08002111 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07002112 // Avoid shifts by literal 0 - no support in Thumb. Change to copy
2113 if (shiftOp && (lit == 0)) {
2114 genRegCopy(cUnit, rlResult.lowReg, rlSrc.lowReg);
2115 } else {
2116 opRegRegImm(cUnit, op, rlResult.lowReg, rlSrc.lowReg, lit);
2117 }
2118 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002119 return false;
2120}
2121
2122static bool handleFmt22c(CompilationUnit *cUnit, MIR *mir)
2123{
2124 OpCode dalvikOpCode = mir->dalvikInsn.opCode;
2125 int fieldOffset;
2126
2127 if (dalvikOpCode >= OP_IGET && dalvikOpCode <= OP_IPUT_SHORT) {
2128 InstField *pInstField = (InstField *)
2129 cUnit->method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vC];
Ben Chengba4fc8b2009-06-01 13:00:29 -07002130
2131 assert(pInstField != NULL);
2132 fieldOffset = pInstField->byteOffset;
2133 } else {
Ben Chenga0e7b602009-10-13 23:09:01 -07002134 /* Deliberately break the code while make the compiler happy */
2135 fieldOffset = -1;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002136 }
2137 switch (dalvikOpCode) {
Ben Chengba4fc8b2009-06-01 13:00:29 -07002138 case OP_NEW_ARRAY: {
Bill Buzbee1465db52009-09-23 17:17:35 -07002139 // Generates a call - use explicit registers
Bill Buzbeec6f10662010-02-09 11:16:15 -08002140 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
2141 RegLocation rlDest = dvmCompilerGetDest(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07002142 RegLocation rlResult;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002143 void *classPtr = (void*)
2144 (cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vC]);
2145 assert(classPtr != NULL);
Bill Buzbeec6f10662010-02-09 11:16:15 -08002146 dvmCompilerFlushAllRegs(cUnit); /* Everything to home location */
Bill Buzbee1465db52009-09-23 17:17:35 -07002147 genExportPC(cUnit, mir);
2148 loadValueDirectFixed(cUnit, rlSrc, r1); /* Len */
Ben Chengba4fc8b2009-06-01 13:00:29 -07002149 loadConstant(cUnit, r0, (int) classPtr );
Bill Buzbee1465db52009-09-23 17:17:35 -07002150 loadConstant(cUnit, r3, (int)dvmAllocArrayByClass);
Ben Cheng4f489172009-09-27 17:08:35 -07002151 /*
2152 * "len < 0": bail to the interpreter to re-execute the
2153 * instruction
2154 */
Bill Buzbee89efc3d2009-07-28 11:22:22 -07002155 ArmLIR *pcrLabel =
Bill Buzbee1465db52009-09-23 17:17:35 -07002156 genRegImmCheck(cUnit, kArmCondMi, r1, 0, mir->offset, NULL);
Bill Buzbee270c1d62009-08-13 16:58:07 -07002157 loadConstant(cUnit, r2, ALLOC_DONT_TRACK);
Bill Buzbee1465db52009-09-23 17:17:35 -07002158 opReg(cUnit, kOpBlx, r3);
Elliott Hughes6a555132010-02-25 15:41:42 -08002159 dvmCompilerClobberCallRegs(cUnit);
Ben Cheng4f489172009-09-27 17:08:35 -07002160 /* generate a branch over if allocation is successful */
Bill Buzbee1465db52009-09-23 17:17:35 -07002161 opRegImm(cUnit, kOpCmp, r0, 0); /* NULL? */
2162 ArmLIR *branchOver = opCondBranch(cUnit, kArmCondNe);
Ben Cheng4f489172009-09-27 17:08:35 -07002163 /*
2164 * OOM exception needs to be thrown here and cannot re-execute
2165 */
2166 loadConstant(cUnit, r0,
2167 (int) (cUnit->method->insns + mir->offset));
2168 genDispatchToHandler(cUnit, TEMPLATE_THROW_EXCEPTION_COMMON);
2169 /* noreturn */
2170
Bill Buzbee1465db52009-09-23 17:17:35 -07002171 ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel);
Ben Cheng4f489172009-09-27 17:08:35 -07002172 target->defMask = ENCODE_ALL;
2173 branchOver->generic.target = (LIR *) target;
Bill Buzbeec6f10662010-02-09 11:16:15 -08002174 rlResult = dvmCompilerGetReturn(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07002175 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002176 break;
2177 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07002178 case OP_INSTANCE_OF: {
Bill Buzbee1465db52009-09-23 17:17:35 -07002179 // May generate a call - use explicit registers
Bill Buzbeec6f10662010-02-09 11:16:15 -08002180 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
2181 RegLocation rlDest = dvmCompilerGetDest(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07002182 RegLocation rlResult;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002183 ClassObject *classPtr =
2184 (cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vC]);
Bill Buzbee480e6782010-01-27 15:43:08 -08002185 /*
2186 * Note: It is possible that classPtr is NULL at this point,
2187 * even though this instruction has been successfully interpreted.
2188 * If the previous interpretation had a null source, the
2189 * interpreter would not have bothered to resolve the clazz.
2190 * Bail out to the interpreter in this case, and log it
2191 * so that we can tell if it happens frequently.
2192 */
2193 if (classPtr == NULL) {
2194 LOGD("null clazz in OP_INSTANCE_OF, single-stepping");
2195 genInterpSingleStep(cUnit, mir);
2196 break;
2197 }
Bill Buzbeec6f10662010-02-09 11:16:15 -08002198 dvmCompilerFlushAllRegs(cUnit); /* Everything to home location */
Bill Buzbee1465db52009-09-23 17:17:35 -07002199 loadValueDirectFixed(cUnit, rlSrc, r0); /* Ref */
Ben Chengba4fc8b2009-06-01 13:00:29 -07002200 loadConstant(cUnit, r2, (int) classPtr );
Bill Buzbee270c1d62009-08-13 16:58:07 -07002201//TUNING: compare to 0 primative to allow use of CB[N]Z
Bill Buzbee1465db52009-09-23 17:17:35 -07002202 opRegImm(cUnit, kOpCmp, r0, 0); /* NULL? */
Ben Cheng752c7942009-06-22 10:50:07 -07002203 /* When taken r0 has NULL which can be used for store directly */
Bill Buzbee1465db52009-09-23 17:17:35 -07002204 ArmLIR *branch1 = opCondBranch(cUnit, kArmCondEq);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002205 /* r1 now contains object->clazz */
Bill Buzbee270c1d62009-08-13 16:58:07 -07002206 loadWordDisp(cUnit, r0, offsetof(Object, clazz), r1);
Bill Buzbee1465db52009-09-23 17:17:35 -07002207 /* r1 now contains object->clazz */
2208 loadConstant(cUnit, r3, (int)dvmInstanceofNonTrivial);
Ben Cheng752c7942009-06-22 10:50:07 -07002209 loadConstant(cUnit, r0, 1); /* Assume true */
Bill Buzbee1465db52009-09-23 17:17:35 -07002210 opRegReg(cUnit, kOpCmp, r1, r2);
2211 ArmLIR *branch2 = opCondBranch(cUnit, kArmCondEq);
2212 genRegCopy(cUnit, r0, r1);
2213 genRegCopy(cUnit, r1, r2);
2214 opReg(cUnit, kOpBlx, r3);
Elliott Hughes6a555132010-02-25 15:41:42 -08002215 dvmCompilerClobberCallRegs(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002216 /* branch target here */
Bill Buzbee1465db52009-09-23 17:17:35 -07002217 ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel);
Ben Chengd7d426a2009-09-22 11:23:36 -07002218 target->defMask = ENCODE_ALL;
Bill Buzbeec6f10662010-02-09 11:16:15 -08002219 rlResult = dvmCompilerGetReturn(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07002220 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002221 branch1->generic.target = (LIR *)target;
2222 branch2->generic.target = (LIR *)target;
2223 break;
2224 }
2225 case OP_IGET_WIDE:
2226 genIGetWide(cUnit, mir, fieldOffset);
2227 break;
2228 case OP_IGET:
2229 case OP_IGET_OBJECT:
Bill Buzbee1465db52009-09-23 17:17:35 -07002230 genIGet(cUnit, mir, kWord, fieldOffset);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002231 break;
2232 case OP_IGET_BOOLEAN:
Bill Buzbee1465db52009-09-23 17:17:35 -07002233 genIGet(cUnit, mir, kUnsignedByte, fieldOffset);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002234 break;
2235 case OP_IGET_BYTE:
Bill Buzbee1465db52009-09-23 17:17:35 -07002236 genIGet(cUnit, mir, kSignedByte, fieldOffset);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002237 break;
2238 case OP_IGET_CHAR:
Bill Buzbee1465db52009-09-23 17:17:35 -07002239 genIGet(cUnit, mir, kUnsignedHalf, fieldOffset);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002240 break;
2241 case OP_IGET_SHORT:
Bill Buzbee1465db52009-09-23 17:17:35 -07002242 genIGet(cUnit, mir, kSignedHalf, fieldOffset);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002243 break;
2244 case OP_IPUT_WIDE:
2245 genIPutWide(cUnit, mir, fieldOffset);
2246 break;
2247 case OP_IPUT:
2248 case OP_IPUT_OBJECT:
Bill Buzbee1465db52009-09-23 17:17:35 -07002249 genIPut(cUnit, mir, kWord, fieldOffset);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002250 break;
2251 case OP_IPUT_SHORT:
2252 case OP_IPUT_CHAR:
Bill Buzbee1465db52009-09-23 17:17:35 -07002253 genIPut(cUnit, mir, kUnsignedHalf, fieldOffset);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002254 break;
2255 case OP_IPUT_BYTE:
2256 case OP_IPUT_BOOLEAN:
Bill Buzbee1465db52009-09-23 17:17:35 -07002257 genIPut(cUnit, mir, kUnsignedByte, fieldOffset);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002258 break;
2259 default:
2260 return true;
2261 }
2262 return false;
2263}
2264
2265static bool handleFmt22cs(CompilationUnit *cUnit, MIR *mir)
2266{
2267 OpCode dalvikOpCode = mir->dalvikInsn.opCode;
2268 int fieldOffset = mir->dalvikInsn.vC;
2269 switch (dalvikOpCode) {
2270 case OP_IGET_QUICK:
2271 case OP_IGET_OBJECT_QUICK:
Bill Buzbee1465db52009-09-23 17:17:35 -07002272 genIGet(cUnit, mir, kWord, fieldOffset);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002273 break;
2274 case OP_IPUT_QUICK:
2275 case OP_IPUT_OBJECT_QUICK:
Bill Buzbee1465db52009-09-23 17:17:35 -07002276 genIPut(cUnit, mir, kWord, fieldOffset);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002277 break;
2278 case OP_IGET_WIDE_QUICK:
2279 genIGetWide(cUnit, mir, fieldOffset);
2280 break;
2281 case OP_IPUT_WIDE_QUICK:
2282 genIPutWide(cUnit, mir, fieldOffset);
2283 break;
2284 default:
2285 return true;
2286 }
2287 return false;
2288
2289}
2290
2291/* Compare agaist zero */
2292static bool handleFmt22t(CompilationUnit *cUnit, MIR *mir, BasicBlock *bb,
Bill Buzbee89efc3d2009-07-28 11:22:22 -07002293 ArmLIR *labelList)
Ben Chengba4fc8b2009-06-01 13:00:29 -07002294{
2295 OpCode dalvikOpCode = mir->dalvikInsn.opCode;
Bill Buzbee89efc3d2009-07-28 11:22:22 -07002296 ArmConditionCode cond;
Bill Buzbeec6f10662010-02-09 11:16:15 -08002297 RegLocation rlSrc1 = dvmCompilerGetSrc(cUnit, mir, 0);
2298 RegLocation rlSrc2 = dvmCompilerGetSrc(cUnit, mir, 1);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002299
Bill Buzbee1465db52009-09-23 17:17:35 -07002300 rlSrc1 = loadValue(cUnit, rlSrc1, kCoreReg);
2301 rlSrc2 = loadValue(cUnit, rlSrc2, kCoreReg);
2302 opRegReg(cUnit, kOpCmp, rlSrc1.lowReg, rlSrc2.lowReg);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002303
2304 switch (dalvikOpCode) {
2305 case OP_IF_EQ:
Bill Buzbee1465db52009-09-23 17:17:35 -07002306 cond = kArmCondEq;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002307 break;
2308 case OP_IF_NE:
Bill Buzbee1465db52009-09-23 17:17:35 -07002309 cond = kArmCondNe;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002310 break;
2311 case OP_IF_LT:
Bill Buzbee1465db52009-09-23 17:17:35 -07002312 cond = kArmCondLt;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002313 break;
2314 case OP_IF_GE:
Bill Buzbee1465db52009-09-23 17:17:35 -07002315 cond = kArmCondGe;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002316 break;
2317 case OP_IF_GT:
Bill Buzbee1465db52009-09-23 17:17:35 -07002318 cond = kArmCondGt;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002319 break;
2320 case OP_IF_LE:
Bill Buzbee1465db52009-09-23 17:17:35 -07002321 cond = kArmCondLe;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002322 break;
2323 default:
2324 cond = 0;
2325 LOGE("Unexpected opcode (%d) for Fmt22t\n", dalvikOpCode);
Bill Buzbeefc519dc2010-03-06 23:30:57 -08002326 dvmCompilerAbort(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002327 }
2328 genConditionalBranch(cUnit, cond, &labelList[bb->taken->id]);
2329 /* This mostly likely will be optimized away in a later phase */
2330 genUnconditionalBranch(cUnit, &labelList[bb->fallThrough->id]);
2331 return false;
2332}
2333
2334static bool handleFmt22x_Fmt32x(CompilationUnit *cUnit, MIR *mir)
2335{
2336 OpCode opCode = mir->dalvikInsn.opCode;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002337
2338 switch (opCode) {
2339 case OP_MOVE_16:
2340 case OP_MOVE_OBJECT_16:
2341 case OP_MOVE_FROM16:
Ben Chenge9695e52009-06-16 16:11:47 -07002342 case OP_MOVE_OBJECT_FROM16: {
Bill Buzbeec6f10662010-02-09 11:16:15 -08002343 storeValue(cUnit, dvmCompilerGetDest(cUnit, mir, 0),
2344 dvmCompilerGetSrc(cUnit, mir, 0));
Ben Chengba4fc8b2009-06-01 13:00:29 -07002345 break;
Ben Chenge9695e52009-06-16 16:11:47 -07002346 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07002347 case OP_MOVE_WIDE_16:
Ben Chenge9695e52009-06-16 16:11:47 -07002348 case OP_MOVE_WIDE_FROM16: {
Bill Buzbeec6f10662010-02-09 11:16:15 -08002349 storeValueWide(cUnit, dvmCompilerGetDestWide(cUnit, mir, 0, 1),
2350 dvmCompilerGetSrcWide(cUnit, mir, 0, 1));
Ben Chengba4fc8b2009-06-01 13:00:29 -07002351 break;
Ben Chenge9695e52009-06-16 16:11:47 -07002352 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07002353 default:
2354 return true;
2355 }
2356 return false;
2357}
2358
2359static bool handleFmt23x(CompilationUnit *cUnit, MIR *mir)
2360{
2361 OpCode opCode = mir->dalvikInsn.opCode;
Bill Buzbee1465db52009-09-23 17:17:35 -07002362 RegLocation rlSrc1;
2363 RegLocation rlSrc2;
2364 RegLocation rlDest;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002365
2366 if ( (opCode >= OP_ADD_INT) && (opCode <= OP_REM_DOUBLE)) {
Ben Cheng5d90c202009-11-22 23:31:11 -08002367 return genArithOp( cUnit, mir );
Ben Chengba4fc8b2009-06-01 13:00:29 -07002368 }
2369
Bill Buzbee1465db52009-09-23 17:17:35 -07002370 /* APUTs have 3 sources and no targets */
2371 if (mir->ssaRep->numDefs == 0) {
2372 if (mir->ssaRep->numUses == 3) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08002373 rlDest = dvmCompilerGetSrc(cUnit, mir, 0);
2374 rlSrc1 = dvmCompilerGetSrc(cUnit, mir, 1);
2375 rlSrc2 = dvmCompilerGetSrc(cUnit, mir, 2);
Bill Buzbee1465db52009-09-23 17:17:35 -07002376 } else {
2377 assert(mir->ssaRep->numUses == 4);
Bill Buzbeec6f10662010-02-09 11:16:15 -08002378 rlDest = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
2379 rlSrc1 = dvmCompilerGetSrc(cUnit, mir, 2);
2380 rlSrc2 = dvmCompilerGetSrc(cUnit, mir, 3);
Bill Buzbee1465db52009-09-23 17:17:35 -07002381 }
2382 } else {
2383 /* Two sources and 1 dest. Deduce the operand sizes */
2384 if (mir->ssaRep->numUses == 4) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08002385 rlSrc1 = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
2386 rlSrc2 = dvmCompilerGetSrcWide(cUnit, mir, 2, 3);
Bill Buzbee1465db52009-09-23 17:17:35 -07002387 } else {
2388 assert(mir->ssaRep->numUses == 2);
Bill Buzbeec6f10662010-02-09 11:16:15 -08002389 rlSrc1 = dvmCompilerGetSrc(cUnit, mir, 0);
2390 rlSrc2 = dvmCompilerGetSrc(cUnit, mir, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -07002391 }
2392 if (mir->ssaRep->numDefs == 2) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08002393 rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -07002394 } else {
2395 assert(mir->ssaRep->numDefs == 1);
Bill Buzbeec6f10662010-02-09 11:16:15 -08002396 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07002397 }
2398 }
2399
2400
Ben Chengba4fc8b2009-06-01 13:00:29 -07002401 switch (opCode) {
Bill Buzbeed45ba372009-06-15 17:00:57 -07002402 case OP_CMPL_FLOAT:
2403 case OP_CMPG_FLOAT:
2404 case OP_CMPL_DOUBLE:
2405 case OP_CMPG_DOUBLE:
Ben Cheng5d90c202009-11-22 23:31:11 -08002406 return genCmpFP(cUnit, mir, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002407 case OP_CMP_LONG:
Bill Buzbee1465db52009-09-23 17:17:35 -07002408 genCmpLong(cUnit, mir, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002409 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002410 case OP_AGET_WIDE:
Bill Buzbee1465db52009-09-23 17:17:35 -07002411 genArrayGet(cUnit, mir, kLong, rlSrc1, rlSrc2, rlDest, 3);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002412 break;
2413 case OP_AGET:
2414 case OP_AGET_OBJECT:
Bill Buzbee1465db52009-09-23 17:17:35 -07002415 genArrayGet(cUnit, mir, kWord, rlSrc1, rlSrc2, rlDest, 2);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002416 break;
2417 case OP_AGET_BOOLEAN:
Bill Buzbee1465db52009-09-23 17:17:35 -07002418 genArrayGet(cUnit, mir, kUnsignedByte, rlSrc1, rlSrc2, rlDest, 0);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002419 break;
2420 case OP_AGET_BYTE:
Bill Buzbee1465db52009-09-23 17:17:35 -07002421 genArrayGet(cUnit, mir, kSignedByte, rlSrc1, rlSrc2, rlDest, 0);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002422 break;
2423 case OP_AGET_CHAR:
Bill Buzbee1465db52009-09-23 17:17:35 -07002424 genArrayGet(cUnit, mir, kUnsignedHalf, rlSrc1, rlSrc2, rlDest, 1);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002425 break;
2426 case OP_AGET_SHORT:
Bill Buzbee1465db52009-09-23 17:17:35 -07002427 genArrayGet(cUnit, mir, kSignedHalf, rlSrc1, rlSrc2, rlDest, 1);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002428 break;
2429 case OP_APUT_WIDE:
Bill Buzbee1465db52009-09-23 17:17:35 -07002430 genArrayPut(cUnit, mir, kLong, rlSrc1, rlSrc2, rlDest, 3);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002431 break;
2432 case OP_APUT:
Bill Buzbee1465db52009-09-23 17:17:35 -07002433 genArrayPut(cUnit, mir, kWord, rlSrc1, rlSrc2, rlDest, 2);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002434 break;
Bill Buzbeebe6534f2010-03-12 16:01:35 -08002435 case OP_APUT_OBJECT:
2436 genArrayObjectPut(cUnit, mir, rlSrc1, rlSrc2, rlDest, 2);
2437 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002438 case OP_APUT_SHORT:
2439 case OP_APUT_CHAR:
Bill Buzbee1465db52009-09-23 17:17:35 -07002440 genArrayPut(cUnit, mir, kUnsignedHalf, rlSrc1, rlSrc2, rlDest, 1);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002441 break;
2442 case OP_APUT_BYTE:
2443 case OP_APUT_BOOLEAN:
Bill Buzbee1465db52009-09-23 17:17:35 -07002444 genArrayPut(cUnit, mir, kUnsignedByte, rlSrc1, rlSrc2, rlDest, 0);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002445 break;
2446 default:
2447 return true;
2448 }
2449 return false;
2450}
2451
Ben Cheng6c10a972009-10-29 14:39:18 -07002452/*
2453 * Find the matching case.
2454 *
2455 * return values:
2456 * r0 (low 32-bit): pc of the chaining cell corresponding to the resolved case,
2457 * including default which is placed at MIN(size, MAX_CHAINED_SWITCH_CASES).
2458 * r1 (high 32-bit): the branch offset of the matching case (only for indexes
2459 * above MAX_CHAINED_SWITCH_CASES).
2460 *
2461 * Instructions around the call are:
2462 *
2463 * mov r2, pc
2464 * blx &findPackedSwitchIndex
2465 * mov pc, r0
2466 * .align4
2467 * chaining cell for case 0 [8 bytes]
2468 * chaining cell for case 1 [8 bytes]
2469 * :
2470 * chaining cell for case MIN(size, MAX_CHAINED_SWITCH_CASES)-1 [8 bytes]
2471 * chaining cell for case default [8 bytes]
2472 * noChain exit
2473 */
2474s8 findPackedSwitchIndex(const u2* switchData, int testVal, int pc)
2475{
2476 int size;
2477 int firstKey;
2478 const int *entries;
2479 int index;
2480 int jumpIndex;
2481 int caseDPCOffset = 0;
2482 /* In Thumb mode pc is 4 ahead of the "mov r2, pc" instruction */
2483 int chainingPC = (pc + 4) & ~3;
2484
2485 /*
2486 * Packed switch data format:
2487 * ushort ident = 0x0100 magic value
2488 * ushort size number of entries in the table
2489 * int first_key first (and lowest) switch case value
2490 * int targets[size] branch targets, relative to switch opcode
2491 *
2492 * Total size is (4+size*2) 16-bit code units.
2493 */
2494 size = switchData[1];
2495 assert(size > 0);
2496
2497 firstKey = switchData[2];
2498 firstKey |= switchData[3] << 16;
2499
2500
2501 /* The entries are guaranteed to be aligned on a 32-bit boundary;
2502 * we can treat them as a native int array.
2503 */
2504 entries = (const int*) &switchData[4];
2505 assert(((u4)entries & 0x3) == 0);
2506
2507 index = testVal - firstKey;
2508
2509 /* Jump to the default cell */
2510 if (index < 0 || index >= size) {
2511 jumpIndex = MIN(size, MAX_CHAINED_SWITCH_CASES);
2512 /* Jump to the non-chaining exit point */
2513 } else if (index >= MAX_CHAINED_SWITCH_CASES) {
2514 jumpIndex = MAX_CHAINED_SWITCH_CASES + 1;
2515 caseDPCOffset = entries[index];
2516 /* Jump to the inline chaining cell */
2517 } else {
2518 jumpIndex = index;
2519 }
2520
2521 chainingPC += jumpIndex * 8;
2522 return (((s8) caseDPCOffset) << 32) | (u8) chainingPC;
2523}
2524
2525/* See comments for findPackedSwitchIndex */
2526s8 findSparseSwitchIndex(const u2* switchData, int testVal, int pc)
2527{
2528 int size;
2529 const int *keys;
2530 const int *entries;
2531 int chainingPC = (pc + 4) & ~3;
2532 int i;
2533
2534 /*
2535 * Sparse switch data format:
2536 * ushort ident = 0x0200 magic value
2537 * ushort size number of entries in the table; > 0
2538 * int keys[size] keys, sorted low-to-high; 32-bit aligned
2539 * int targets[size] branch targets, relative to switch opcode
2540 *
2541 * Total size is (2+size*4) 16-bit code units.
2542 */
2543
2544 size = switchData[1];
2545 assert(size > 0);
2546
2547 /* The keys are guaranteed to be aligned on a 32-bit boundary;
2548 * we can treat them as a native int array.
2549 */
2550 keys = (const int*) &switchData[2];
2551 assert(((u4)keys & 0x3) == 0);
2552
2553 /* The entries are guaranteed to be aligned on a 32-bit boundary;
2554 * we can treat them as a native int array.
2555 */
2556 entries = keys + size;
2557 assert(((u4)entries & 0x3) == 0);
2558
2559 /*
2560 * Run through the list of keys, which are guaranteed to
2561 * be sorted low-to-high.
2562 *
2563 * Most tables have 3-4 entries. Few have more than 10. A binary
2564 * search here is probably not useful.
2565 */
2566 for (i = 0; i < size; i++) {
2567 int k = keys[i];
2568 if (k == testVal) {
2569 /* MAX_CHAINED_SWITCH_CASES + 1 is the start of the overflow case */
2570 int jumpIndex = (i < MAX_CHAINED_SWITCH_CASES) ?
2571 i : MAX_CHAINED_SWITCH_CASES + 1;
2572 chainingPC += jumpIndex * 8;
2573 return (((s8) entries[i]) << 32) | (u8) chainingPC;
2574 } else if (k > testVal) {
2575 break;
2576 }
2577 }
2578 return chainingPC + MIN(size, MAX_CHAINED_SWITCH_CASES) * 8;
2579}
2580
Ben Chengba4fc8b2009-06-01 13:00:29 -07002581static bool handleFmt31t(CompilationUnit *cUnit, MIR *mir)
2582{
2583 OpCode dalvikOpCode = mir->dalvikInsn.opCode;
2584 switch (dalvikOpCode) {
2585 case OP_FILL_ARRAY_DATA: {
Bill Buzbeec6f10662010-02-09 11:16:15 -08002586 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07002587 // Making a call - use explicit registers
Bill Buzbeec6f10662010-02-09 11:16:15 -08002588 dvmCompilerFlushAllRegs(cUnit); /* Everything to home location */
Bill Buzbee1465db52009-09-23 17:17:35 -07002589 genExportPC(cUnit, mir);
2590 loadValueDirectFixed(cUnit, rlSrc, r0);
Bill Buzbeefd023aa2009-11-02 09:23:49 -08002591 loadConstant(cUnit, r2, (int)dvmInterpHandleFillArrayData);
Ben Cheng6c10a972009-10-29 14:39:18 -07002592 loadConstant(cUnit, r1,
2593 (int) (cUnit->method->insns + mir->offset + mir->dalvikInsn.vB));
Bill Buzbee1465db52009-09-23 17:17:35 -07002594 opReg(cUnit, kOpBlx, r2);
Elliott Hughes6a555132010-02-25 15:41:42 -08002595 dvmCompilerClobberCallRegs(cUnit);
Bill Buzbeefd023aa2009-11-02 09:23:49 -08002596 /* generate a branch over if successful */
2597 opRegImm(cUnit, kOpCmp, r0, 0); /* NULL? */
2598 ArmLIR *branchOver = opCondBranch(cUnit, kArmCondNe);
2599 loadConstant(cUnit, r0,
2600 (int) (cUnit->method->insns + mir->offset));
2601 genDispatchToHandler(cUnit, TEMPLATE_THROW_EXCEPTION_COMMON);
2602 ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel);
2603 target->defMask = ENCODE_ALL;
2604 branchOver->generic.target = (LIR *) target;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002605 break;
2606 }
2607 /*
Ben Cheng6c10a972009-10-29 14:39:18 -07002608 * Compute the goto target of up to
2609 * MIN(switchSize, MAX_CHAINED_SWITCH_CASES) + 1 chaining cells.
2610 * See the comment before findPackedSwitchIndex for the code layout.
Ben Chengba4fc8b2009-06-01 13:00:29 -07002611 */
2612 case OP_PACKED_SWITCH:
2613 case OP_SPARSE_SWITCH: {
Bill Buzbeec6f10662010-02-09 11:16:15 -08002614 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
2615 dvmCompilerFlushAllRegs(cUnit); /* Everything to home location */
Bill Buzbee1465db52009-09-23 17:17:35 -07002616 loadValueDirectFixed(cUnit, rlSrc, r1);
Bill Buzbeec6f10662010-02-09 11:16:15 -08002617 dvmCompilerLockAllTemps(cUnit);
Ben Cheng6c10a972009-10-29 14:39:18 -07002618 const u2 *switchData =
2619 cUnit->method->insns + mir->offset + mir->dalvikInsn.vB;
2620 u2 size = switchData[1];
2621
Ben Chengba4fc8b2009-06-01 13:00:29 -07002622 if (dalvikOpCode == OP_PACKED_SWITCH) {
Ben Cheng6c10a972009-10-29 14:39:18 -07002623 loadConstant(cUnit, r4PC, (int)findPackedSwitchIndex);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002624 } else {
Ben Cheng6c10a972009-10-29 14:39:18 -07002625 loadConstant(cUnit, r4PC, (int)findSparseSwitchIndex);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002626 }
Ben Cheng6c10a972009-10-29 14:39:18 -07002627 /* r0 <- Addr of the switch data */
2628 loadConstant(cUnit, r0,
2629 (int) (cUnit->method->insns + mir->offset + mir->dalvikInsn.vB));
2630 /* r2 <- pc of the instruction following the blx */
2631 opRegReg(cUnit, kOpMov, r2, rpc);
Bill Buzbee1465db52009-09-23 17:17:35 -07002632 opReg(cUnit, kOpBlx, r4PC);
Elliott Hughes6a555132010-02-25 15:41:42 -08002633 dvmCompilerClobberCallRegs(cUnit);
Ben Cheng6c10a972009-10-29 14:39:18 -07002634 /* pc <- computed goto target */
2635 opRegReg(cUnit, kOpMov, rpc, r0);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002636 break;
2637 }
2638 default:
2639 return true;
2640 }
2641 return false;
2642}
2643
2644static bool handleFmt35c_3rc(CompilationUnit *cUnit, MIR *mir, BasicBlock *bb,
Bill Buzbee89efc3d2009-07-28 11:22:22 -07002645 ArmLIR *labelList)
Ben Chengba4fc8b2009-06-01 13:00:29 -07002646{
Bill Buzbee9bc3df32009-07-30 10:52:29 -07002647 ArmLIR *retChainingCell = NULL;
Bill Buzbee89efc3d2009-07-28 11:22:22 -07002648 ArmLIR *pcrLabel = NULL;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002649
Bill Buzbeef4ce16f2009-07-28 13:28:25 -07002650 if (bb->fallThrough != NULL)
2651 retChainingCell = &labelList[bb->fallThrough->id];
2652
Ben Chengba4fc8b2009-06-01 13:00:29 -07002653 DecodedInstruction *dInsn = &mir->dalvikInsn;
2654 switch (mir->dalvikInsn.opCode) {
2655 /*
2656 * calleeMethod = this->clazz->vtable[
2657 * method->clazz->pDvmDex->pResMethods[BBBB]->methodIndex
2658 * ]
2659 */
2660 case OP_INVOKE_VIRTUAL:
2661 case OP_INVOKE_VIRTUAL_RANGE: {
Bill Buzbee89efc3d2009-07-28 11:22:22 -07002662 ArmLIR *predChainingCell = &labelList[bb->taken->id];
Ben Chengba4fc8b2009-06-01 13:00:29 -07002663 int methodIndex =
2664 cUnit->method->clazz->pDvmDex->pResMethods[dInsn->vB]->
2665 methodIndex;
2666
2667 if (mir->dalvikInsn.opCode == OP_INVOKE_VIRTUAL)
2668 genProcessArgsNoRange(cUnit, mir, dInsn, &pcrLabel);
2669 else
2670 genProcessArgsRange(cUnit, mir, dInsn, &pcrLabel);
2671
Ben Cheng38329f52009-07-07 14:19:20 -07002672 genInvokeVirtualCommon(cUnit, mir, methodIndex,
2673 retChainingCell,
2674 predChainingCell,
2675 pcrLabel);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002676 break;
2677 }
2678 /*
2679 * calleeMethod = method->clazz->super->vtable[method->clazz->pDvmDex
2680 * ->pResMethods[BBBB]->methodIndex]
2681 */
2682 /* TODO - not excersized in RunPerf.jar */
2683 case OP_INVOKE_SUPER:
2684 case OP_INVOKE_SUPER_RANGE: {
2685 int mIndex = cUnit->method->clazz->pDvmDex->
2686 pResMethods[dInsn->vB]->methodIndex;
2687 const Method *calleeMethod =
2688 cUnit->method->clazz->super->vtable[mIndex];
2689
2690 if (mir->dalvikInsn.opCode == OP_INVOKE_SUPER)
2691 genProcessArgsNoRange(cUnit, mir, dInsn, &pcrLabel);
2692 else
2693 genProcessArgsRange(cUnit, mir, dInsn, &pcrLabel);
2694
2695 /* r0 = calleeMethod */
2696 loadConstant(cUnit, r0, (int) calleeMethod);
2697
Ben Cheng38329f52009-07-07 14:19:20 -07002698 genInvokeSingletonCommon(cUnit, mir, bb, labelList, pcrLabel,
2699 calleeMethod);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002700 break;
2701 }
2702 /* calleeMethod = method->clazz->pDvmDex->pResMethods[BBBB] */
2703 case OP_INVOKE_DIRECT:
2704 case OP_INVOKE_DIRECT_RANGE: {
2705 const Method *calleeMethod =
2706 cUnit->method->clazz->pDvmDex->pResMethods[dInsn->vB];
2707
2708 if (mir->dalvikInsn.opCode == OP_INVOKE_DIRECT)
2709 genProcessArgsNoRange(cUnit, mir, dInsn, &pcrLabel);
2710 else
2711 genProcessArgsRange(cUnit, mir, dInsn, &pcrLabel);
2712
2713 /* r0 = calleeMethod */
2714 loadConstant(cUnit, r0, (int) calleeMethod);
2715
Ben Cheng38329f52009-07-07 14:19:20 -07002716 genInvokeSingletonCommon(cUnit, mir, bb, labelList, pcrLabel,
2717 calleeMethod);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002718 break;
2719 }
2720 /* calleeMethod = method->clazz->pDvmDex->pResMethods[BBBB] */
2721 case OP_INVOKE_STATIC:
2722 case OP_INVOKE_STATIC_RANGE: {
2723 const Method *calleeMethod =
2724 cUnit->method->clazz->pDvmDex->pResMethods[dInsn->vB];
2725
2726 if (mir->dalvikInsn.opCode == OP_INVOKE_STATIC)
2727 genProcessArgsNoRange(cUnit, mir, dInsn,
2728 NULL /* no null check */);
2729 else
2730 genProcessArgsRange(cUnit, mir, dInsn,
2731 NULL /* no null check */);
2732
2733 /* r0 = calleeMethod */
2734 loadConstant(cUnit, r0, (int) calleeMethod);
2735
Ben Cheng38329f52009-07-07 14:19:20 -07002736 genInvokeSingletonCommon(cUnit, mir, bb, labelList, pcrLabel,
2737 calleeMethod);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002738 break;
2739 }
Bill Buzbee1465db52009-09-23 17:17:35 -07002740 /*
Ben Chengba4fc8b2009-06-01 13:00:29 -07002741 * calleeMethod = dvmFindInterfaceMethodInCache(this->clazz,
2742 * BBBB, method, method->clazz->pDvmDex)
Ben Cheng38329f52009-07-07 14:19:20 -07002743 *
2744 * Given "invoke-interface {v0}", the following is the generated code:
2745 *
2746 * 0x426a9abe : ldr r0, [r5, #0] --+
2747 * 0x426a9ac0 : mov r7, r5 |
2748 * 0x426a9ac2 : sub r7, #24 |
2749 * 0x426a9ac4 : cmp r0, #0 | genProcessArgsNoRange
2750 * 0x426a9ac6 : beq 0x426a9afe |
2751 * 0x426a9ac8 : stmia r7, <r0> --+
2752 * 0x426a9aca : ldr r4, [pc, #104] --> r4 <- dalvikPC of this invoke
2753 * 0x426a9acc : add r1, pc, #52 --> r1 <- &retChainingCell
2754 * 0x426a9ace : add r2, pc, #60 --> r2 <- &predictedChainingCell
2755 * 0x426a9ad0 : blx_1 0x426a918c --+ TEMPLATE_INVOKE_METHOD_
2756 * 0x426a9ad2 : blx_2 see above --+ PREDICTED_CHAIN
2757 * 0x426a9ad4 : b 0x426a9b0c --> off to the predicted chain
2758 * 0x426a9ad6 : b 0x426a9afe --> punt to the interpreter
Ben Chenga8e64a72009-10-20 13:01:36 -07002759 * 0x426a9ad8 : mov r8, r1 --+
2760 * 0x426a9ada : mov r9, r2 |
2761 * 0x426a9adc : mov r10, r3 |
Ben Cheng38329f52009-07-07 14:19:20 -07002762 * 0x426a9ade : mov r0, r3 |
2763 * 0x426a9ae0 : mov r1, #74 | dvmFindInterfaceMethodInCache
2764 * 0x426a9ae2 : ldr r2, [pc, #76] |
2765 * 0x426a9ae4 : ldr r3, [pc, #68] |
2766 * 0x426a9ae6 : ldr r7, [pc, #64] |
2767 * 0x426a9ae8 : blx r7 --+
Ben Chenga8e64a72009-10-20 13:01:36 -07002768 * 0x426a9aea : mov r1, r8 --> r1 <- rechain count
Ben Cheng38329f52009-07-07 14:19:20 -07002769 * 0x426a9aec : cmp r1, #0 --> compare against 0
2770 * 0x426a9aee : bgt 0x426a9af8 --> >=0? don't rechain
2771 * 0x426a9af0 : ldr r7, [r6, #96] --+
Ben Chenga8e64a72009-10-20 13:01:36 -07002772 * 0x426a9af2 : mov r2, r9 | dvmJitToPatchPredictedChain
2773 * 0x426a9af4 : mov r3, r10 |
Ben Cheng38329f52009-07-07 14:19:20 -07002774 * 0x426a9af6 : blx r7 --+
2775 * 0x426a9af8 : add r1, pc, #8 --> r1 <- &retChainingCell
2776 * 0x426a9afa : blx_1 0x426a9098 --+ TEMPLATE_INVOKE_METHOD_NO_OPT
2777 * 0x426a9afc : blx_2 see above --+
2778 * -------- reconstruct dalvik PC : 0x428b786c @ +0x001e
2779 * 0x426a9afe (0042): ldr r0, [pc, #52]
2780 * Exception_Handling:
2781 * 0x426a9b00 (0044): ldr r1, [r6, #84]
2782 * 0x426a9b02 (0046): blx r1
2783 * 0x426a9b04 (0048): .align4
2784 * -------- chaining cell (hot): 0x0021
2785 * 0x426a9b04 (0048): ldr r0, [r6, #92]
2786 * 0x426a9b06 (004a): blx r0
2787 * 0x426a9b08 (004c): data 0x7872(30834)
2788 * 0x426a9b0a (004e): data 0x428b(17035)
2789 * 0x426a9b0c (0050): .align4
2790 * -------- chaining cell (predicted)
2791 * 0x426a9b0c (0050): data 0x0000(0) --> will be patched into bx
2792 * 0x426a9b0e (0052): data 0x0000(0)
2793 * 0x426a9b10 (0054): data 0x0000(0) --> class
2794 * 0x426a9b12 (0056): data 0x0000(0)
2795 * 0x426a9b14 (0058): data 0x0000(0) --> method
2796 * 0x426a9b16 (005a): data 0x0000(0)
2797 * 0x426a9b18 (005c): data 0x0000(0) --> reset count
2798 * 0x426a9b1a (005e): data 0x0000(0)
2799 * 0x426a9b28 (006c): .word (0xad0392a5)
2800 * 0x426a9b2c (0070): .word (0x6e750)
2801 * 0x426a9b30 (0074): .word (0x4109a618)
2802 * 0x426a9b34 (0078): .word (0x428b786c)
Ben Chengba4fc8b2009-06-01 13:00:29 -07002803 */
2804 case OP_INVOKE_INTERFACE:
2805 case OP_INVOKE_INTERFACE_RANGE: {
Bill Buzbee89efc3d2009-07-28 11:22:22 -07002806 ArmLIR *predChainingCell = &labelList[bb->taken->id];
Ben Chengba4fc8b2009-06-01 13:00:29 -07002807 int methodIndex = dInsn->vB;
2808
Bill Buzbee1465db52009-09-23 17:17:35 -07002809 /* Ensure that nothing is both live and dirty */
Bill Buzbeec6f10662010-02-09 11:16:15 -08002810 dvmCompilerFlushAllRegs(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07002811
Ben Chengba4fc8b2009-06-01 13:00:29 -07002812 if (mir->dalvikInsn.opCode == OP_INVOKE_INTERFACE)
2813 genProcessArgsNoRange(cUnit, mir, dInsn, &pcrLabel);
2814 else
2815 genProcessArgsRange(cUnit, mir, dInsn, &pcrLabel);
2816
Ben Cheng38329f52009-07-07 14:19:20 -07002817 /* "this" is already left in r0 by genProcessArgs* */
2818
2819 /* r4PC = dalvikCallsite */
2820 loadConstant(cUnit, r4PC,
2821 (int) (cUnit->method->insns + mir->offset));
2822
2823 /* r1 = &retChainingCell */
Bill Buzbee270c1d62009-08-13 16:58:07 -07002824 ArmLIR *addrRetChain =
Bill Buzbee1465db52009-09-23 17:17:35 -07002825 opRegRegImm(cUnit, kOpAdd, r1, rpc, 0);
Ben Cheng38329f52009-07-07 14:19:20 -07002826 addrRetChain->generic.target = (LIR *) retChainingCell;
2827
2828 /* r2 = &predictedChainingCell */
Bill Buzbee89efc3d2009-07-28 11:22:22 -07002829 ArmLIR *predictedChainingCell =
Bill Buzbee1465db52009-09-23 17:17:35 -07002830 opRegRegImm(cUnit, kOpAdd, r2, rpc, 0);
Ben Cheng38329f52009-07-07 14:19:20 -07002831 predictedChainingCell->generic.target = (LIR *) predChainingCell;
2832
2833 genDispatchToHandler(cUnit, TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN);
2834
2835 /* return through lr - jump to the chaining cell */
2836 genUnconditionalBranch(cUnit, predChainingCell);
2837
2838 /*
2839 * null-check on "this" may have been eliminated, but we still need
2840 * a PC-reconstruction label for stack overflow bailout.
2841 */
2842 if (pcrLabel == NULL) {
2843 int dPC = (int) (cUnit->method->insns + mir->offset);
Bill Buzbee89efc3d2009-07-28 11:22:22 -07002844 pcrLabel = dvmCompilerNew(sizeof(ArmLIR), true);
Bill Buzbee1465db52009-09-23 17:17:35 -07002845 pcrLabel->opCode = ARM_PSEUDO_kPCReconstruction_CELL;
Ben Cheng38329f52009-07-07 14:19:20 -07002846 pcrLabel->operands[0] = dPC;
2847 pcrLabel->operands[1] = mir->offset;
2848 /* Insert the place holder to the growable list */
2849 dvmInsertGrowableList(&cUnit->pcReconstructionList, pcrLabel);
2850 }
2851
2852 /* return through lr+2 - punt to the interpreter */
2853 genUnconditionalBranch(cUnit, pcrLabel);
2854
2855 /*
2856 * return through lr+4 - fully resolve the callee method.
2857 * r1 <- count
2858 * r2 <- &predictedChainCell
2859 * r3 <- this->class
2860 * r4 <- dPC
2861 * r7 <- this->class->vtable
2862 */
2863
2864 /* Save count, &predictedChainCell, and class to high regs first */
Bill Buzbee1465db52009-09-23 17:17:35 -07002865 genRegCopy(cUnit, r8, r1);
2866 genRegCopy(cUnit, r9, r2);
2867 genRegCopy(cUnit, r10, r3);
Ben Cheng38329f52009-07-07 14:19:20 -07002868
Ben Chengba4fc8b2009-06-01 13:00:29 -07002869 /* r0 now contains this->clazz */
Bill Buzbee1465db52009-09-23 17:17:35 -07002870 genRegCopy(cUnit, r0, r3);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002871
2872 /* r1 = BBBB */
2873 loadConstant(cUnit, r1, dInsn->vB);
2874
2875 /* r2 = method (caller) */
2876 loadConstant(cUnit, r2, (int) cUnit->method);
2877
2878 /* r3 = pDvmDex */
2879 loadConstant(cUnit, r3, (int) cUnit->method->clazz->pDvmDex);
2880
2881 loadConstant(cUnit, r7,
2882 (intptr_t) dvmFindInterfaceMethodInCache);
Bill Buzbee1465db52009-09-23 17:17:35 -07002883 opReg(cUnit, kOpBlx, r7);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002884
2885 /* r0 = calleeMethod (returned from dvmFindInterfaceMethodInCache */
2886
Bill Buzbee1465db52009-09-23 17:17:35 -07002887 genRegCopy(cUnit, r1, r8);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002888
Ben Cheng38329f52009-07-07 14:19:20 -07002889 /* Check if rechain limit is reached */
Bill Buzbee1465db52009-09-23 17:17:35 -07002890 opRegImm(cUnit, kOpCmp, r1, 0);
Ben Cheng38329f52009-07-07 14:19:20 -07002891
Bill Buzbee1465db52009-09-23 17:17:35 -07002892 ArmLIR *bypassRechaining = opCondBranch(cUnit, kArmCondGt);
Ben Cheng38329f52009-07-07 14:19:20 -07002893
Bill Buzbee270c1d62009-08-13 16:58:07 -07002894 loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
2895 jitToInterpEntries.dvmJitToPatchPredictedChain), r7);
Ben Cheng38329f52009-07-07 14:19:20 -07002896
Bill Buzbee1465db52009-09-23 17:17:35 -07002897 genRegCopy(cUnit, r2, r9);
2898 genRegCopy(cUnit, r3, r10);
Ben Cheng38329f52009-07-07 14:19:20 -07002899
2900 /*
2901 * r0 = calleeMethod
2902 * r2 = &predictedChainingCell
2903 * r3 = class
2904 *
2905 * &returnChainingCell has been loaded into r1 but is not needed
2906 * when patching the chaining cell and will be clobbered upon
2907 * returning so it will be reconstructed again.
2908 */
Bill Buzbee1465db52009-09-23 17:17:35 -07002909 opReg(cUnit, kOpBlx, r7);
Ben Cheng38329f52009-07-07 14:19:20 -07002910
2911 /* r1 = &retChainingCell */
Bill Buzbee1465db52009-09-23 17:17:35 -07002912 addrRetChain = opRegRegImm(cUnit, kOpAdd, r1, rpc, 0);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002913 addrRetChain->generic.target = (LIR *) retChainingCell;
Ben Cheng38329f52009-07-07 14:19:20 -07002914
2915 bypassRechaining->generic.target = (LIR *) addrRetChain;
2916
Ben Chengba4fc8b2009-06-01 13:00:29 -07002917 /*
2918 * r0 = this, r1 = calleeMethod,
2919 * r1 = &ChainingCell,
2920 * r4PC = callsiteDPC,
2921 */
2922 genDispatchToHandler(cUnit, TEMPLATE_INVOKE_METHOD_NO_OPT);
Ben Cheng86717f72010-03-05 15:27:21 -08002923#if defined(JIT_STATS)
2924 gDvmJit.invokePolymorphic++;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002925#endif
2926 /* Handle exceptions using the interpreter */
2927 genTrap(cUnit, mir->offset, pcrLabel);
2928 break;
2929 }
2930 /* NOP */
2931 case OP_INVOKE_DIRECT_EMPTY: {
2932 return false;
2933 }
2934 case OP_FILLED_NEW_ARRAY:
2935 case OP_FILLED_NEW_ARRAY_RANGE: {
2936 /* Just let the interpreter deal with these */
2937 genInterpSingleStep(cUnit, mir);
2938 break;
2939 }
2940 default:
2941 return true;
2942 }
2943 return false;
2944}
2945
2946static bool handleFmt35ms_3rms(CompilationUnit *cUnit, MIR *mir,
Bill Buzbee89efc3d2009-07-28 11:22:22 -07002947 BasicBlock *bb, ArmLIR *labelList)
Ben Chengba4fc8b2009-06-01 13:00:29 -07002948{
Bill Buzbee89efc3d2009-07-28 11:22:22 -07002949 ArmLIR *retChainingCell = &labelList[bb->fallThrough->id];
2950 ArmLIR *predChainingCell = &labelList[bb->taken->id];
2951 ArmLIR *pcrLabel = NULL;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002952
2953 DecodedInstruction *dInsn = &mir->dalvikInsn;
2954 switch (mir->dalvikInsn.opCode) {
2955 /* calleeMethod = this->clazz->vtable[BBBB] */
2956 case OP_INVOKE_VIRTUAL_QUICK_RANGE:
2957 case OP_INVOKE_VIRTUAL_QUICK: {
2958 int methodIndex = dInsn->vB;
2959 if (mir->dalvikInsn.opCode == OP_INVOKE_VIRTUAL_QUICK)
2960 genProcessArgsNoRange(cUnit, mir, dInsn, &pcrLabel);
2961 else
2962 genProcessArgsRange(cUnit, mir, dInsn, &pcrLabel);
2963
Ben Cheng38329f52009-07-07 14:19:20 -07002964 genInvokeVirtualCommon(cUnit, mir, methodIndex,
2965 retChainingCell,
2966 predChainingCell,
2967 pcrLabel);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002968 break;
2969 }
2970 /* calleeMethod = method->clazz->super->vtable[BBBB] */
2971 case OP_INVOKE_SUPER_QUICK:
2972 case OP_INVOKE_SUPER_QUICK_RANGE: {
2973 const Method *calleeMethod =
2974 cUnit->method->clazz->super->vtable[dInsn->vB];
2975
2976 if (mir->dalvikInsn.opCode == OP_INVOKE_SUPER_QUICK)
2977 genProcessArgsNoRange(cUnit, mir, dInsn, &pcrLabel);
2978 else
2979 genProcessArgsRange(cUnit, mir, dInsn, &pcrLabel);
2980
2981 /* r0 = calleeMethod */
2982 loadConstant(cUnit, r0, (int) calleeMethod);
2983
Ben Cheng38329f52009-07-07 14:19:20 -07002984 genInvokeSingletonCommon(cUnit, mir, bb, labelList, pcrLabel,
2985 calleeMethod);
2986 /* Handle exceptions using the interpreter */
2987 genTrap(cUnit, mir->offset, pcrLabel);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002988 break;
2989 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07002990 default:
2991 return true;
2992 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07002993 return false;
2994}
2995
2996/*
Bill Buzbeefd023aa2009-11-02 09:23:49 -08002997 * This operation is complex enough that we'll do it partly inline
2998 * and partly with a handler. NOTE: the handler uses hardcoded
2999 * values for string object offsets and must be revisitied if the
3000 * layout changes.
3001 */
3002static bool genInlinedCompareTo(CompilationUnit *cUnit, MIR *mir)
3003{
3004#if defined(USE_GLOBAL_STRING_DEFS)
3005 return false;
3006#else
3007 ArmLIR *rollback;
Bill Buzbeec6f10662010-02-09 11:16:15 -08003008 RegLocation rlThis = dvmCompilerGetSrc(cUnit, mir, 0);
3009 RegLocation rlComp = dvmCompilerGetSrc(cUnit, mir, 1);
Bill Buzbeefd023aa2009-11-02 09:23:49 -08003010
3011 loadValueDirectFixed(cUnit, rlThis, r0);
3012 loadValueDirectFixed(cUnit, rlComp, r1);
3013 /* Test objects for NULL */
3014 rollback = genNullCheck(cUnit, rlThis.sRegLow, r0, mir->offset, NULL);
3015 genNullCheck(cUnit, rlComp.sRegLow, r1, mir->offset, rollback);
3016 /*
3017 * TUNING: we could check for object pointer equality before invoking
3018 * handler. Unclear whether the gain would be worth the added code size
3019 * expansion.
3020 */
3021 genDispatchToHandler(cUnit, TEMPLATE_STRING_COMPARETO);
Bill Buzbeec6f10662010-02-09 11:16:15 -08003022 storeValue(cUnit, inlinedTarget(cUnit, mir, false),
3023 dvmCompilerGetReturn(cUnit));
Bill Buzbeefd023aa2009-11-02 09:23:49 -08003024 return true;
3025#endif
3026}
3027
3028static bool genInlinedIndexOf(CompilationUnit *cUnit, MIR *mir, bool singleI)
3029{
3030#if defined(USE_GLOBAL_STRING_DEFS)
3031 return false;
3032#else
Bill Buzbeec6f10662010-02-09 11:16:15 -08003033 RegLocation rlThis = dvmCompilerGetSrc(cUnit, mir, 0);
3034 RegLocation rlChar = dvmCompilerGetSrc(cUnit, mir, 1);
Bill Buzbeefd023aa2009-11-02 09:23:49 -08003035
3036 loadValueDirectFixed(cUnit, rlThis, r0);
3037 loadValueDirectFixed(cUnit, rlChar, r1);
3038 if (!singleI) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08003039 RegLocation rlStart = dvmCompilerGetSrc(cUnit, mir, 2);
Bill Buzbeefd023aa2009-11-02 09:23:49 -08003040 loadValueDirectFixed(cUnit, rlStart, r2);
3041 } else {
3042 loadConstant(cUnit, r2, 0);
3043 }
3044 /* Test objects for NULL */
3045 genNullCheck(cUnit, rlThis.sRegLow, r0, mir->offset, NULL);
3046 genDispatchToHandler(cUnit, TEMPLATE_STRING_INDEXOF);
Bill Buzbeec6f10662010-02-09 11:16:15 -08003047 storeValue(cUnit, inlinedTarget(cUnit, mir, false),
3048 dvmCompilerGetReturn(cUnit));
Bill Buzbeefd023aa2009-11-02 09:23:49 -08003049 return true;
3050#endif
3051}
3052
Bill Buzbee1f748632010-03-02 16:14:41 -08003053static bool genInlinedStringLength(CompilationUnit *cUnit, MIR *mir)
3054{
3055 RegLocation rlObj = dvmCompilerGetSrc(cUnit, mir, 0);
3056 RegLocation rlDest = inlinedTarget(cUnit, mir, false);
3057 rlObj = loadValue(cUnit, rlObj, kCoreReg);
3058 RegLocation rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
3059 genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset, NULL);
3060 loadWordDisp(cUnit, rlObj.lowReg, gDvm.offJavaLangString_count,
3061 rlResult.lowReg);
3062 storeValue(cUnit, rlDest, rlResult);
3063 return false;
3064}
3065
3066static bool genInlinedStringCharAt(CompilationUnit *cUnit, MIR *mir)
3067{
3068 int contents = offsetof(ArrayObject, contents);
3069 RegLocation rlObj = dvmCompilerGetSrc(cUnit, mir, 0);
3070 RegLocation rlIdx = dvmCompilerGetSrc(cUnit, mir, 1);
3071 RegLocation rlDest = inlinedTarget(cUnit, mir, false);
3072 RegLocation rlResult;
3073 rlObj = loadValue(cUnit, rlObj, kCoreReg);
3074 rlIdx = loadValue(cUnit, rlIdx, kCoreReg);
3075 int regMax = dvmCompilerAllocTemp(cUnit);
3076 int regOff = dvmCompilerAllocTemp(cUnit);
3077 int regPtr = dvmCompilerAllocTemp(cUnit);
3078 ArmLIR *pcrLabel = genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg,
3079 mir->offset, NULL);
3080 loadWordDisp(cUnit, rlObj.lowReg, gDvm.offJavaLangString_count, regMax);
3081 loadWordDisp(cUnit, rlObj.lowReg, gDvm.offJavaLangString_offset, regOff);
3082 loadWordDisp(cUnit, rlObj.lowReg, gDvm.offJavaLangString_value, regPtr);
3083 genBoundsCheck(cUnit, rlIdx.lowReg, regMax, mir->offset, pcrLabel);
3084 dvmCompilerFreeTemp(cUnit, regMax);
3085 opRegImm(cUnit, kOpAdd, regPtr, contents);
3086 opRegReg(cUnit, kOpAdd, regOff, rlIdx.lowReg);
3087 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
3088 loadBaseIndexed(cUnit, regPtr, regOff, rlResult.lowReg, 1, kUnsignedHalf);
3089 storeValue(cUnit, rlDest, rlResult);
3090 return false;
3091}
3092
3093static bool genInlinedAbsInt(CompilationUnit *cUnit, MIR *mir)
3094{
3095 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
3096 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
3097 RegLocation rlDest = inlinedTarget(cUnit, mir, false);;
3098 RegLocation rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
3099 int signReg = dvmCompilerAllocTemp(cUnit);
3100 /*
3101 * abs(x) = y<=x>>31, (x+y)^y.
3102 * Thumb2's IT block also yields 3 instructions, but imposes
3103 * scheduling constraints.
3104 */
3105 opRegRegImm(cUnit, kOpAsr, signReg, rlSrc.lowReg, 31);
3106 opRegRegReg(cUnit, kOpAdd, rlResult.lowReg, rlSrc.lowReg, signReg);
3107 opRegReg(cUnit, kOpXor, rlResult.lowReg, signReg);
3108 storeValue(cUnit, rlDest, rlResult);
3109 return false;
3110}
3111
3112static bool genInlinedAbsLong(CompilationUnit *cUnit, MIR *mir)
3113{
3114 RegLocation rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
3115 RegLocation rlDest = inlinedTargetWide(cUnit, mir, false);
3116 rlSrc = loadValueWide(cUnit, rlSrc, kCoreReg);
3117 RegLocation rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
3118 int signReg = dvmCompilerAllocTemp(cUnit);
3119 /*
3120 * abs(x) = y<=x>>31, (x+y)^y.
3121 * Thumb2 IT block allows slightly shorter sequence,
3122 * but introduces a scheduling barrier. Stick with this
3123 * mechanism for now.
3124 */
3125 opRegRegImm(cUnit, kOpAsr, signReg, rlSrc.highReg, 31);
3126 opRegRegReg(cUnit, kOpAdd, rlResult.lowReg, rlSrc.lowReg, signReg);
3127 opRegRegReg(cUnit, kOpAdc, rlResult.highReg, rlSrc.highReg, signReg);
3128 opRegReg(cUnit, kOpXor, rlResult.lowReg, signReg);
3129 opRegReg(cUnit, kOpXor, rlResult.highReg, signReg);
3130 storeValueWide(cUnit, rlDest, rlResult);
3131 return false;
3132}
Bill Buzbeefd023aa2009-11-02 09:23:49 -08003133
3134/*
Bill Buzbeece46c942009-11-20 15:41:34 -08003135 * NOTE: Handles both range and non-range versions (arguments
3136 * have already been normalized by this point).
Ben Chengba4fc8b2009-06-01 13:00:29 -07003137 */
Bill Buzbeece46c942009-11-20 15:41:34 -08003138static bool handleExecuteInline(CompilationUnit *cUnit, MIR *mir)
Ben Chengba4fc8b2009-06-01 13:00:29 -07003139{
3140 DecodedInstruction *dInsn = &mir->dalvikInsn;
3141 switch( mir->dalvikInsn.opCode) {
Bill Buzbeece46c942009-11-20 15:41:34 -08003142 case OP_EXECUTE_INLINE_RANGE:
Ben Chengba4fc8b2009-06-01 13:00:29 -07003143 case OP_EXECUTE_INLINE: {
3144 unsigned int i;
3145 const InlineOperation* inLineTable = dvmGetInlineOpsTable();
Bill Buzbee50a6bf22009-07-08 13:08:04 -07003146 int offset = offsetof(InterpState, retval);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003147 int operation = dInsn->vB;
Bill Buzbee1465db52009-09-23 17:17:35 -07003148 int tReg1;
3149 int tReg2;
Bill Buzbee50a6bf22009-07-08 13:08:04 -07003150 switch (operation) {
3151 case INLINE_EMPTYINLINEMETHOD:
3152 return false; /* Nop */
3153 case INLINE_STRING_LENGTH:
3154 return genInlinedStringLength(cUnit, mir);
3155 case INLINE_MATH_ABS_INT:
3156 return genInlinedAbsInt(cUnit, mir);
3157 case INLINE_MATH_ABS_LONG:
3158 return genInlinedAbsLong(cUnit, mir);
3159 case INLINE_MATH_MIN_INT:
3160 return genInlinedMinMaxInt(cUnit, mir, true);
3161 case INLINE_MATH_MAX_INT:
3162 return genInlinedMinMaxInt(cUnit, mir, false);
3163 case INLINE_STRING_CHARAT:
3164 return genInlinedStringCharAt(cUnit, mir);
3165 case INLINE_MATH_SQRT:
3166 if (genInlineSqrt(cUnit, mir))
Bill Buzbee9727c3d2009-08-01 11:32:36 -07003167 return false;
Bill Buzbee50a6bf22009-07-08 13:08:04 -07003168 else
3169 break; /* Handle with C routine */
Bill Buzbee50a6bf22009-07-08 13:08:04 -07003170 case INLINE_MATH_ABS_FLOAT:
Bill Buzbee1465db52009-09-23 17:17:35 -07003171 if (genInlinedAbsFloat(cUnit, mir))
3172 return false;
3173 else
3174 break;
Bill Buzbee50a6bf22009-07-08 13:08:04 -07003175 case INLINE_MATH_ABS_DOUBLE:
Bill Buzbee1465db52009-09-23 17:17:35 -07003176 if (genInlinedAbsDouble(cUnit, mir))
3177 return false;
3178 else
3179 break;
Bill Buzbee50a6bf22009-07-08 13:08:04 -07003180 case INLINE_STRING_COMPARETO:
Bill Buzbeefd023aa2009-11-02 09:23:49 -08003181 if (genInlinedCompareTo(cUnit, mir))
3182 return false;
3183 else
3184 break;
Bill Buzbee12ba0152009-09-03 14:03:09 -07003185 case INLINE_STRING_INDEXOF_I:
Bill Buzbeefd023aa2009-11-02 09:23:49 -08003186 if (genInlinedIndexOf(cUnit, mir, true /* I */))
3187 return false;
3188 else
3189 break;
Bill Buzbee12ba0152009-09-03 14:03:09 -07003190 case INLINE_STRING_INDEXOF_II:
Bill Buzbeefd023aa2009-11-02 09:23:49 -08003191 if (genInlinedIndexOf(cUnit, mir, false /* I */))
3192 return false;
3193 else
3194 break;
3195 case INLINE_STRING_EQUALS:
3196 case INLINE_MATH_COS:
3197 case INLINE_MATH_SIN:
3198 break; /* Handle with C routine */
Bill Buzbee50a6bf22009-07-08 13:08:04 -07003199 default:
Bill Buzbeefc519dc2010-03-06 23:30:57 -08003200 dvmCompilerAbort(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003201 }
Bill Buzbeec6f10662010-02-09 11:16:15 -08003202 dvmCompilerFlushAllRegs(cUnit); /* Everything to home location */
Elliott Hughes6a555132010-02-25 15:41:42 -08003203 dvmCompilerClobberCallRegs(cUnit);
Bill Buzbeec6f10662010-02-09 11:16:15 -08003204 dvmCompilerClobber(cUnit, r4PC);
3205 dvmCompilerClobber(cUnit, r7);
Bill Buzbee1465db52009-09-23 17:17:35 -07003206 opRegRegImm(cUnit, kOpAdd, r4PC, rGLUE, offset);
3207 opImm(cUnit, kOpPush, (1<<r4PC) | (1<<r7));
Ben Chengba4fc8b2009-06-01 13:00:29 -07003208 loadConstant(cUnit, r4PC, (int)inLineTable[operation].func);
Bill Buzbee1465db52009-09-23 17:17:35 -07003209 genExportPC(cUnit, mir);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003210 for (i=0; i < dInsn->vA; i++) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08003211 loadValueDirect(cUnit, dvmCompilerGetSrc(cUnit, mir, i), i);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003212 }
Bill Buzbee1465db52009-09-23 17:17:35 -07003213 opReg(cUnit, kOpBlx, r4PC);
3214 opRegImm(cUnit, kOpAdd, r13, 8);
Bill Buzbeece46c942009-11-20 15:41:34 -08003215 opRegImm(cUnit, kOpCmp, r0, 0); /* NULL? */
3216 ArmLIR *branchOver = opCondBranch(cUnit, kArmCondNe);
3217 loadConstant(cUnit, r0,
3218 (int) (cUnit->method->insns + mir->offset));
3219 genDispatchToHandler(cUnit, TEMPLATE_THROW_EXCEPTION_COMMON);
3220 ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel);
3221 target->defMask = ENCODE_ALL;
3222 branchOver->generic.target = (LIR *) target;
Ben Chengba4fc8b2009-06-01 13:00:29 -07003223 break;
3224 }
3225 default:
3226 return true;
3227 }
3228 return false;
3229}
3230
3231static bool handleFmt51l(CompilationUnit *cUnit, MIR *mir)
3232{
Bill Buzbee1465db52009-09-23 17:17:35 -07003233 //TUNING: We're using core regs here - not optimal when target is a double
Bill Buzbeec6f10662010-02-09 11:16:15 -08003234 RegLocation rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
3235 RegLocation rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07003236 loadConstantValue(cUnit, rlResult.lowReg,
3237 mir->dalvikInsn.vB_wide & 0xFFFFFFFFUL);
3238 loadConstantValue(cUnit, rlResult.highReg,
3239 (mir->dalvikInsn.vB_wide>>32) & 0xFFFFFFFFUL);
3240 storeValueWide(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003241 return false;
3242}
3243
Ben Chengba4fc8b2009-06-01 13:00:29 -07003244/*
3245 * The following are special processing routines that handle transfer of
3246 * controls between compiled code and the interpreter. Certain VM states like
3247 * Dalvik PC and special-purpose registers are reconstructed here.
3248 */
3249
Ben Cheng1efc9c52009-06-08 18:25:27 -07003250/* Chaining cell for code that may need warmup. */
3251static void handleNormalChainingCell(CompilationUnit *cUnit,
3252 unsigned int offset)
Ben Chengba4fc8b2009-06-01 13:00:29 -07003253{
Bill Buzbee270c1d62009-08-13 16:58:07 -07003254 loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
3255 jitToInterpEntries.dvmJitToInterpNormal), r0);
Bill Buzbee1465db52009-09-23 17:17:35 -07003256 opReg(cUnit, kOpBlx, r0);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003257 addWordData(cUnit, (int) (cUnit->method->insns + offset), true);
3258}
3259
3260/*
Ben Cheng1efc9c52009-06-08 18:25:27 -07003261 * Chaining cell for instructions that immediately following already translated
3262 * code.
Ben Chengba4fc8b2009-06-01 13:00:29 -07003263 */
Ben Cheng1efc9c52009-06-08 18:25:27 -07003264static void handleHotChainingCell(CompilationUnit *cUnit,
3265 unsigned int offset)
Ben Chengba4fc8b2009-06-01 13:00:29 -07003266{
Bill Buzbee270c1d62009-08-13 16:58:07 -07003267 loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
Ben Cheng40094c12010-02-24 20:58:44 -08003268 jitToInterpEntries.dvmJitToInterpTraceSelect), r0);
Bill Buzbee1465db52009-09-23 17:17:35 -07003269 opReg(cUnit, kOpBlx, r0);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003270 addWordData(cUnit, (int) (cUnit->method->insns + offset), true);
3271}
3272
Bill Buzbee9c4b7c82009-09-10 10:10:38 -07003273#if defined(WITH_SELF_VERIFICATION) || defined(WITH_JIT_TUNING)
Jeff Hao97319a82009-08-12 16:57:15 -07003274/* Chaining cell for branches that branch back into the same basic block */
3275static void handleBackwardBranchChainingCell(CompilationUnit *cUnit,
3276 unsigned int offset)
3277{
Bill Buzbee9c4b7c82009-09-10 10:10:38 -07003278#if defined(WITH_SELF_VERIFICATION)
Bill Buzbee1465db52009-09-23 17:17:35 -07003279 newLIR3(cUnit, kThumbLdrRRI5, r0, rGLUE,
Ben Cheng40094c12010-02-24 20:58:44 -08003280 offsetof(InterpState,
3281 jitToInterpEntries.dvmJitToInterpBackwardBranch) >> 2);
Bill Buzbee9c4b7c82009-09-10 10:10:38 -07003282#else
Bill Buzbee1465db52009-09-23 17:17:35 -07003283 newLIR3(cUnit, kThumbLdrRRI5, r0, rGLUE,
Bill Buzbee9c4b7c82009-09-10 10:10:38 -07003284 offsetof(InterpState, jitToInterpEntries.dvmJitToInterpNormal) >> 2);
3285#endif
Bill Buzbee1465db52009-09-23 17:17:35 -07003286 newLIR1(cUnit, kThumbBlxR, r0);
Jeff Hao97319a82009-08-12 16:57:15 -07003287 addWordData(cUnit, (int) (cUnit->method->insns + offset), true);
3288}
3289
3290#endif
Ben Chengba4fc8b2009-06-01 13:00:29 -07003291/* Chaining cell for monomorphic method invocations. */
Ben Cheng38329f52009-07-07 14:19:20 -07003292static void handleInvokeSingletonChainingCell(CompilationUnit *cUnit,
3293 const Method *callee)
Ben Chengba4fc8b2009-06-01 13:00:29 -07003294{
Bill Buzbee270c1d62009-08-13 16:58:07 -07003295 loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
Ben Cheng40094c12010-02-24 20:58:44 -08003296 jitToInterpEntries.dvmJitToInterpTraceSelect), r0);
Bill Buzbee1465db52009-09-23 17:17:35 -07003297 opReg(cUnit, kOpBlx, r0);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003298 addWordData(cUnit, (int) (callee->insns), true);
3299}
3300
Ben Cheng38329f52009-07-07 14:19:20 -07003301/* Chaining cell for monomorphic method invocations. */
3302static void handleInvokePredictedChainingCell(CompilationUnit *cUnit)
3303{
3304
3305 /* Should not be executed in the initial state */
3306 addWordData(cUnit, PREDICTED_CHAIN_BX_PAIR_INIT, true);
3307 /* To be filled: class */
3308 addWordData(cUnit, PREDICTED_CHAIN_CLAZZ_INIT, true);
3309 /* To be filled: method */
3310 addWordData(cUnit, PREDICTED_CHAIN_METHOD_INIT, true);
3311 /*
3312 * Rechain count. The initial value of 0 here will trigger chaining upon
3313 * the first invocation of this callsite.
3314 */
3315 addWordData(cUnit, PREDICTED_CHAIN_COUNTER_INIT, true);
3316}
3317
Ben Chengba4fc8b2009-06-01 13:00:29 -07003318/* Load the Dalvik PC into r0 and jump to the specified target */
3319static void handlePCReconstruction(CompilationUnit *cUnit,
Bill Buzbee89efc3d2009-07-28 11:22:22 -07003320 ArmLIR *targetLabel)
Ben Chengba4fc8b2009-06-01 13:00:29 -07003321{
Bill Buzbee89efc3d2009-07-28 11:22:22 -07003322 ArmLIR **pcrLabel =
3323 (ArmLIR **) cUnit->pcReconstructionList.elemList;
Ben Chengba4fc8b2009-06-01 13:00:29 -07003324 int numElems = cUnit->pcReconstructionList.numUsed;
3325 int i;
3326 for (i = 0; i < numElems; i++) {
3327 dvmCompilerAppendLIR(cUnit, (LIR *) pcrLabel[i]);
3328 /* r0 = dalvik PC */
3329 loadConstant(cUnit, r0, pcrLabel[i]->operands[0]);
3330 genUnconditionalBranch(cUnit, targetLabel);
3331 }
3332}
3333
Bill Buzbee1465db52009-09-23 17:17:35 -07003334static char *extendedMIROpNames[kMirOpLast - kMirOpFirst] = {
3335 "kMirOpPhi",
3336 "kMirOpNullNRangeUpCheck",
3337 "kMirOpNullNRangeDownCheck",
3338 "kMirOpLowerBound",
3339 "kMirOpPunt",
Ben Cheng4238ec22009-08-24 16:32:22 -07003340};
3341
3342/*
3343 * vA = arrayReg;
3344 * vB = idxReg;
3345 * vC = endConditionReg;
3346 * arg[0] = maxC
3347 * arg[1] = minC
3348 * arg[2] = loopBranchConditionCode
3349 */
3350static void genHoistedChecksForCountUpLoop(CompilationUnit *cUnit, MIR *mir)
3351{
Bill Buzbee1465db52009-09-23 17:17:35 -07003352 /*
3353 * NOTE: these synthesized blocks don't have ssa names assigned
3354 * for Dalvik registers. However, because they dominate the following
3355 * blocks we can simply use the Dalvik name w/ subscript 0 as the
3356 * ssa name.
3357 */
Ben Cheng4238ec22009-08-24 16:32:22 -07003358 DecodedInstruction *dInsn = &mir->dalvikInsn;
3359 const int lenOffset = offsetof(ArrayObject, length);
Ben Cheng4238ec22009-08-24 16:32:22 -07003360 const int maxC = dInsn->arg[0];
3361 const int minC = dInsn->arg[1];
Bill Buzbee1465db52009-09-23 17:17:35 -07003362 int regLength;
3363 RegLocation rlArray = cUnit->regLocation[mir->dalvikInsn.vA];
3364 RegLocation rlIdxEnd = cUnit->regLocation[mir->dalvikInsn.vC];
Ben Cheng4238ec22009-08-24 16:32:22 -07003365
3366 /* regArray <- arrayRef */
Bill Buzbee1465db52009-09-23 17:17:35 -07003367 rlArray = loadValue(cUnit, rlArray, kCoreReg);
3368 rlIdxEnd = loadValue(cUnit, rlIdxEnd, kCoreReg);
3369 genRegImmCheck(cUnit, kArmCondEq, rlArray.lowReg, 0, 0,
Ben Cheng4238ec22009-08-24 16:32:22 -07003370 (ArmLIR *) cUnit->loopAnalysis->branchToPCR);
3371
3372 /* regLength <- len(arrayRef) */
Bill Buzbeec6f10662010-02-09 11:16:15 -08003373 regLength = dvmCompilerAllocTemp(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07003374 loadWordDisp(cUnit, rlArray.lowReg, lenOffset, regLength);
Ben Cheng4238ec22009-08-24 16:32:22 -07003375
3376 int delta = maxC;
3377 /*
3378 * If the loop end condition is ">=" instead of ">", then the largest value
3379 * of the index is "endCondition - 1".
3380 */
3381 if (dInsn->arg[2] == OP_IF_GE) {
3382 delta--;
3383 }
3384
3385 if (delta) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08003386 int tReg = dvmCompilerAllocTemp(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07003387 opRegRegImm(cUnit, kOpAdd, tReg, rlIdxEnd.lowReg, delta);
3388 rlIdxEnd.lowReg = tReg;
Bill Buzbeec6f10662010-02-09 11:16:15 -08003389 dvmCompilerFreeTemp(cUnit, tReg);
Ben Cheng4238ec22009-08-24 16:32:22 -07003390 }
3391 /* Punt if "regIdxEnd < len(Array)" is false */
Bill Buzbee1465db52009-09-23 17:17:35 -07003392 genRegRegCheck(cUnit, kArmCondGe, rlIdxEnd.lowReg, regLength, 0,
Ben Cheng0fd31e42009-09-03 14:40:16 -07003393 (ArmLIR *) cUnit->loopAnalysis->branchToPCR);
Ben Cheng4238ec22009-08-24 16:32:22 -07003394}
3395
3396/*
3397 * vA = arrayReg;
3398 * vB = idxReg;
3399 * vC = endConditionReg;
3400 * arg[0] = maxC
3401 * arg[1] = minC
3402 * arg[2] = loopBranchConditionCode
3403 */
3404static void genHoistedChecksForCountDownLoop(CompilationUnit *cUnit, MIR *mir)
3405{
3406 DecodedInstruction *dInsn = &mir->dalvikInsn;
3407 const int lenOffset = offsetof(ArrayObject, length);
Bill Buzbeec6f10662010-02-09 11:16:15 -08003408 const int regLength = dvmCompilerAllocTemp(cUnit);
Ben Cheng4238ec22009-08-24 16:32:22 -07003409 const int maxC = dInsn->arg[0];
3410 const int minC = dInsn->arg[1];
Bill Buzbee1465db52009-09-23 17:17:35 -07003411 RegLocation rlArray = cUnit->regLocation[mir->dalvikInsn.vA];
3412 RegLocation rlIdxInit = cUnit->regLocation[mir->dalvikInsn.vB];
Ben Cheng4238ec22009-08-24 16:32:22 -07003413
3414 /* regArray <- arrayRef */
Bill Buzbee1465db52009-09-23 17:17:35 -07003415 rlArray = loadValue(cUnit, rlArray, kCoreReg);
3416 rlIdxInit = loadValue(cUnit, rlIdxInit, kCoreReg);
3417 genRegImmCheck(cUnit, kArmCondEq, rlArray.lowReg, 0, 0,
Ben Cheng4238ec22009-08-24 16:32:22 -07003418 (ArmLIR *) cUnit->loopAnalysis->branchToPCR);
3419
3420 /* regLength <- len(arrayRef) */
Bill Buzbee1465db52009-09-23 17:17:35 -07003421 loadWordDisp(cUnit, rlArray.lowReg, lenOffset, regLength);
Ben Cheng4238ec22009-08-24 16:32:22 -07003422
3423 if (maxC) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08003424 int tReg = dvmCompilerAllocTemp(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07003425 opRegRegImm(cUnit, kOpAdd, tReg, rlIdxInit.lowReg, maxC);
3426 rlIdxInit.lowReg = tReg;
Bill Buzbeec6f10662010-02-09 11:16:15 -08003427 dvmCompilerFreeTemp(cUnit, tReg);
Ben Cheng4238ec22009-08-24 16:32:22 -07003428 }
3429
3430 /* Punt if "regIdxInit < len(Array)" is false */
Bill Buzbee1465db52009-09-23 17:17:35 -07003431 genRegRegCheck(cUnit, kArmCondGe, rlIdxInit.lowReg, regLength, 0,
Ben Cheng0fd31e42009-09-03 14:40:16 -07003432 (ArmLIR *) cUnit->loopAnalysis->branchToPCR);
Ben Cheng4238ec22009-08-24 16:32:22 -07003433}
3434
3435/*
3436 * vA = idxReg;
3437 * vB = minC;
3438 */
3439static void genHoistedLowerBoundCheck(CompilationUnit *cUnit, MIR *mir)
3440{
3441 DecodedInstruction *dInsn = &mir->dalvikInsn;
Ben Cheng4238ec22009-08-24 16:32:22 -07003442 const int minC = dInsn->vB;
Bill Buzbee1465db52009-09-23 17:17:35 -07003443 RegLocation rlIdx = cUnit->regLocation[mir->dalvikInsn.vA];
Ben Cheng4238ec22009-08-24 16:32:22 -07003444
3445 /* regIdx <- initial index value */
Bill Buzbee1465db52009-09-23 17:17:35 -07003446 rlIdx = loadValue(cUnit, rlIdx, kCoreReg);
Ben Cheng4238ec22009-08-24 16:32:22 -07003447
3448 /* Punt if "regIdxInit + minC >= 0" is false */
Bill Buzbee1465db52009-09-23 17:17:35 -07003449 genRegImmCheck(cUnit, kArmCondLt, rlIdx.lowReg, -minC, 0,
Ben Cheng4238ec22009-08-24 16:32:22 -07003450 (ArmLIR *) cUnit->loopAnalysis->branchToPCR);
3451}
3452
3453/* Extended MIR instructions like PHI */
3454static void handleExtendedMIR(CompilationUnit *cUnit, MIR *mir)
3455{
Bill Buzbee1465db52009-09-23 17:17:35 -07003456 int opOffset = mir->dalvikInsn.opCode - kMirOpFirst;
Ben Cheng4238ec22009-08-24 16:32:22 -07003457 char *msg = dvmCompilerNew(strlen(extendedMIROpNames[opOffset]) + 1,
3458 false);
3459 strcpy(msg, extendedMIROpNames[opOffset]);
Bill Buzbee1465db52009-09-23 17:17:35 -07003460 newLIR1(cUnit, kArmPseudoExtended, (int) msg);
Ben Cheng4238ec22009-08-24 16:32:22 -07003461
3462 switch (mir->dalvikInsn.opCode) {
Bill Buzbee1465db52009-09-23 17:17:35 -07003463 case kMirOpPhi: {
Ben Cheng4238ec22009-08-24 16:32:22 -07003464 char *ssaString = dvmCompilerGetSSAString(cUnit, mir->ssaRep);
Bill Buzbee1465db52009-09-23 17:17:35 -07003465 newLIR1(cUnit, kArmPseudoSSARep, (int) ssaString);
Ben Cheng4238ec22009-08-24 16:32:22 -07003466 break;
3467 }
Bill Buzbee1465db52009-09-23 17:17:35 -07003468 case kMirOpNullNRangeUpCheck: {
Ben Cheng4238ec22009-08-24 16:32:22 -07003469 genHoistedChecksForCountUpLoop(cUnit, mir);
3470 break;
3471 }
Bill Buzbee1465db52009-09-23 17:17:35 -07003472 case kMirOpNullNRangeDownCheck: {
Ben Cheng4238ec22009-08-24 16:32:22 -07003473 genHoistedChecksForCountDownLoop(cUnit, mir);
3474 break;
3475 }
Bill Buzbee1465db52009-09-23 17:17:35 -07003476 case kMirOpLowerBound: {
Ben Cheng4238ec22009-08-24 16:32:22 -07003477 genHoistedLowerBoundCheck(cUnit, mir);
3478 break;
3479 }
Bill Buzbee1465db52009-09-23 17:17:35 -07003480 case kMirOpPunt: {
Ben Cheng4238ec22009-08-24 16:32:22 -07003481 genUnconditionalBranch(cUnit,
3482 (ArmLIR *) cUnit->loopAnalysis->branchToPCR);
3483 break;
3484 }
3485 default:
3486 break;
3487 }
3488}
3489
3490/*
3491 * Create a PC-reconstruction cell for the starting offset of this trace.
3492 * Since the PCR cell is placed near the end of the compiled code which is
3493 * usually out of range for a conditional branch, we put two branches (one
3494 * branch over to the loop body and one layover branch to the actual PCR) at the
3495 * end of the entry block.
3496 */
3497static void setupLoopEntryBlock(CompilationUnit *cUnit, BasicBlock *entry,
3498 ArmLIR *bodyLabel)
3499{
3500 /* Set up the place holder to reconstruct this Dalvik PC */
3501 ArmLIR *pcrLabel = dvmCompilerNew(sizeof(ArmLIR), true);
Bill Buzbee1465db52009-09-23 17:17:35 -07003502 pcrLabel->opCode = ARM_PSEUDO_kPCReconstruction_CELL;
Ben Cheng4238ec22009-08-24 16:32:22 -07003503 pcrLabel->operands[0] =
3504 (int) (cUnit->method->insns + entry->startOffset);
3505 pcrLabel->operands[1] = entry->startOffset;
3506 /* Insert the place holder to the growable list */
3507 dvmInsertGrowableList(&cUnit->pcReconstructionList, pcrLabel);
3508
3509 /*
3510 * Next, create two branches - one branch over to the loop body and the
3511 * other branch to the PCR cell to punt.
3512 */
3513 ArmLIR *branchToBody = dvmCompilerNew(sizeof(ArmLIR), true);
Bill Buzbee1465db52009-09-23 17:17:35 -07003514 branchToBody->opCode = kThumbBUncond;
Ben Cheng4238ec22009-08-24 16:32:22 -07003515 branchToBody->generic.target = (LIR *) bodyLabel;
Ben Chengdcf3e5d2009-09-11 13:42:05 -07003516 setupResourceMasks(branchToBody);
Ben Cheng4238ec22009-08-24 16:32:22 -07003517 cUnit->loopAnalysis->branchToBody = (LIR *) branchToBody;
3518
3519 ArmLIR *branchToPCR = dvmCompilerNew(sizeof(ArmLIR), true);
Bill Buzbee1465db52009-09-23 17:17:35 -07003520 branchToPCR->opCode = kThumbBUncond;
Ben Cheng4238ec22009-08-24 16:32:22 -07003521 branchToPCR->generic.target = (LIR *) pcrLabel;
Ben Chengdcf3e5d2009-09-11 13:42:05 -07003522 setupResourceMasks(branchToPCR);
Ben Cheng4238ec22009-08-24 16:32:22 -07003523 cUnit->loopAnalysis->branchToPCR = (LIR *) branchToPCR;
3524}
3525
Ben Chengba4fc8b2009-06-01 13:00:29 -07003526void dvmCompilerMIR2LIR(CompilationUnit *cUnit)
3527{
3528 /* Used to hold the labels of each block */
Bill Buzbee89efc3d2009-07-28 11:22:22 -07003529 ArmLIR *labelList =
3530 dvmCompilerNew(sizeof(ArmLIR) * cUnit->numBlocks, true);
Ben Chengcec26f62010-01-15 15:29:33 -08003531 GrowableList chainingListByType[kChainingCellGap];
Ben Chengba4fc8b2009-06-01 13:00:29 -07003532 int i;
3533
3534 /*
Ben Cheng38329f52009-07-07 14:19:20 -07003535 * Initialize various types chaining lists.
Ben Chengba4fc8b2009-06-01 13:00:29 -07003536 */
Ben Chengcec26f62010-01-15 15:29:33 -08003537 for (i = 0; i < kChainingCellGap; i++) {
Ben Chengba4fc8b2009-06-01 13:00:29 -07003538 dvmInitGrowableList(&chainingListByType[i], 2);
3539 }
3540
3541 BasicBlock **blockList = cUnit->blockList;
3542
Bill Buzbee6e963e12009-06-17 16:56:19 -07003543 if (cUnit->executionCount) {
3544 /*
3545 * Reserve 6 bytes at the beginning of the trace
3546 * +----------------------------+
3547 * | execution count (4 bytes) |
3548 * +----------------------------+
3549 * | chain cell offset (2 bytes)|
3550 * +----------------------------+
3551 * ...and then code to increment the execution
3552 * count:
3553 * mov r0, pc @ move adr of "mov r0,pc" + 4 to r0
3554 * sub r0, #10 @ back up to addr of executionCount
3555 * ldr r1, [r0]
3556 * add r1, #1
3557 * str r1, [r0]
3558 */
Bill Buzbee1465db52009-09-23 17:17:35 -07003559 newLIR1(cUnit, kArm16BitData, 0);
3560 newLIR1(cUnit, kArm16BitData, 0);
Ben Chengcc6600c2009-06-22 14:45:16 -07003561 cUnit->chainCellOffsetLIR =
Bill Buzbee1465db52009-09-23 17:17:35 -07003562 (LIR *) newLIR1(cUnit, kArm16BitData, CHAIN_CELL_OFFSET_TAG);
Bill Buzbee6e963e12009-06-17 16:56:19 -07003563 cUnit->headerSize = 6;
Bill Buzbee270c1d62009-08-13 16:58:07 -07003564 /* Thumb instruction used directly here to ensure correct size */
Bill Buzbee1465db52009-09-23 17:17:35 -07003565 newLIR2(cUnit, kThumbMovRR_H2L, r0, rpc);
3566 newLIR2(cUnit, kThumbSubRI8, r0, 10);
3567 newLIR3(cUnit, kThumbLdrRRI5, r1, r0, 0);
3568 newLIR2(cUnit, kThumbAddRI8, r1, 1);
3569 newLIR3(cUnit, kThumbStrRRI5, r1, r0, 0);
Bill Buzbee6e963e12009-06-17 16:56:19 -07003570 } else {
3571 /* Just reserve 2 bytes for the chain cell offset */
Ben Chengcc6600c2009-06-22 14:45:16 -07003572 cUnit->chainCellOffsetLIR =
Bill Buzbee1465db52009-09-23 17:17:35 -07003573 (LIR *) newLIR1(cUnit, kArm16BitData, CHAIN_CELL_OFFSET_TAG);
Bill Buzbee6e963e12009-06-17 16:56:19 -07003574 cUnit->headerSize = 2;
3575 }
Ben Cheng1efc9c52009-06-08 18:25:27 -07003576
Ben Chengba4fc8b2009-06-01 13:00:29 -07003577 /* Handle the content in each basic block */
3578 for (i = 0; i < cUnit->numBlocks; i++) {
3579 blockList[i]->visited = true;
3580 MIR *mir;
3581
3582 labelList[i].operands[0] = blockList[i]->startOffset;
3583
Ben Chengcec26f62010-01-15 15:29:33 -08003584 if (blockList[i]->blockType >= kChainingCellGap) {
Ben Chengba4fc8b2009-06-01 13:00:29 -07003585 /*
3586 * Append the label pseudo LIR first. Chaining cells will be handled
3587 * separately afterwards.
3588 */
3589 dvmCompilerAppendLIR(cUnit, (LIR *) &labelList[i]);
3590 }
3591
Bill Buzbee1465db52009-09-23 17:17:35 -07003592 if (blockList[i]->blockType == kEntryBlock) {
3593 labelList[i].opCode = ARM_PSEUDO_kEntryBlock;
Ben Cheng4238ec22009-08-24 16:32:22 -07003594 if (blockList[i]->firstMIRInsn == NULL) {
3595 continue;
3596 } else {
3597 setupLoopEntryBlock(cUnit, blockList[i],
3598 &labelList[blockList[i]->fallThrough->id]);
3599 }
Bill Buzbee1465db52009-09-23 17:17:35 -07003600 } else if (blockList[i]->blockType == kExitBlock) {
3601 labelList[i].opCode = ARM_PSEUDO_kExitBlock;
Ben Cheng4238ec22009-08-24 16:32:22 -07003602 goto gen_fallthrough;
Bill Buzbee1465db52009-09-23 17:17:35 -07003603 } else if (blockList[i]->blockType == kDalvikByteCode) {
3604 labelList[i].opCode = kArmPseudoNormalBlockLabel;
Ben Chenge9695e52009-06-16 16:11:47 -07003605 /* Reset the register state */
Bill Buzbeec6f10662010-02-09 11:16:15 -08003606 dvmCompilerResetRegPool(cUnit);
3607 dvmCompilerClobberAllRegs(cUnit);
3608 dvmCompilerResetNullCheck(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003609 } else {
3610 switch (blockList[i]->blockType) {
Bill Buzbee1465db52009-09-23 17:17:35 -07003611 case kChainingCellNormal:
3612 labelList[i].opCode = ARM_PSEUDO_kChainingCellNormal;
Ben Chengba4fc8b2009-06-01 13:00:29 -07003613 /* handle the codegen later */
3614 dvmInsertGrowableList(
Bill Buzbee1465db52009-09-23 17:17:35 -07003615 &chainingListByType[kChainingCellNormal], (void *) i);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003616 break;
Bill Buzbee1465db52009-09-23 17:17:35 -07003617 case kChainingCellInvokeSingleton:
Ben Cheng38329f52009-07-07 14:19:20 -07003618 labelList[i].opCode =
Bill Buzbee1465db52009-09-23 17:17:35 -07003619 ARM_PSEUDO_kChainingCellInvokeSingleton;
Ben Chengba4fc8b2009-06-01 13:00:29 -07003620 labelList[i].operands[0] =
3621 (int) blockList[i]->containingMethod;
3622 /* handle the codegen later */
3623 dvmInsertGrowableList(
Bill Buzbee1465db52009-09-23 17:17:35 -07003624 &chainingListByType[kChainingCellInvokeSingleton],
Ben Cheng38329f52009-07-07 14:19:20 -07003625 (void *) i);
3626 break;
Bill Buzbee1465db52009-09-23 17:17:35 -07003627 case kChainingCellInvokePredicted:
Ben Cheng38329f52009-07-07 14:19:20 -07003628 labelList[i].opCode =
Bill Buzbee1465db52009-09-23 17:17:35 -07003629 ARM_PSEUDO_kChainingCellInvokePredicted;
Ben Cheng38329f52009-07-07 14:19:20 -07003630 /* handle the codegen later */
3631 dvmInsertGrowableList(
Bill Buzbee1465db52009-09-23 17:17:35 -07003632 &chainingListByType[kChainingCellInvokePredicted],
Ben Cheng38329f52009-07-07 14:19:20 -07003633 (void *) i);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003634 break;
Bill Buzbee1465db52009-09-23 17:17:35 -07003635 case kChainingCellHot:
Ben Chengba4fc8b2009-06-01 13:00:29 -07003636 labelList[i].opCode =
Bill Buzbee1465db52009-09-23 17:17:35 -07003637 ARM_PSEUDO_kChainingCellHot;
Ben Chengba4fc8b2009-06-01 13:00:29 -07003638 /* handle the codegen later */
3639 dvmInsertGrowableList(
Bill Buzbee1465db52009-09-23 17:17:35 -07003640 &chainingListByType[kChainingCellHot],
Ben Chengba4fc8b2009-06-01 13:00:29 -07003641 (void *) i);
3642 break;
Bill Buzbee1465db52009-09-23 17:17:35 -07003643 case kPCReconstruction:
Ben Chengba4fc8b2009-06-01 13:00:29 -07003644 /* Make sure exception handling block is next */
3645 labelList[i].opCode =
Bill Buzbee1465db52009-09-23 17:17:35 -07003646 ARM_PSEUDO_kPCReconstruction_BLOCK_LABEL;
Ben Chengba4fc8b2009-06-01 13:00:29 -07003647 assert (i == cUnit->numBlocks - 2);
3648 handlePCReconstruction(cUnit, &labelList[i+1]);
3649 break;
Bill Buzbee1465db52009-09-23 17:17:35 -07003650 case kExceptionHandling:
3651 labelList[i].opCode = kArmPseudoEHBlockLabel;
Ben Chengba4fc8b2009-06-01 13:00:29 -07003652 if (cUnit->pcReconstructionList.numUsed) {
Bill Buzbee270c1d62009-08-13 16:58:07 -07003653 loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
3654 jitToInterpEntries.dvmJitToInterpPunt),
3655 r1);
Bill Buzbee1465db52009-09-23 17:17:35 -07003656 opReg(cUnit, kOpBlx, r1);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003657 }
3658 break;
Bill Buzbee9c4b7c82009-09-10 10:10:38 -07003659#if defined(WITH_SELF_VERIFICATION) || defined(WITH_JIT_TUNING)
Bill Buzbee1465db52009-09-23 17:17:35 -07003660 case kChainingCellBackwardBranch:
Jeff Hao97319a82009-08-12 16:57:15 -07003661 labelList[i].opCode =
Bill Buzbee1465db52009-09-23 17:17:35 -07003662 ARM_PSEUDO_kChainingCellBackwardBranch;
Jeff Hao97319a82009-08-12 16:57:15 -07003663 /* handle the codegen later */
3664 dvmInsertGrowableList(
Bill Buzbee1465db52009-09-23 17:17:35 -07003665 &chainingListByType[kChainingCellBackwardBranch],
Jeff Hao97319a82009-08-12 16:57:15 -07003666 (void *) i);
3667 break;
3668#endif
Ben Chengba4fc8b2009-06-01 13:00:29 -07003669 default:
3670 break;
3671 }
3672 continue;
3673 }
Ben Chenge9695e52009-06-16 16:11:47 -07003674
Bill Buzbee89efc3d2009-07-28 11:22:22 -07003675 ArmLIR *headLIR = NULL;
Ben Chenge9695e52009-06-16 16:11:47 -07003676
Ben Chengba4fc8b2009-06-01 13:00:29 -07003677 for (mir = blockList[i]->firstMIRInsn; mir; mir = mir->next) {
Bill Buzbee1465db52009-09-23 17:17:35 -07003678
Bill Buzbeec6f10662010-02-09 11:16:15 -08003679 dvmCompilerResetRegPool(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07003680 if (gDvmJit.disableOpt & (1 << kTrackLiveTemps)) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08003681 dvmCompilerClobberAllRegs(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07003682 }
3683
3684 if (gDvmJit.disableOpt & (1 << kSuppressLoads)) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08003685 dvmCompilerResetDefTracking(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07003686 }
3687
3688 if (mir->dalvikInsn.opCode >= kMirOpFirst) {
Ben Cheng4238ec22009-08-24 16:32:22 -07003689 handleExtendedMIR(cUnit, mir);
3690 continue;
3691 }
3692
Bill Buzbee1465db52009-09-23 17:17:35 -07003693
Ben Chengba4fc8b2009-06-01 13:00:29 -07003694 OpCode dalvikOpCode = mir->dalvikInsn.opCode;
3695 InstructionFormat dalvikFormat =
3696 dexGetInstrFormat(gDvm.instrFormat, dalvikOpCode);
Bill Buzbee89efc3d2009-07-28 11:22:22 -07003697 ArmLIR *boundaryLIR =
Bill Buzbee1465db52009-09-23 17:17:35 -07003698 newLIR2(cUnit, ARM_PSEUDO_kDalvikByteCode_BOUNDARY,
Ben Chengccd6c012009-10-15 14:52:45 -07003699 mir->offset,
3700 (int) dvmCompilerGetDalvikDisassembly(&mir->dalvikInsn)
3701 );
Ben Cheng4238ec22009-08-24 16:32:22 -07003702 if (mir->ssaRep) {
3703 char *ssaString = dvmCompilerGetSSAString(cUnit, mir->ssaRep);
Bill Buzbee1465db52009-09-23 17:17:35 -07003704 newLIR1(cUnit, kArmPseudoSSARep, (int) ssaString);
Ben Cheng4238ec22009-08-24 16:32:22 -07003705 }
3706
Ben Chenge9695e52009-06-16 16:11:47 -07003707 /* Remember the first LIR for this block */
3708 if (headLIR == NULL) {
3709 headLIR = boundaryLIR;
Ben Chengd7d426a2009-09-22 11:23:36 -07003710 /* Set the first boundaryLIR as a scheduling barrier */
3711 headLIR->defMask = ENCODE_ALL;
Ben Chenge9695e52009-06-16 16:11:47 -07003712 }
Ben Cheng4238ec22009-08-24 16:32:22 -07003713
Ben Chengba4fc8b2009-06-01 13:00:29 -07003714 bool notHandled;
3715 /*
3716 * Debugging: screen the opcode first to see if it is in the
3717 * do[-not]-compile list
3718 */
3719 bool singleStepMe =
3720 gDvmJit.includeSelectedOp !=
3721 ((gDvmJit.opList[dalvikOpCode >> 3] &
3722 (1 << (dalvikOpCode & 0x7))) !=
3723 0);
3724 if (singleStepMe || cUnit->allSingleStep) {
3725 notHandled = false;
3726 genInterpSingleStep(cUnit, mir);
3727 } else {
3728 opcodeCoverage[dalvikOpCode]++;
3729 switch (dalvikFormat) {
3730 case kFmt10t:
3731 case kFmt20t:
3732 case kFmt30t:
3733 notHandled = handleFmt10t_Fmt20t_Fmt30t(cUnit,
3734 mir, blockList[i], labelList);
3735 break;
3736 case kFmt10x:
3737 notHandled = handleFmt10x(cUnit, mir);
3738 break;
3739 case kFmt11n:
3740 case kFmt31i:
3741 notHandled = handleFmt11n_Fmt31i(cUnit, mir);
3742 break;
3743 case kFmt11x:
3744 notHandled = handleFmt11x(cUnit, mir);
3745 break;
3746 case kFmt12x:
3747 notHandled = handleFmt12x(cUnit, mir);
3748 break;
3749 case kFmt20bc:
3750 notHandled = handleFmt20bc(cUnit, mir);
3751 break;
3752 case kFmt21c:
3753 case kFmt31c:
3754 notHandled = handleFmt21c_Fmt31c(cUnit, mir);
3755 break;
3756 case kFmt21h:
3757 notHandled = handleFmt21h(cUnit, mir);
3758 break;
3759 case kFmt21s:
3760 notHandled = handleFmt21s(cUnit, mir);
3761 break;
3762 case kFmt21t:
3763 notHandled = handleFmt21t(cUnit, mir, blockList[i],
3764 labelList);
3765 break;
3766 case kFmt22b:
3767 case kFmt22s:
3768 notHandled = handleFmt22b_Fmt22s(cUnit, mir);
3769 break;
3770 case kFmt22c:
3771 notHandled = handleFmt22c(cUnit, mir);
3772 break;
3773 case kFmt22cs:
3774 notHandled = handleFmt22cs(cUnit, mir);
3775 break;
3776 case kFmt22t:
3777 notHandled = handleFmt22t(cUnit, mir, blockList[i],
3778 labelList);
3779 break;
3780 case kFmt22x:
3781 case kFmt32x:
3782 notHandled = handleFmt22x_Fmt32x(cUnit, mir);
3783 break;
3784 case kFmt23x:
3785 notHandled = handleFmt23x(cUnit, mir);
3786 break;
3787 case kFmt31t:
3788 notHandled = handleFmt31t(cUnit, mir);
3789 break;
3790 case kFmt3rc:
3791 case kFmt35c:
3792 notHandled = handleFmt35c_3rc(cUnit, mir, blockList[i],
3793 labelList);
3794 break;
3795 case kFmt3rms:
3796 case kFmt35ms:
3797 notHandled = handleFmt35ms_3rms(cUnit, mir,blockList[i],
3798 labelList);
3799 break;
3800 case kFmt3inline:
Andy McFaddenb0a05412009-11-19 10:23:41 -08003801 case kFmt3rinline:
Bill Buzbeece46c942009-11-20 15:41:34 -08003802 notHandled = handleExecuteInline(cUnit, mir);
Andy McFaddenb0a05412009-11-19 10:23:41 -08003803 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07003804 case kFmt51l:
3805 notHandled = handleFmt51l(cUnit, mir);
3806 break;
3807 default:
3808 notHandled = true;
3809 break;
3810 }
3811 }
3812 if (notHandled) {
3813 LOGE("%#06x: Opcode 0x%x (%s) / Fmt %d not handled\n",
3814 mir->offset,
3815 dalvikOpCode, getOpcodeName(dalvikOpCode),
3816 dalvikFormat);
Bill Buzbeefc519dc2010-03-06 23:30:57 -08003817 dvmCompilerAbort(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003818 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07003819 }
3820 }
Ben Cheng4238ec22009-08-24 16:32:22 -07003821
Bill Buzbee1465db52009-09-23 17:17:35 -07003822 if (blockList[i]->blockType == kEntryBlock) {
Ben Cheng4238ec22009-08-24 16:32:22 -07003823 dvmCompilerAppendLIR(cUnit,
3824 (LIR *) cUnit->loopAnalysis->branchToBody);
3825 dvmCompilerAppendLIR(cUnit,
3826 (LIR *) cUnit->loopAnalysis->branchToPCR);
3827 }
3828
3829 if (headLIR) {
3830 /*
3831 * Eliminate redundant loads/stores and delay stores into later
3832 * slots
3833 */
3834 dvmCompilerApplyLocalOptimizations(cUnit, (LIR *) headLIR,
3835 cUnit->lastLIRInsn);
3836 }
3837
3838gen_fallthrough:
Ben Cheng1efc9c52009-06-08 18:25:27 -07003839 /*
3840 * Check if the block is terminated due to trace length constraint -
3841 * insert an unconditional branch to the chaining cell.
3842 */
3843 if (blockList[i]->needFallThroughBranch) {
3844 genUnconditionalBranch(cUnit,
3845 &labelList[blockList[i]->fallThrough->id]);
3846 }
3847
Ben Chengba4fc8b2009-06-01 13:00:29 -07003848 }
3849
Ben Chenge9695e52009-06-16 16:11:47 -07003850 /* Handle the chaining cells in predefined order */
Ben Chengcec26f62010-01-15 15:29:33 -08003851 for (i = 0; i < kChainingCellGap; i++) {
Ben Chengba4fc8b2009-06-01 13:00:29 -07003852 size_t j;
3853 int *blockIdList = (int *) chainingListByType[i].elemList;
3854
3855 cUnit->numChainingCells[i] = chainingListByType[i].numUsed;
3856
3857 /* No chaining cells of this type */
3858 if (cUnit->numChainingCells[i] == 0)
3859 continue;
3860
3861 /* Record the first LIR for a new type of chaining cell */
3862 cUnit->firstChainingLIR[i] = (LIR *) &labelList[blockIdList[0]];
3863
3864 for (j = 0; j < chainingListByType[i].numUsed; j++) {
3865 int blockId = blockIdList[j];
3866
3867 /* Align this chaining cell first */
Bill Buzbee1465db52009-09-23 17:17:35 -07003868 newLIR0(cUnit, kArmPseudoPseudoAlign4);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003869
3870 /* Insert the pseudo chaining instruction */
3871 dvmCompilerAppendLIR(cUnit, (LIR *) &labelList[blockId]);
3872
3873
3874 switch (blockList[blockId]->blockType) {
Bill Buzbee1465db52009-09-23 17:17:35 -07003875 case kChainingCellNormal:
Ben Cheng1efc9c52009-06-08 18:25:27 -07003876 handleNormalChainingCell(cUnit,
Ben Chengba4fc8b2009-06-01 13:00:29 -07003877 blockList[blockId]->startOffset);
3878 break;
Bill Buzbee1465db52009-09-23 17:17:35 -07003879 case kChainingCellInvokeSingleton:
Ben Cheng38329f52009-07-07 14:19:20 -07003880 handleInvokeSingletonChainingCell(cUnit,
Ben Chengba4fc8b2009-06-01 13:00:29 -07003881 blockList[blockId]->containingMethod);
3882 break;
Bill Buzbee1465db52009-09-23 17:17:35 -07003883 case kChainingCellInvokePredicted:
Ben Cheng38329f52009-07-07 14:19:20 -07003884 handleInvokePredictedChainingCell(cUnit);
3885 break;
Bill Buzbee1465db52009-09-23 17:17:35 -07003886 case kChainingCellHot:
Ben Cheng1efc9c52009-06-08 18:25:27 -07003887 handleHotChainingCell(cUnit,
Ben Chengba4fc8b2009-06-01 13:00:29 -07003888 blockList[blockId]->startOffset);
3889 break;
Bill Buzbee9c4b7c82009-09-10 10:10:38 -07003890#if defined(WITH_SELF_VERIFICATION) || defined(WITH_JIT_TUNING)
Bill Buzbee1465db52009-09-23 17:17:35 -07003891 case kChainingCellBackwardBranch:
Jeff Hao97319a82009-08-12 16:57:15 -07003892 handleBackwardBranchChainingCell(cUnit,
3893 blockList[blockId]->startOffset);
3894 break;
3895#endif
Ben Chengba4fc8b2009-06-01 13:00:29 -07003896 default:
Bill Buzbee1465db52009-09-23 17:17:35 -07003897 LOGE("Bad blocktype %d", blockList[blockId]->blockType);
Bill Buzbeefc519dc2010-03-06 23:30:57 -08003898 dvmCompilerAbort(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003899 }
3900 }
3901 }
Ben Chenge9695e52009-06-16 16:11:47 -07003902
Ben Chengcec26f62010-01-15 15:29:33 -08003903 /* Mark the bottom of chaining cells */
3904 cUnit->chainingCellBottom = (LIR *) newLIR0(cUnit, kArmChainingCellBottom);
3905
Ben Cheng6c10a972009-10-29 14:39:18 -07003906 /*
3907 * Generate the branch to the dvmJitToInterpNoChain entry point at the end
3908 * of all chaining cells for the overflow cases.
3909 */
3910 if (cUnit->switchOverflowPad) {
3911 loadConstant(cUnit, r0, (int) cUnit->switchOverflowPad);
3912 loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
3913 jitToInterpEntries.dvmJitToInterpNoChain), r2);
3914 opRegReg(cUnit, kOpAdd, r1, r1);
3915 opRegRegReg(cUnit, kOpAdd, r4PC, r0, r1);
Ben Cheng86717f72010-03-05 15:27:21 -08003916#if defined(JIT_STATS)
Ben Cheng6c10a972009-10-29 14:39:18 -07003917 loadConstant(cUnit, r0, kSwitchOverflow);
3918#endif
3919 opReg(cUnit, kOpBlx, r2);
3920 }
3921
Ben Chenge9695e52009-06-16 16:11:47 -07003922 dvmCompilerApplyGlobalOptimizations(cUnit);
jeffhao9e45c0b2010-02-03 10:24:05 -08003923
3924#if defined(WITH_SELF_VERIFICATION)
3925 selfVerificationBranchInsertPass(cUnit);
3926#endif
Ben Chengba4fc8b2009-06-01 13:00:29 -07003927}
3928
3929/* Accept the work and start compiling */
Bill Buzbee716f1202009-07-23 13:22:09 -07003930bool dvmCompilerDoWork(CompilerWorkOrder *work)
Ben Chengba4fc8b2009-06-01 13:00:29 -07003931{
Ben Chengccd6c012009-10-15 14:52:45 -07003932 bool res;
Ben Chengba4fc8b2009-06-01 13:00:29 -07003933
Ben Cheng6999d842010-01-26 16:46:15 -08003934 if (gDvmJit.codeCacheFull) {
Ben Chengccd6c012009-10-15 14:52:45 -07003935 return false;
3936 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07003937
Ben Chengccd6c012009-10-15 14:52:45 -07003938 switch (work->kind) {
3939 case kWorkOrderMethod:
3940 res = dvmCompileMethod(work->info, &work->result);
3941 break;
3942 case kWorkOrderTrace:
3943 /* Start compilation with maximally allowed trace length */
Bill Buzbeefc519dc2010-03-06 23:30:57 -08003944 res = dvmCompileTrace(work->info, JIT_MAX_TRACE_LEN, &work->result,
3945 work->bailPtr);
Ben Chengccd6c012009-10-15 14:52:45 -07003946 break;
3947 case kWorkOrderTraceDebug: {
3948 bool oldPrintMe = gDvmJit.printMe;
3949 gDvmJit.printMe = true;
3950 /* Start compilation with maximally allowed trace length */
Bill Buzbeefc519dc2010-03-06 23:30:57 -08003951 res = dvmCompileTrace(work->info, JIT_MAX_TRACE_LEN, &work->result,
3952 work->bailPtr);
Ben Chengccd6c012009-10-15 14:52:45 -07003953 gDvmJit.printMe = oldPrintMe;;
3954 break;
3955 }
3956 default:
3957 res = false;
Bill Buzbeefc519dc2010-03-06 23:30:57 -08003958 LOGE("Jit: unknown work order type");
3959 assert(0); // Bail if debug build, discard oteherwise
Ben Chengccd6c012009-10-15 14:52:45 -07003960 }
3961 return res;
Ben Chengba4fc8b2009-06-01 13:00:29 -07003962}
3963
Ben Chengba4fc8b2009-06-01 13:00:29 -07003964/* Architectural-specific debugging helpers go here */
3965void dvmCompilerArchDump(void)
3966{
3967 /* Print compiled opcode in this VM instance */
3968 int i, start, streak;
3969 char buf[1024];
3970
3971 streak = i = 0;
3972 buf[0] = 0;
3973 while (opcodeCoverage[i] == 0 && i < 256) {
3974 i++;
3975 }
3976 if (i == 256) {
3977 return;
3978 }
3979 for (start = i++, streak = 1; i < 256; i++) {
3980 if (opcodeCoverage[i]) {
3981 streak++;
3982 } else {
3983 if (streak == 1) {
3984 sprintf(buf+strlen(buf), "%x,", start);
3985 } else {
3986 sprintf(buf+strlen(buf), "%x-%x,", start, start + streak - 1);
3987 }
3988 streak = 0;
3989 while (opcodeCoverage[i] == 0 && i < 256) {
3990 i++;
3991 }
3992 if (i < 256) {
3993 streak = 1;
3994 start = i;
3995 }
3996 }
3997 }
3998 if (streak) {
3999 if (streak == 1) {
4000 sprintf(buf+strlen(buf), "%x", start);
4001 } else {
4002 sprintf(buf+strlen(buf), "%x-%x", start, start + streak - 1);
4003 }
4004 }
4005 if (strlen(buf)) {
Ben Cheng8b258bf2009-06-24 17:27:07 -07004006 LOGD("dalvik.vm.jit.op = %s", buf);
Ben Chengba4fc8b2009-06-01 13:00:29 -07004007 }
4008}
Ben Chengd7d426a2009-09-22 11:23:36 -07004009
4010/* Common initialization routine for an architecture family */
4011bool dvmCompilerArchInit()
4012{
4013 int i;
4014
Bill Buzbee1465db52009-09-23 17:17:35 -07004015 for (i = 0; i < kArmLast; i++) {
Ben Chengd7d426a2009-09-22 11:23:36 -07004016 if (EncodingMap[i].opCode != i) {
4017 LOGE("Encoding order for %s is wrong: expecting %d, seeing %d",
4018 EncodingMap[i].name, i, EncodingMap[i].opCode);
Bill Buzbeefc519dc2010-03-06 23:30:57 -08004019 dvmAbort(); // OK to dvmAbort - build error
Ben Chengd7d426a2009-09-22 11:23:36 -07004020 }
4021 }
4022
Ben Cheng5d90c202009-11-22 23:31:11 -08004023 return dvmCompilerArchVariantInit();
4024}
4025
4026void *dvmCompilerGetInterpretTemplate()
4027{
4028 return (void*) ((int)gDvmJit.codeCache +
4029 templateEntryOffsets[TEMPLATE_INTERPRET]);
4030}
4031
4032/* Needed by the ld/st optmizatons */
4033ArmLIR* dvmCompilerRegCopyNoInsert(CompilationUnit *cUnit, int rDest, int rSrc)
4034{
4035 return genRegCopyNoInsert(cUnit, rDest, rSrc);
4036}
4037
4038/* Needed by the register allocator */
4039ArmLIR* dvmCompilerRegCopy(CompilationUnit *cUnit, int rDest, int rSrc)
4040{
4041 return genRegCopy(cUnit, rDest, rSrc);
4042}
4043
4044/* Needed by the register allocator */
4045void dvmCompilerRegCopyWide(CompilationUnit *cUnit, int destLo, int destHi,
4046 int srcLo, int srcHi)
4047{
4048 genRegCopyWide(cUnit, destLo, destHi, srcLo, srcHi);
4049}
4050
4051void dvmCompilerFlushRegImpl(CompilationUnit *cUnit, int rBase,
4052 int displacement, int rSrc, OpSize size)
4053{
4054 storeBaseDisp(cUnit, rBase, displacement, rSrc, size);
4055}
4056
4057void dvmCompilerFlushRegWideImpl(CompilationUnit *cUnit, int rBase,
4058 int displacement, int rSrcLo, int rSrcHi)
4059{
4060 storeBaseDispWide(cUnit, rBase, displacement, rSrcLo, rSrcHi);
Ben Chengd7d426a2009-09-22 11:23:36 -07004061}