blob: df0825a8572579b2403040adb9aba492faa3ef72 [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);
568 /* Bad? - roll back and re-execute if so */
569 genRegImmCheck(cUnit, kArmCondEq, r0, 0, mir->offset, pcrLabel);
570
571 /* Resume here - must reload element, regPtr & index preserved */
572 loadValueDirectFixed(cUnit, rlSrc, r0);
573
574 ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel);
575 target->defMask = ENCODE_ALL;
576 branchOver->generic.target = (LIR *) target;
577
578#if defined(WITH_SELF_VERIFICATION)
579 cUnit->heapMemOp = true;
580#endif
581 storeBaseIndexed(cUnit, regPtr, regIndex, r0,
582 scale, kWord);
583#if defined(WITH_SELF_VERIFICATION)
584 cUnit->heapMemOp = false;
585#endif
586}
587
Ben Cheng5d90c202009-11-22 23:31:11 -0800588static bool genShiftOpLong(CompilationUnit *cUnit, MIR *mir,
589 RegLocation rlDest, RegLocation rlSrc1,
590 RegLocation rlShift)
Ben Chengba4fc8b2009-06-01 13:00:29 -0700591{
Ben Chenge9695e52009-06-16 16:11:47 -0700592 /*
593 * Don't mess with the regsiters here as there is a particular calling
594 * convention to the out-of-line handler.
595 */
Bill Buzbee1465db52009-09-23 17:17:35 -0700596 RegLocation rlResult;
597
598 loadValueDirectWideFixed(cUnit, rlSrc1, r0, r1);
599 loadValueDirect(cUnit, rlShift, r2);
Ben Chenge9695e52009-06-16 16:11:47 -0700600 switch( mir->dalvikInsn.opCode) {
601 case OP_SHL_LONG:
602 case OP_SHL_LONG_2ADDR:
603 genDispatchToHandler(cUnit, TEMPLATE_SHL_LONG);
604 break;
605 case OP_SHR_LONG:
606 case OP_SHR_LONG_2ADDR:
607 genDispatchToHandler(cUnit, TEMPLATE_SHR_LONG);
608 break;
609 case OP_USHR_LONG:
610 case OP_USHR_LONG_2ADDR:
611 genDispatchToHandler(cUnit, TEMPLATE_USHR_LONG);
612 break;
613 default:
614 return true;
615 }
Bill Buzbeec6f10662010-02-09 11:16:15 -0800616 rlResult = dvmCompilerGetReturnWide(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700617 storeValueWide(cUnit, rlDest, rlResult);
Ben Chenge9695e52009-06-16 16:11:47 -0700618 return false;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700619}
Ben Chenge9695e52009-06-16 16:11:47 -0700620
Ben Cheng5d90c202009-11-22 23:31:11 -0800621static bool genArithOpLong(CompilationUnit *cUnit, MIR *mir,
622 RegLocation rlDest, RegLocation rlSrc1,
623 RegLocation rlSrc2)
Ben Chengba4fc8b2009-06-01 13:00:29 -0700624{
Bill Buzbee1465db52009-09-23 17:17:35 -0700625 RegLocation rlResult;
626 OpKind firstOp = kOpBkpt;
627 OpKind secondOp = kOpBkpt;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700628 bool callOut = false;
629 void *callTgt;
630 int retReg = r0;
631 /* TODO - find proper .h file to declare these */
632 long long __aeabi_ldivmod(long long op1, long long op2);
633
634 switch (mir->dalvikInsn.opCode) {
635 case OP_NOT_LONG:
Bill Buzbee1465db52009-09-23 17:17:35 -0700636 rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800637 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -0700638 opRegReg(cUnit, kOpMvn, rlResult.lowReg, rlSrc2.lowReg);
639 opRegReg(cUnit, kOpMvn, rlResult.highReg, rlSrc2.highReg);
640 storeValueWide(cUnit, rlDest, rlResult);
641 return false;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700642 break;
643 case OP_ADD_LONG:
644 case OP_ADD_LONG_2ADDR:
Bill Buzbee1465db52009-09-23 17:17:35 -0700645 firstOp = kOpAdd;
646 secondOp = kOpAdc;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700647 break;
648 case OP_SUB_LONG:
649 case OP_SUB_LONG_2ADDR:
Bill Buzbee1465db52009-09-23 17:17:35 -0700650 firstOp = kOpSub;
651 secondOp = kOpSbc;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700652 break;
653 case OP_MUL_LONG:
654 case OP_MUL_LONG_2ADDR:
Bill Buzbee1465db52009-09-23 17:17:35 -0700655 genMulLong(cUnit, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700656 return false;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700657 case OP_DIV_LONG:
658 case OP_DIV_LONG_2ADDR:
659 callOut = true;
660 retReg = r0;
661 callTgt = (void*)__aeabi_ldivmod;
662 break;
663 /* NOTE - result is in r2/r3 instead of r0/r1 */
664 case OP_REM_LONG:
665 case OP_REM_LONG_2ADDR:
666 callOut = true;
667 callTgt = (void*)__aeabi_ldivmod;
668 retReg = r2;
669 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700670 case OP_AND_LONG_2ADDR:
Bill Buzbee1465db52009-09-23 17:17:35 -0700671 case OP_AND_LONG:
672 firstOp = kOpAnd;
673 secondOp = kOpAnd;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700674 break;
675 case OP_OR_LONG:
676 case OP_OR_LONG_2ADDR:
Bill Buzbee1465db52009-09-23 17:17:35 -0700677 firstOp = kOpOr;
678 secondOp = kOpOr;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700679 break;
680 case OP_XOR_LONG:
681 case OP_XOR_LONG_2ADDR:
Bill Buzbee1465db52009-09-23 17:17:35 -0700682 firstOp = kOpXor;
683 secondOp = kOpXor;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700684 break;
Ben Chenge9695e52009-06-16 16:11:47 -0700685 case OP_NEG_LONG: {
Bill Buzbee51ecf602010-01-14 14:27:52 -0800686 //TUNING: can improve this using Thumb2 code
Bill Buzbeec6f10662010-02-09 11:16:15 -0800687 int tReg = dvmCompilerAllocTemp(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700688 rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800689 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee51ecf602010-01-14 14:27:52 -0800690 loadConstantValue(cUnit, tReg, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -0700691 opRegRegReg(cUnit, kOpSub, rlResult.lowReg,
Bill Buzbee51ecf602010-01-14 14:27:52 -0800692 tReg, rlSrc2.lowReg);
693 opRegReg(cUnit, kOpSbc, tReg, rlSrc2.highReg);
694 genRegCopy(cUnit, rlResult.highReg, tReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700695 storeValueWide(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700696 return false;
Ben Chenge9695e52009-06-16 16:11:47 -0700697 }
Ben Chengba4fc8b2009-06-01 13:00:29 -0700698 default:
699 LOGE("Invalid long arith op");
Bill Buzbeefc519dc2010-03-06 23:30:57 -0800700 dvmCompilerAbort(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700701 }
702 if (!callOut) {
Bill Buzbee1465db52009-09-23 17:17:35 -0700703 genLong3Addr(cUnit, firstOp, secondOp, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700704 } else {
Bill Buzbee1465db52009-09-23 17:17:35 -0700705 // Adjust return regs in to handle case of rem returning r2/r3
Bill Buzbeec6f10662010-02-09 11:16:15 -0800706 dvmCompilerFlushAllRegs(cUnit); /* Send everything to home location */
Bill Buzbee1465db52009-09-23 17:17:35 -0700707 loadValueDirectWideFixed(cUnit, rlSrc1, r0, r1);
708 loadConstant(cUnit, rlr, (int) callTgt);
709 loadValueDirectWideFixed(cUnit, rlSrc2, r2, r3);
710 opReg(cUnit, kOpBlx, rlr);
Elliott Hughes6a555132010-02-25 15:41:42 -0800711 dvmCompilerClobberCallRegs(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700712 if (retReg == r0)
Bill Buzbeec6f10662010-02-09 11:16:15 -0800713 rlResult = dvmCompilerGetReturnWide(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700714 else
Bill Buzbeec6f10662010-02-09 11:16:15 -0800715 rlResult = dvmCompilerGetReturnWideAlt(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700716 storeValueWide(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700717 }
718 return false;
719}
720
Ben Cheng5d90c202009-11-22 23:31:11 -0800721static bool genArithOpInt(CompilationUnit *cUnit, MIR *mir,
722 RegLocation rlDest, RegLocation rlSrc1,
723 RegLocation rlSrc2)
Ben Chengba4fc8b2009-06-01 13:00:29 -0700724{
Bill Buzbee1465db52009-09-23 17:17:35 -0700725 OpKind op = kOpBkpt;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700726 bool callOut = false;
727 bool checkZero = false;
Bill Buzbee1465db52009-09-23 17:17:35 -0700728 bool unary = false;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700729 int retReg = r0;
730 void *callTgt;
Bill Buzbee1465db52009-09-23 17:17:35 -0700731 RegLocation rlResult;
Bill Buzbee0e605272009-12-01 14:28:05 -0800732 bool shiftOp = false;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700733
734 /* TODO - find proper .h file to declare these */
735 int __aeabi_idivmod(int op1, int op2);
736 int __aeabi_idiv(int op1, int op2);
737
738 switch (mir->dalvikInsn.opCode) {
739 case OP_NEG_INT:
Bill Buzbee1465db52009-09-23 17:17:35 -0700740 op = kOpNeg;
741 unary = true;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700742 break;
743 case OP_NOT_INT:
Bill Buzbee1465db52009-09-23 17:17:35 -0700744 op = kOpMvn;
745 unary = true;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700746 break;
747 case OP_ADD_INT:
748 case OP_ADD_INT_2ADDR:
Bill Buzbee1465db52009-09-23 17:17:35 -0700749 op = kOpAdd;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700750 break;
751 case OP_SUB_INT:
752 case OP_SUB_INT_2ADDR:
Bill Buzbee1465db52009-09-23 17:17:35 -0700753 op = kOpSub;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700754 break;
755 case OP_MUL_INT:
756 case OP_MUL_INT_2ADDR:
Bill Buzbee1465db52009-09-23 17:17:35 -0700757 op = kOpMul;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700758 break;
759 case OP_DIV_INT:
760 case OP_DIV_INT_2ADDR:
761 callOut = true;
762 checkZero = true;
763 callTgt = __aeabi_idiv;
764 retReg = r0;
765 break;
766 /* NOTE: returns in r1 */
767 case OP_REM_INT:
768 case OP_REM_INT_2ADDR:
769 callOut = true;
770 checkZero = true;
771 callTgt = __aeabi_idivmod;
772 retReg = r1;
773 break;
774 case OP_AND_INT:
775 case OP_AND_INT_2ADDR:
Bill Buzbee1465db52009-09-23 17:17:35 -0700776 op = kOpAnd;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700777 break;
778 case OP_OR_INT:
779 case OP_OR_INT_2ADDR:
Bill Buzbee1465db52009-09-23 17:17:35 -0700780 op = kOpOr;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700781 break;
782 case OP_XOR_INT:
783 case OP_XOR_INT_2ADDR:
Bill Buzbee1465db52009-09-23 17:17:35 -0700784 op = kOpXor;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700785 break;
786 case OP_SHL_INT:
787 case OP_SHL_INT_2ADDR:
Bill Buzbee0e605272009-12-01 14:28:05 -0800788 shiftOp = true;
Bill Buzbee1465db52009-09-23 17:17:35 -0700789 op = kOpLsl;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700790 break;
791 case OP_SHR_INT:
792 case OP_SHR_INT_2ADDR:
Bill Buzbee0e605272009-12-01 14:28:05 -0800793 shiftOp = true;
Bill Buzbee1465db52009-09-23 17:17:35 -0700794 op = kOpAsr;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700795 break;
796 case OP_USHR_INT:
797 case OP_USHR_INT_2ADDR:
Bill Buzbee0e605272009-12-01 14:28:05 -0800798 shiftOp = true;
Bill Buzbee1465db52009-09-23 17:17:35 -0700799 op = kOpLsr;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700800 break;
801 default:
802 LOGE("Invalid word arith op: 0x%x(%d)",
803 mir->dalvikInsn.opCode, mir->dalvikInsn.opCode);
Bill Buzbeefc519dc2010-03-06 23:30:57 -0800804 dvmCompilerAbort(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700805 }
806 if (!callOut) {
Bill Buzbee1465db52009-09-23 17:17:35 -0700807 rlSrc1 = loadValue(cUnit, rlSrc1, kCoreReg);
808 if (unary) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800809 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -0700810 opRegReg(cUnit, op, rlResult.lowReg,
811 rlSrc1.lowReg);
Ben Chenge9695e52009-06-16 16:11:47 -0700812 } else {
Bill Buzbee1465db52009-09-23 17:17:35 -0700813 rlSrc2 = loadValue(cUnit, rlSrc2, kCoreReg);
Bill Buzbee0e605272009-12-01 14:28:05 -0800814 if (shiftOp) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800815 int tReg = dvmCompilerAllocTemp(cUnit);
Bill Buzbee0e605272009-12-01 14:28:05 -0800816 opRegRegImm(cUnit, kOpAnd, tReg, rlSrc2.lowReg, 31);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800817 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee0e605272009-12-01 14:28:05 -0800818 opRegRegReg(cUnit, op, rlResult.lowReg,
819 rlSrc1.lowReg, tReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800820 dvmCompilerFreeTemp(cUnit, tReg);
Bill Buzbee0e605272009-12-01 14:28:05 -0800821 } else {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800822 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee0e605272009-12-01 14:28:05 -0800823 opRegRegReg(cUnit, op, rlResult.lowReg,
824 rlSrc1.lowReg, rlSrc2.lowReg);
825 }
Ben Chenge9695e52009-06-16 16:11:47 -0700826 }
Bill Buzbee1465db52009-09-23 17:17:35 -0700827 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700828 } else {
Bill Buzbee1465db52009-09-23 17:17:35 -0700829 RegLocation rlResult;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800830 dvmCompilerFlushAllRegs(cUnit); /* Send everything to home location */
Bill Buzbee1465db52009-09-23 17:17:35 -0700831 loadValueDirectFixed(cUnit, rlSrc2, r1);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700832 loadConstant(cUnit, r2, (int) callTgt);
Bill Buzbee1465db52009-09-23 17:17:35 -0700833 loadValueDirectFixed(cUnit, rlSrc1, r0);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700834 if (checkZero) {
Bill Buzbee1465db52009-09-23 17:17:35 -0700835 genNullCheck(cUnit, rlSrc2.sRegLow, r1, mir->offset, NULL);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700836 }
Bill Buzbee1465db52009-09-23 17:17:35 -0700837 opReg(cUnit, kOpBlx, r2);
Elliott Hughes6a555132010-02-25 15:41:42 -0800838 dvmCompilerClobberCallRegs(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700839 if (retReg == r0)
Bill Buzbeec6f10662010-02-09 11:16:15 -0800840 rlResult = dvmCompilerGetReturn(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700841 else
Bill Buzbeec6f10662010-02-09 11:16:15 -0800842 rlResult = dvmCompilerGetReturnAlt(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700843 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700844 }
845 return false;
846}
847
Ben Cheng5d90c202009-11-22 23:31:11 -0800848static bool genArithOp(CompilationUnit *cUnit, MIR *mir)
Ben Chengba4fc8b2009-06-01 13:00:29 -0700849{
850 OpCode opCode = mir->dalvikInsn.opCode;
Bill Buzbee1465db52009-09-23 17:17:35 -0700851 RegLocation rlDest;
852 RegLocation rlSrc1;
853 RegLocation rlSrc2;
854 /* Deduce sizes of operands */
855 if (mir->ssaRep->numUses == 2) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800856 rlSrc1 = dvmCompilerGetSrc(cUnit, mir, 0);
857 rlSrc2 = dvmCompilerGetSrc(cUnit, mir, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -0700858 } else if (mir->ssaRep->numUses == 3) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800859 rlSrc1 = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
860 rlSrc2 = dvmCompilerGetSrc(cUnit, mir, 2);
Bill Buzbee1465db52009-09-23 17:17:35 -0700861 } else {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800862 rlSrc1 = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
863 rlSrc2 = dvmCompilerGetSrcWide(cUnit, mir, 2, 3);
Bill Buzbee1465db52009-09-23 17:17:35 -0700864 assert(mir->ssaRep->numUses == 4);
865 }
866 if (mir->ssaRep->numDefs == 1) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800867 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -0700868 } else {
869 assert(mir->ssaRep->numDefs == 2);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800870 rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -0700871 }
Ben Chengba4fc8b2009-06-01 13:00:29 -0700872
873 if ((opCode >= OP_ADD_LONG_2ADDR) && (opCode <= OP_XOR_LONG_2ADDR)) {
Ben Cheng5d90c202009-11-22 23:31:11 -0800874 return genArithOpLong(cUnit,mir, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700875 }
876 if ((opCode >= OP_ADD_LONG) && (opCode <= OP_XOR_LONG)) {
Ben Cheng5d90c202009-11-22 23:31:11 -0800877 return genArithOpLong(cUnit,mir, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700878 }
879 if ((opCode >= OP_SHL_LONG_2ADDR) && (opCode <= OP_USHR_LONG_2ADDR)) {
Ben Cheng5d90c202009-11-22 23:31:11 -0800880 return genShiftOpLong(cUnit,mir, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700881 }
882 if ((opCode >= OP_SHL_LONG) && (opCode <= OP_USHR_LONG)) {
Ben Cheng5d90c202009-11-22 23:31:11 -0800883 return genShiftOpLong(cUnit,mir, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700884 }
885 if ((opCode >= OP_ADD_INT_2ADDR) && (opCode <= OP_USHR_INT_2ADDR)) {
Ben Cheng5d90c202009-11-22 23:31:11 -0800886 return genArithOpInt(cUnit,mir, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700887 }
888 if ((opCode >= OP_ADD_INT) && (opCode <= OP_USHR_INT)) {
Ben Cheng5d90c202009-11-22 23:31:11 -0800889 return genArithOpInt(cUnit,mir, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700890 }
891 if ((opCode >= OP_ADD_FLOAT_2ADDR) && (opCode <= OP_REM_FLOAT_2ADDR)) {
Ben Cheng5d90c202009-11-22 23:31:11 -0800892 return genArithOpFloat(cUnit,mir, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700893 }
894 if ((opCode >= OP_ADD_FLOAT) && (opCode <= OP_REM_FLOAT)) {
Ben Cheng5d90c202009-11-22 23:31:11 -0800895 return genArithOpFloat(cUnit, mir, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700896 }
897 if ((opCode >= OP_ADD_DOUBLE_2ADDR) && (opCode <= OP_REM_DOUBLE_2ADDR)) {
Ben Cheng5d90c202009-11-22 23:31:11 -0800898 return genArithOpDouble(cUnit,mir, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700899 }
900 if ((opCode >= OP_ADD_DOUBLE) && (opCode <= OP_REM_DOUBLE)) {
Ben Cheng5d90c202009-11-22 23:31:11 -0800901 return genArithOpDouble(cUnit,mir, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700902 }
903 return true;
904}
905
Bill Buzbee1465db52009-09-23 17:17:35 -0700906/* Generate unconditional branch instructions */
907static ArmLIR *genUnconditionalBranch(CompilationUnit *cUnit, ArmLIR *target)
908{
909 ArmLIR *branch = opNone(cUnit, kOpUncondBr);
910 branch->generic.target = (LIR *) target;
911 return branch;
912}
913
Bill Buzbee1465db52009-09-23 17:17:35 -0700914/* Perform the actual operation for OP_RETURN_* */
915static void genReturnCommon(CompilationUnit *cUnit, MIR *mir)
916{
917 genDispatchToHandler(cUnit, TEMPLATE_RETURN);
Ben Cheng86717f72010-03-05 15:27:21 -0800918#if defined(JIT_STATS)
Bill Buzbee1465db52009-09-23 17:17:35 -0700919 gDvmJit.returnOp++;
920#endif
921 int dPC = (int) (cUnit->method->insns + mir->offset);
922 /* Insert branch, but defer setting of target */
923 ArmLIR *branch = genUnconditionalBranch(cUnit, NULL);
924 /* Set up the place holder to reconstruct this Dalvik PC */
925 ArmLIR *pcrLabel = dvmCompilerNew(sizeof(ArmLIR), true);
926 pcrLabel->opCode = ARM_PSEUDO_kPCReconstruction_CELL;
927 pcrLabel->operands[0] = dPC;
928 pcrLabel->operands[1] = mir->offset;
929 /* Insert the place holder to the growable list */
930 dvmInsertGrowableList(&cUnit->pcReconstructionList, pcrLabel);
931 /* Branch to the PC reconstruction code */
932 branch->generic.target = (LIR *) pcrLabel;
933}
934
Ben Chengba4fc8b2009-06-01 13:00:29 -0700935static void genProcessArgsNoRange(CompilationUnit *cUnit, MIR *mir,
936 DecodedInstruction *dInsn,
Bill Buzbee89efc3d2009-07-28 11:22:22 -0700937 ArmLIR **pcrLabel)
Ben Chengba4fc8b2009-06-01 13:00:29 -0700938{
939 unsigned int i;
940 unsigned int regMask = 0;
Bill Buzbee1465db52009-09-23 17:17:35 -0700941 RegLocation rlArg;
942 int numDone = 0;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700943
Bill Buzbee1465db52009-09-23 17:17:35 -0700944 /*
945 * Load arguments to r0..r4. Note that these registers may contain
946 * live values, so we clobber them immediately after loading to prevent
947 * them from being used as sources for subsequent loads.
948 */
Bill Buzbeec6f10662010-02-09 11:16:15 -0800949 dvmCompilerLockAllTemps(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700950 for (i = 0; i < dInsn->vA; i++) {
951 regMask |= 1 << i;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800952 rlArg = dvmCompilerGetSrc(cUnit, mir, numDone++);
Bill Buzbee1465db52009-09-23 17:17:35 -0700953 loadValueDirectFixed(cUnit, rlArg, i);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700954 }
955 if (regMask) {
956 /* Up to 5 args are pushed on top of FP - sizeofStackSaveArea */
Bill Buzbee1465db52009-09-23 17:17:35 -0700957 opRegRegImm(cUnit, kOpSub, r7, rFP,
958 sizeof(StackSaveArea) + (dInsn->vA << 2));
Ben Chengba4fc8b2009-06-01 13:00:29 -0700959 /* generate null check */
960 if (pcrLabel) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800961 *pcrLabel = genNullCheck(cUnit, dvmCompilerSSASrc(mir, 0), r0,
Bill Buzbee1465db52009-09-23 17:17:35 -0700962 mir->offset, NULL);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700963 }
Bill Buzbee270c1d62009-08-13 16:58:07 -0700964 storeMultiple(cUnit, r7, regMask);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700965 }
966}
967
968static void genProcessArgsRange(CompilationUnit *cUnit, MIR *mir,
969 DecodedInstruction *dInsn,
Bill Buzbee89efc3d2009-07-28 11:22:22 -0700970 ArmLIR **pcrLabel)
Ben Chengba4fc8b2009-06-01 13:00:29 -0700971{
972 int srcOffset = dInsn->vC << 2;
973 int numArgs = dInsn->vA;
974 int regMask;
Bill Buzbee1465db52009-09-23 17:17:35 -0700975
976 /*
977 * Note: here, all promoted registers will have been flushed
978 * back to the Dalvik base locations, so register usage restrictins
979 * are lifted. All parms loaded from original Dalvik register
980 * region - even though some might conceivably have valid copies
981 * cached in a preserved register.
982 */
Bill Buzbeec6f10662010-02-09 11:16:15 -0800983 dvmCompilerLockAllTemps(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700984
Ben Chengba4fc8b2009-06-01 13:00:29 -0700985 /*
986 * r4PC : &rFP[vC]
987 * r7: &newFP[0]
988 */
Bill Buzbee1465db52009-09-23 17:17:35 -0700989 opRegRegImm(cUnit, kOpAdd, r4PC, rFP, srcOffset);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700990 /* load [r0 .. min(numArgs,4)] */
991 regMask = (1 << ((numArgs < 4) ? numArgs : 4)) - 1;
Ben Chengd7d426a2009-09-22 11:23:36 -0700992 /*
993 * Protect the loadMultiple instruction from being reordered with other
994 * Dalvik stack accesses.
995 */
Bill Buzbee270c1d62009-08-13 16:58:07 -0700996 loadMultiple(cUnit, r4PC, regMask);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700997
Bill Buzbee1465db52009-09-23 17:17:35 -0700998 opRegRegImm(cUnit, kOpSub, r7, rFP,
999 sizeof(StackSaveArea) + (numArgs << 2));
Ben Chengba4fc8b2009-06-01 13:00:29 -07001000 /* generate null check */
1001 if (pcrLabel) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001002 *pcrLabel = genNullCheck(cUnit, dvmCompilerSSASrc(mir, 0), r0,
Bill Buzbee1465db52009-09-23 17:17:35 -07001003 mir->offset, NULL);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001004 }
1005
1006 /*
1007 * Handle remaining 4n arguments:
1008 * store previously loaded 4 values and load the next 4 values
1009 */
1010 if (numArgs >= 8) {
Bill Buzbee89efc3d2009-07-28 11:22:22 -07001011 ArmLIR *loopLabel = NULL;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001012 /*
1013 * r0 contains "this" and it will be used later, so push it to the stack
Bill Buzbee270c1d62009-08-13 16:58:07 -07001014 * first. Pushing r5 (rFP) is just for stack alignment purposes.
Ben Chengba4fc8b2009-06-01 13:00:29 -07001015 */
Bill Buzbee1465db52009-09-23 17:17:35 -07001016 opImm(cUnit, kOpPush, (1 << r0 | 1 << rFP));
Ben Chengba4fc8b2009-06-01 13:00:29 -07001017 /* No need to generate the loop structure if numArgs <= 11 */
1018 if (numArgs > 11) {
1019 loadConstant(cUnit, 5, ((numArgs - 4) >> 2) << 2);
Bill Buzbee1465db52009-09-23 17:17:35 -07001020 loopLabel = newLIR0(cUnit, kArmPseudoTargetLabel);
Ben Chengd7d426a2009-09-22 11:23:36 -07001021 loopLabel->defMask = ENCODE_ALL;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001022 }
Bill Buzbee270c1d62009-08-13 16:58:07 -07001023 storeMultiple(cUnit, r7, regMask);
Ben Chengd7d426a2009-09-22 11:23:36 -07001024 /*
1025 * Protect the loadMultiple instruction from being reordered with other
1026 * Dalvik stack accesses.
1027 */
Bill Buzbee270c1d62009-08-13 16:58:07 -07001028 loadMultiple(cUnit, r4PC, regMask);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001029 /* No need to generate the loop structure if numArgs <= 11 */
1030 if (numArgs > 11) {
Bill Buzbee1465db52009-09-23 17:17:35 -07001031 opRegImm(cUnit, kOpSub, rFP, 4);
1032 genConditionalBranch(cUnit, kArmCondNe, loopLabel);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001033 }
1034 }
1035
1036 /* Save the last batch of loaded values */
Bill Buzbee270c1d62009-08-13 16:58:07 -07001037 storeMultiple(cUnit, r7, regMask);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001038
1039 /* Generate the loop epilogue - don't use r0 */
1040 if ((numArgs > 4) && (numArgs % 4)) {
1041 regMask = ((1 << (numArgs & 0x3)) - 1) << 1;
Ben Chengd7d426a2009-09-22 11:23:36 -07001042 /*
1043 * Protect the loadMultiple instruction from being reordered with other
1044 * Dalvik stack accesses.
1045 */
Bill Buzbee270c1d62009-08-13 16:58:07 -07001046 loadMultiple(cUnit, r4PC, regMask);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001047 }
1048 if (numArgs >= 8)
Bill Buzbee1465db52009-09-23 17:17:35 -07001049 opImm(cUnit, kOpPop, (1 << r0 | 1 << rFP));
Ben Chengba4fc8b2009-06-01 13:00:29 -07001050
1051 /* Save the modulo 4 arguments */
1052 if ((numArgs > 4) && (numArgs % 4)) {
Bill Buzbee270c1d62009-08-13 16:58:07 -07001053 storeMultiple(cUnit, r7, regMask);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001054 }
1055}
1056
Ben Cheng38329f52009-07-07 14:19:20 -07001057/*
1058 * Generate code to setup the call stack then jump to the chaining cell if it
1059 * is not a native method.
1060 */
1061static void genInvokeSingletonCommon(CompilationUnit *cUnit, MIR *mir,
Bill Buzbee89efc3d2009-07-28 11:22:22 -07001062 BasicBlock *bb, ArmLIR *labelList,
1063 ArmLIR *pcrLabel,
Ben Cheng38329f52009-07-07 14:19:20 -07001064 const Method *calleeMethod)
Ben Chengba4fc8b2009-06-01 13:00:29 -07001065{
Bill Buzbee1465db52009-09-23 17:17:35 -07001066 /*
1067 * Note: all Dalvik register state should be flushed to
1068 * memory by the point, so register usage restrictions no
1069 * longer apply. All temp & preserved registers may be used.
1070 */
Bill Buzbeec6f10662010-02-09 11:16:15 -08001071 dvmCompilerLockAllTemps(cUnit);
Bill Buzbee89efc3d2009-07-28 11:22:22 -07001072 ArmLIR *retChainingCell = &labelList[bb->fallThrough->id];
Ben Chengba4fc8b2009-06-01 13:00:29 -07001073
1074 /* r1 = &retChainingCell */
Bill Buzbeec6f10662010-02-09 11:16:15 -08001075 dvmCompilerLockTemp(cUnit, r1);
Bill Buzbee1465db52009-09-23 17:17:35 -07001076 ArmLIR *addrRetChain = opRegRegImm(cUnit, kOpAdd, r1, rpc, 0);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001077 /* r4PC = dalvikCallsite */
1078 loadConstant(cUnit, r4PC,
1079 (int) (cUnit->method->insns + mir->offset));
1080 addrRetChain->generic.target = (LIR *) retChainingCell;
1081 /*
Ben Cheng38329f52009-07-07 14:19:20 -07001082 * r0 = calleeMethod (loaded upon calling genInvokeSingletonCommon)
Ben Chengba4fc8b2009-06-01 13:00:29 -07001083 * r1 = &ChainingCell
1084 * r4PC = callsiteDPC
1085 */
1086 if (dvmIsNativeMethod(calleeMethod)) {
Ben Cheng38329f52009-07-07 14:19:20 -07001087 genDispatchToHandler(cUnit, TEMPLATE_INVOKE_METHOD_NATIVE);
Ben Cheng86717f72010-03-05 15:27:21 -08001088#if defined(JIT_STATS)
Ben Cheng38329f52009-07-07 14:19:20 -07001089 gDvmJit.invokeNative++;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001090#endif
1091 } else {
1092 genDispatchToHandler(cUnit, TEMPLATE_INVOKE_METHOD_CHAIN);
Ben Cheng86717f72010-03-05 15:27:21 -08001093#if defined(JIT_STATS)
1094 gDvmJit.invokeMonomorphic++;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001095#endif
Ben Cheng38329f52009-07-07 14:19:20 -07001096 /* Branch to the chaining cell */
Ben Chengba4fc8b2009-06-01 13:00:29 -07001097 genUnconditionalBranch(cUnit, &labelList[bb->taken->id]);
1098 }
1099 /* Handle exceptions using the interpreter */
1100 genTrap(cUnit, mir->offset, pcrLabel);
1101}
1102
Ben Cheng38329f52009-07-07 14:19:20 -07001103/*
1104 * Generate code to check the validity of a predicted chain and take actions
1105 * based on the result.
1106 *
1107 * 0x426a99aa : ldr r4, [pc, #72] --> r4 <- dalvikPC of this invoke
1108 * 0x426a99ac : add r1, pc, #32 --> r1 <- &retChainingCell
1109 * 0x426a99ae : add r2, pc, #40 --> r2 <- &predictedChainingCell
1110 * 0x426a99b0 : blx_1 0x426a918c --+ TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN
1111 * 0x426a99b2 : blx_2 see above --+
1112 * 0x426a99b4 : b 0x426a99d8 --> off to the predicted chain
1113 * 0x426a99b6 : b 0x426a99c8 --> punt to the interpreter
1114 * 0x426a99b8 : ldr r0, [r7, #44] --> r0 <- this->class->vtable[methodIdx]
1115 * 0x426a99ba : cmp r1, #0 --> compare r1 (rechain count) against 0
1116 * 0x426a99bc : bgt 0x426a99c2 --> >=0? don't rechain
1117 * 0x426a99be : ldr r7, [r6, #96] --+ dvmJitToPatchPredictedChain
1118 * 0x426a99c0 : blx r7 --+
1119 * 0x426a99c2 : add r1, pc, #12 --> r1 <- &retChainingCell
1120 * 0x426a99c4 : blx_1 0x426a9098 --+ TEMPLATE_INVOKE_METHOD_NO_OPT
1121 * 0x426a99c6 : blx_2 see above --+
1122 */
1123static void genInvokeVirtualCommon(CompilationUnit *cUnit, MIR *mir,
1124 int methodIndex,
Bill Buzbee89efc3d2009-07-28 11:22:22 -07001125 ArmLIR *retChainingCell,
1126 ArmLIR *predChainingCell,
1127 ArmLIR *pcrLabel)
Ben Cheng38329f52009-07-07 14:19:20 -07001128{
Bill Buzbee1465db52009-09-23 17:17:35 -07001129 /*
1130 * Note: all Dalvik register state should be flushed to
1131 * memory by the point, so register usage restrictions no
1132 * longer apply. Lock temps to prevent them from being
1133 * allocated by utility routines.
1134 */
Bill Buzbeec6f10662010-02-09 11:16:15 -08001135 dvmCompilerLockAllTemps(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07001136
Ben Cheng38329f52009-07-07 14:19:20 -07001137 /* "this" is already left in r0 by genProcessArgs* */
1138
1139 /* r4PC = dalvikCallsite */
1140 loadConstant(cUnit, r4PC,
1141 (int) (cUnit->method->insns + mir->offset));
1142
1143 /* r1 = &retChainingCell */
Bill Buzbee1465db52009-09-23 17:17:35 -07001144 ArmLIR *addrRetChain = opRegRegImm(cUnit, kOpAdd, r1, rpc, 0);
Ben Cheng38329f52009-07-07 14:19:20 -07001145 addrRetChain->generic.target = (LIR *) retChainingCell;
1146
1147 /* r2 = &predictedChainingCell */
Bill Buzbee1465db52009-09-23 17:17:35 -07001148 ArmLIR *predictedChainingCell = opRegRegImm(cUnit, kOpAdd, r2, rpc, 0);
Ben Cheng38329f52009-07-07 14:19:20 -07001149 predictedChainingCell->generic.target = (LIR *) predChainingCell;
1150
1151 genDispatchToHandler(cUnit, TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN);
1152
1153 /* return through lr - jump to the chaining cell */
1154 genUnconditionalBranch(cUnit, predChainingCell);
1155
1156 /*
1157 * null-check on "this" may have been eliminated, but we still need a PC-
1158 * reconstruction label for stack overflow bailout.
1159 */
1160 if (pcrLabel == NULL) {
1161 int dPC = (int) (cUnit->method->insns + mir->offset);
Bill Buzbee89efc3d2009-07-28 11:22:22 -07001162 pcrLabel = dvmCompilerNew(sizeof(ArmLIR), true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001163 pcrLabel->opCode = ARM_PSEUDO_kPCReconstruction_CELL;
Ben Cheng38329f52009-07-07 14:19:20 -07001164 pcrLabel->operands[0] = dPC;
1165 pcrLabel->operands[1] = mir->offset;
1166 /* Insert the place holder to the growable list */
1167 dvmInsertGrowableList(&cUnit->pcReconstructionList, pcrLabel);
1168 }
1169
1170 /* return through lr+2 - punt to the interpreter */
1171 genUnconditionalBranch(cUnit, pcrLabel);
1172
1173 /*
1174 * return through lr+4 - fully resolve the callee method.
1175 * r1 <- count
1176 * r2 <- &predictedChainCell
1177 * r3 <- this->class
1178 * r4 <- dPC
1179 * r7 <- this->class->vtable
1180 */
1181
1182 /* r0 <- calleeMethod */
Bill Buzbee270c1d62009-08-13 16:58:07 -07001183 loadWordDisp(cUnit, r7, methodIndex * 4, r0);
Ben Cheng38329f52009-07-07 14:19:20 -07001184
1185 /* Check if rechain limit is reached */
Bill Buzbee1465db52009-09-23 17:17:35 -07001186 opRegImm(cUnit, kOpCmp, r1, 0);
Ben Cheng38329f52009-07-07 14:19:20 -07001187
Bill Buzbee1465db52009-09-23 17:17:35 -07001188 ArmLIR *bypassRechaining = opCondBranch(cUnit, kArmCondGt);
Ben Cheng38329f52009-07-07 14:19:20 -07001189
Bill Buzbee270c1d62009-08-13 16:58:07 -07001190 loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
1191 jitToInterpEntries.dvmJitToPatchPredictedChain), r7);
Ben Cheng38329f52009-07-07 14:19:20 -07001192
1193 /*
1194 * r0 = calleeMethod
1195 * r2 = &predictedChainingCell
1196 * r3 = class
1197 *
1198 * &returnChainingCell has been loaded into r1 but is not needed
1199 * when patching the chaining cell and will be clobbered upon
1200 * returning so it will be reconstructed again.
1201 */
Bill Buzbee1465db52009-09-23 17:17:35 -07001202 opReg(cUnit, kOpBlx, r7);
Ben Cheng38329f52009-07-07 14:19:20 -07001203
1204 /* r1 = &retChainingCell */
Bill Buzbee1465db52009-09-23 17:17:35 -07001205 addrRetChain = opRegRegImm(cUnit, kOpAdd, r1, rpc, 0);
Ben Cheng38329f52009-07-07 14:19:20 -07001206 addrRetChain->generic.target = (LIR *) retChainingCell;
1207
1208 bypassRechaining->generic.target = (LIR *) addrRetChain;
1209 /*
1210 * r0 = calleeMethod,
1211 * r1 = &ChainingCell,
1212 * r4PC = callsiteDPC,
1213 */
1214 genDispatchToHandler(cUnit, TEMPLATE_INVOKE_METHOD_NO_OPT);
Ben Cheng86717f72010-03-05 15:27:21 -08001215#if defined(JIT_STATS)
1216 gDvmJit.invokePolymorphic++;
Ben Cheng38329f52009-07-07 14:19:20 -07001217#endif
1218 /* Handle exceptions using the interpreter */
1219 genTrap(cUnit, mir->offset, pcrLabel);
1220}
1221
1222/*
1223 * Up calling this function, "this" is stored in r0. The actual class will be
1224 * chased down off r0 and the predicted one will be retrieved through
1225 * predictedChainingCell then a comparison is performed to see whether the
1226 * previously established chaining is still valid.
1227 *
1228 * The return LIR is a branch based on the comparison result. The actual branch
1229 * target will be setup in the caller.
1230 */
Bill Buzbee89efc3d2009-07-28 11:22:22 -07001231static ArmLIR *genCheckPredictedChain(CompilationUnit *cUnit,
1232 ArmLIR *predChainingCell,
1233 ArmLIR *retChainingCell,
Ben Cheng38329f52009-07-07 14:19:20 -07001234 MIR *mir)
1235{
Bill Buzbee1465db52009-09-23 17:17:35 -07001236 /*
1237 * Note: all Dalvik register state should be flushed to
1238 * memory by the point, so register usage restrictions no
1239 * longer apply. All temp & preserved registers may be used.
1240 */
Bill Buzbeec6f10662010-02-09 11:16:15 -08001241 dvmCompilerLockAllTemps(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07001242
Ben Cheng38329f52009-07-07 14:19:20 -07001243 /* r3 now contains this->clazz */
Bill Buzbee270c1d62009-08-13 16:58:07 -07001244 loadWordDisp(cUnit, r0, offsetof(Object, clazz), r3);
Ben Cheng38329f52009-07-07 14:19:20 -07001245
1246 /*
1247 * r2 now contains predicted class. The starting offset of the
1248 * cached value is 4 bytes into the chaining cell.
1249 */
Bill Buzbee89efc3d2009-07-28 11:22:22 -07001250 ArmLIR *getPredictedClass =
Bill Buzbee270c1d62009-08-13 16:58:07 -07001251 loadWordDisp(cUnit, rpc, offsetof(PredictedChainingCell, clazz), r2);
Ben Cheng38329f52009-07-07 14:19:20 -07001252 getPredictedClass->generic.target = (LIR *) predChainingCell;
1253
1254 /*
1255 * r0 now contains predicted method. The starting offset of the
1256 * cached value is 8 bytes into the chaining cell.
1257 */
Bill Buzbee89efc3d2009-07-28 11:22:22 -07001258 ArmLIR *getPredictedMethod =
Bill Buzbee270c1d62009-08-13 16:58:07 -07001259 loadWordDisp(cUnit, rpc, offsetof(PredictedChainingCell, method), r0);
Ben Cheng38329f52009-07-07 14:19:20 -07001260 getPredictedMethod->generic.target = (LIR *) predChainingCell;
1261
1262 /* Load the stats counter to see if it is time to unchain and refresh */
Bill Buzbee89efc3d2009-07-28 11:22:22 -07001263 ArmLIR *getRechainingRequestCount =
Bill Buzbee270c1d62009-08-13 16:58:07 -07001264 loadWordDisp(cUnit, rpc, offsetof(PredictedChainingCell, counter), r7);
Ben Cheng38329f52009-07-07 14:19:20 -07001265 getRechainingRequestCount->generic.target =
1266 (LIR *) predChainingCell;
1267
1268 /* r4PC = dalvikCallsite */
1269 loadConstant(cUnit, r4PC,
1270 (int) (cUnit->method->insns + mir->offset));
1271
1272 /* r1 = &retChainingCell */
Bill Buzbee1465db52009-09-23 17:17:35 -07001273 ArmLIR *addrRetChain = opRegRegImm(cUnit, kOpAdd, r1, rpc, 0);
Ben Cheng38329f52009-07-07 14:19:20 -07001274 addrRetChain->generic.target = (LIR *) retChainingCell;
1275
1276 /* Check if r2 (predicted class) == r3 (actual class) */
Bill Buzbee1465db52009-09-23 17:17:35 -07001277 opRegReg(cUnit, kOpCmp, r2, r3);
Ben Cheng38329f52009-07-07 14:19:20 -07001278
Bill Buzbee1465db52009-09-23 17:17:35 -07001279 return opCondBranch(cUnit, kArmCondEq);
Ben Cheng38329f52009-07-07 14:19:20 -07001280}
1281
Ben Chengba4fc8b2009-06-01 13:00:29 -07001282/* Geneate a branch to go back to the interpreter */
1283static void genPuntToInterp(CompilationUnit *cUnit, unsigned int offset)
1284{
1285 /* r0 = dalvik pc */
Bill Buzbeec6f10662010-02-09 11:16:15 -08001286 dvmCompilerFlushAllRegs(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001287 loadConstant(cUnit, r0, (int) (cUnit->method->insns + offset));
Bill Buzbee270c1d62009-08-13 16:58:07 -07001288 loadWordDisp(cUnit, r0, offsetof(Object, clazz), r3);
1289 loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
1290 jitToInterpEntries.dvmJitToInterpPunt), r1);
Bill Buzbee1465db52009-09-23 17:17:35 -07001291 opReg(cUnit, kOpBlx, r1);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001292}
1293
1294/*
1295 * Attempt to single step one instruction using the interpreter and return
1296 * to the compiled code for the next Dalvik instruction
1297 */
1298static void genInterpSingleStep(CompilationUnit *cUnit, MIR *mir)
1299{
1300 int flags = dexGetInstrFlags(gDvm.instrFlags, mir->dalvikInsn.opCode);
1301 int flagsToCheck = kInstrCanBranch | kInstrCanSwitch | kInstrCanReturn |
1302 kInstrCanThrow;
Bill Buzbee1465db52009-09-23 17:17:35 -07001303
Bill Buzbee45273872010-03-11 11:12:15 -08001304 //If already optimized out, just ignore
1305 if (mir->dalvikInsn.opCode == OP_NOP)
1306 return;
1307
Bill Buzbee1465db52009-09-23 17:17:35 -07001308 //Ugly, but necessary. Flush all Dalvik regs so Interp can find them
Bill Buzbeec6f10662010-02-09 11:16:15 -08001309 dvmCompilerFlushAllRegs(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07001310
Ben Chengba4fc8b2009-06-01 13:00:29 -07001311 if ((mir->next == NULL) || (flags & flagsToCheck)) {
1312 genPuntToInterp(cUnit, mir->offset);
1313 return;
1314 }
1315 int entryAddr = offsetof(InterpState,
1316 jitToInterpEntries.dvmJitToInterpSingleStep);
Bill Buzbee270c1d62009-08-13 16:58:07 -07001317 loadWordDisp(cUnit, rGLUE, entryAddr, r2);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001318 /* r0 = dalvik pc */
1319 loadConstant(cUnit, r0, (int) (cUnit->method->insns + mir->offset));
1320 /* r1 = dalvik pc of following instruction */
1321 loadConstant(cUnit, r1, (int) (cUnit->method->insns + mir->next->offset));
Bill Buzbee1465db52009-09-23 17:17:35 -07001322 opReg(cUnit, kOpBlx, r2);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001323}
1324
Bill Buzbeec1d9ed42010-02-02 11:04:33 -08001325/*
1326 * To prevent a thread in a monitor wait from blocking the Jit from
1327 * resetting the code cache, heavyweight monitor lock will not
1328 * be allowed to return to an existing translation. Instead, we will
1329 * handle them by branching to a handler, which will in turn call the
1330 * runtime lock routine and then branch directly back to the
1331 * interpreter main loop. Given the high cost of the heavyweight
1332 * lock operation, this additional cost should be slight (especially when
1333 * considering that we expect the vast majority of lock operations to
1334 * use the fast-path thin lock bypass).
1335 */
Ben Cheng5d90c202009-11-22 23:31:11 -08001336static void genMonitorPortable(CompilationUnit *cUnit, MIR *mir)
Bill Buzbee270c1d62009-08-13 16:58:07 -07001337{
Bill Buzbeeefbd3c52009-11-04 22:18:40 -08001338 bool isEnter = (mir->dalvikInsn.opCode == OP_MONITOR_ENTER);
Bill Buzbee1465db52009-09-23 17:17:35 -07001339 genExportPC(cUnit, mir);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001340 dvmCompilerFlushAllRegs(cUnit); /* Send everything to home location */
1341 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001342 loadValueDirectFixed(cUnit, rlSrc, r1);
1343 loadWordDisp(cUnit, rGLUE, offsetof(InterpState, self), r0);
Bill Buzbeec1d9ed42010-02-02 11:04:33 -08001344 genNullCheck(cUnit, rlSrc.sRegLow, r1, mir->offset, NULL);
Bill Buzbeeefbd3c52009-11-04 22:18:40 -08001345 if (isEnter) {
Bill Buzbeec1d9ed42010-02-02 11:04:33 -08001346 /* Get dPC of next insn */
1347 loadConstant(cUnit, r4PC, (int)(cUnit->method->insns + mir->offset +
1348 dexGetInstrWidthAbs(gDvm.instrWidth, OP_MONITOR_ENTER)));
1349#if defined(WITH_DEADLOCK_PREDICTION)
1350 genDispatchToHandler(cUnit, TEMPLATE_MONITOR_ENTER_DEBUG);
1351#else
1352 genDispatchToHandler(cUnit, TEMPLATE_MONITOR_ENTER);
1353#endif
Bill Buzbee1465db52009-09-23 17:17:35 -07001354 } else {
1355 loadConstant(cUnit, r2, (int)dvmUnlockObject);
Bill Buzbeec1d9ed42010-02-02 11:04:33 -08001356 /* Do the call */
1357 opReg(cUnit, kOpBlx, r2);
Bill Buzbee6bbdd6b2010-02-16 14:40:01 -08001358 opRegImm(cUnit, kOpCmp, r0, 0); /* Did we throw? */
1359 ArmLIR *branchOver = opCondBranch(cUnit, kArmCondNe);
1360 loadConstant(cUnit, r0,
1361 (int) (cUnit->method->insns + mir->offset +
1362 dexGetInstrWidthAbs(gDvm.instrWidth, OP_MONITOR_EXIT)));
1363 genDispatchToHandler(cUnit, TEMPLATE_THROW_EXCEPTION_COMMON);
1364 ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel);
1365 target->defMask = ENCODE_ALL;
1366 branchOver->generic.target = (LIR *) target;
Elliott Hughes6a555132010-02-25 15:41:42 -08001367 dvmCompilerClobberCallRegs(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07001368 }
Bill Buzbee270c1d62009-08-13 16:58:07 -07001369}
1370
Ben Chengba4fc8b2009-06-01 13:00:29 -07001371/*
1372 * The following are the first-level codegen routines that analyze the format
1373 * of each bytecode then either dispatch special purpose codegen routines
1374 * or produce corresponding Thumb instructions directly.
1375 */
1376
1377static bool handleFmt10t_Fmt20t_Fmt30t(CompilationUnit *cUnit, MIR *mir,
Bill Buzbee89efc3d2009-07-28 11:22:22 -07001378 BasicBlock *bb, ArmLIR *labelList)
Ben Chengba4fc8b2009-06-01 13:00:29 -07001379{
1380 /* For OP_GOTO, OP_GOTO_16, and OP_GOTO_32 */
1381 genUnconditionalBranch(cUnit, &labelList[bb->taken->id]);
1382 return false;
1383}
1384
1385static bool handleFmt10x(CompilationUnit *cUnit, MIR *mir)
1386{
1387 OpCode dalvikOpCode = mir->dalvikInsn.opCode;
1388 if (((dalvikOpCode >= OP_UNUSED_3E) && (dalvikOpCode <= OP_UNUSED_43)) ||
Andy McFadden96516932009-10-28 17:39:02 -07001389 ((dalvikOpCode >= OP_UNUSED_E3) && (dalvikOpCode <= OP_UNUSED_EB))) {
Ben Chengba4fc8b2009-06-01 13:00:29 -07001390 LOGE("Codegen: got unused opcode 0x%x\n",dalvikOpCode);
1391 return true;
1392 }
1393 switch (dalvikOpCode) {
1394 case OP_RETURN_VOID:
1395 genReturnCommon(cUnit,mir);
1396 break;
1397 case OP_UNUSED_73:
1398 case OP_UNUSED_79:
1399 case OP_UNUSED_7A:
1400 LOGE("Codegen: got unused opcode 0x%x\n",dalvikOpCode);
1401 return true;
1402 case OP_NOP:
1403 break;
1404 default:
1405 return true;
1406 }
1407 return false;
1408}
1409
1410static bool handleFmt11n_Fmt31i(CompilationUnit *cUnit, MIR *mir)
1411{
Bill Buzbee1465db52009-09-23 17:17:35 -07001412 RegLocation rlDest;
1413 RegLocation rlResult;
1414 if (mir->ssaRep->numDefs == 2) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001415 rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -07001416 } else {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001417 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001418 }
Ben Chenge9695e52009-06-16 16:11:47 -07001419
Ben Chengba4fc8b2009-06-01 13:00:29 -07001420 switch (mir->dalvikInsn.opCode) {
1421 case OP_CONST:
Ben Chenge9695e52009-06-16 16:11:47 -07001422 case OP_CONST_4: {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001423 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001424 loadConstantValue(cUnit, rlResult.lowReg, mir->dalvikInsn.vB);
1425 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001426 break;
Ben Chenge9695e52009-06-16 16:11:47 -07001427 }
1428 case OP_CONST_WIDE_32: {
Bill Buzbee1465db52009-09-23 17:17:35 -07001429 //TUNING: single routine to load constant pair for support doubles
Bill Buzbee964a7b02010-01-28 12:54:19 -08001430 //TUNING: load 0/-1 separately to avoid load dependency
Bill Buzbeec6f10662010-02-09 11:16:15 -08001431 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001432 loadConstantValue(cUnit, rlResult.lowReg, mir->dalvikInsn.vB);
1433 opRegRegImm(cUnit, kOpAsr, rlResult.highReg,
1434 rlResult.lowReg, 31);
1435 storeValueWide(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001436 break;
Ben Chenge9695e52009-06-16 16:11:47 -07001437 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07001438 default:
1439 return true;
1440 }
1441 return false;
1442}
1443
1444static bool handleFmt21h(CompilationUnit *cUnit, MIR *mir)
1445{
Bill Buzbee1465db52009-09-23 17:17:35 -07001446 RegLocation rlDest;
1447 RegLocation rlResult;
1448 if (mir->ssaRep->numDefs == 2) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001449 rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -07001450 } else {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001451 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001452 }
Bill Buzbeec6f10662010-02-09 11:16:15 -08001453 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
Ben Chenge9695e52009-06-16 16:11:47 -07001454
Ben Chengba4fc8b2009-06-01 13:00:29 -07001455 switch (mir->dalvikInsn.opCode) {
Ben Chenge9695e52009-06-16 16:11:47 -07001456 case OP_CONST_HIGH16: {
Bill Buzbee1465db52009-09-23 17:17:35 -07001457 loadConstantValue(cUnit, rlResult.lowReg, mir->dalvikInsn.vB << 16);
1458 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001459 break;
Ben Chenge9695e52009-06-16 16:11:47 -07001460 }
1461 case OP_CONST_WIDE_HIGH16: {
Bill Buzbee1465db52009-09-23 17:17:35 -07001462 loadConstantValueWide(cUnit, rlResult.lowReg, rlResult.highReg,
1463 0, mir->dalvikInsn.vB << 16);
1464 storeValueWide(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001465 break;
Ben Chenge9695e52009-06-16 16:11:47 -07001466 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07001467 default:
1468 return true;
1469 }
1470 return false;
1471}
1472
1473static bool handleFmt20bc(CompilationUnit *cUnit, MIR *mir)
1474{
1475 /* For OP_THROW_VERIFICATION_ERROR */
1476 genInterpSingleStep(cUnit, mir);
1477 return false;
1478}
1479
1480static bool handleFmt21c_Fmt31c(CompilationUnit *cUnit, MIR *mir)
1481{
Bill Buzbee1465db52009-09-23 17:17:35 -07001482 RegLocation rlResult;
1483 RegLocation rlDest;
1484 RegLocation rlSrc;
Ben Chenge9695e52009-06-16 16:11:47 -07001485
Ben Chengba4fc8b2009-06-01 13:00:29 -07001486 switch (mir->dalvikInsn.opCode) {
Ben Chengba4fc8b2009-06-01 13:00:29 -07001487 case OP_CONST_STRING_JUMBO:
1488 case OP_CONST_STRING: {
1489 void *strPtr = (void*)
1490 (cUnit->method->clazz->pDvmDex->pResStrings[mir->dalvikInsn.vB]);
1491 assert(strPtr != NULL);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001492 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
1493 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001494 loadConstantValue(cUnit, rlResult.lowReg, (int) strPtr );
1495 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001496 break;
1497 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07001498 case OP_CONST_CLASS: {
1499 void *classPtr = (void*)
1500 (cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vB]);
1501 assert(classPtr != 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) classPtr );
1505 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001506 break;
1507 }
1508 case OP_SGET_OBJECT:
1509 case OP_SGET_BOOLEAN:
1510 case OP_SGET_CHAR:
1511 case OP_SGET_BYTE:
1512 case OP_SGET_SHORT:
1513 case OP_SGET: {
Bill Buzbee50a6bf22009-07-08 13:08:04 -07001514 int valOffset = offsetof(StaticField, value);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001515 int tReg = dvmCompilerAllocTemp(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001516 void *fieldPtr = (void*)
1517 (cUnit->method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vB]);
1518 assert(fieldPtr != NULL);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001519 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
1520 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001521 loadConstant(cUnit, tReg, (int) fieldPtr + valOffset);
jeffhao9e45c0b2010-02-03 10:24:05 -08001522#if defined(WITH_SELF_VERIFICATION)
1523 cUnit->heapMemOp = true;
1524#endif
Bill Buzbee1465db52009-09-23 17:17:35 -07001525 loadWordDisp(cUnit, tReg, 0, rlResult.lowReg);
jeffhao9e45c0b2010-02-03 10:24:05 -08001526#if defined(WITH_SELF_VERIFICATION)
1527 cUnit->heapMemOp = false;
Jeff Hao97319a82009-08-12 16:57:15 -07001528#endif
Bill Buzbee1465db52009-09-23 17:17:35 -07001529 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001530 break;
1531 }
1532 case OP_SGET_WIDE: {
Bill Buzbee50a6bf22009-07-08 13:08:04 -07001533 int valOffset = offsetof(StaticField, value);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001534 void *fieldPtr = (void*)
1535 (cUnit->method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vB]);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001536 int tReg = dvmCompilerAllocTemp(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001537 assert(fieldPtr != NULL);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001538 rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
1539 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001540 loadConstant(cUnit, tReg, (int) fieldPtr + valOffset);
jeffhao9e45c0b2010-02-03 10:24:05 -08001541#if defined(WITH_SELF_VERIFICATION)
1542 cUnit->heapMemOp = true;
1543#endif
Bill Buzbee1465db52009-09-23 17:17:35 -07001544 loadPair(cUnit, tReg, rlResult.lowReg, rlResult.highReg);
jeffhao9e45c0b2010-02-03 10:24:05 -08001545#if defined(WITH_SELF_VERIFICATION)
1546 cUnit->heapMemOp = false;
Jeff Hao97319a82009-08-12 16:57:15 -07001547#endif
Bill Buzbee1465db52009-09-23 17:17:35 -07001548 storeValueWide(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001549 break;
1550 }
1551 case OP_SPUT_OBJECT:
1552 case OP_SPUT_BOOLEAN:
1553 case OP_SPUT_CHAR:
1554 case OP_SPUT_BYTE:
1555 case OP_SPUT_SHORT:
1556 case OP_SPUT: {
Bill Buzbee50a6bf22009-07-08 13:08:04 -07001557 int valOffset = offsetof(StaticField, value);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001558 int tReg = dvmCompilerAllocTemp(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001559 void *fieldPtr = (void*)
1560 (cUnit->method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vB]);
Ben Chenge9695e52009-06-16 16:11:47 -07001561
Ben Chengba4fc8b2009-06-01 13:00:29 -07001562 assert(fieldPtr != NULL);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001563 rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001564 rlSrc = loadValue(cUnit, rlSrc, kAnyReg);
1565 loadConstant(cUnit, tReg, (int) fieldPtr + valOffset);
jeffhao9e45c0b2010-02-03 10:24:05 -08001566#if defined(WITH_SELF_VERIFICATION)
1567 cUnit->heapMemOp = true;
1568#endif
Bill Buzbee1465db52009-09-23 17:17:35 -07001569 storeWordDisp(cUnit, tReg, 0 ,rlSrc.lowReg);
jeffhao9e45c0b2010-02-03 10:24:05 -08001570#if defined(WITH_SELF_VERIFICATION)
1571 cUnit->heapMemOp = false;
Jeff Hao97319a82009-08-12 16:57:15 -07001572#endif
Ben Chengba4fc8b2009-06-01 13:00:29 -07001573 break;
1574 }
1575 case OP_SPUT_WIDE: {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001576 int tReg = dvmCompilerAllocTemp(cUnit);
Bill Buzbee50a6bf22009-07-08 13:08:04 -07001577 int valOffset = offsetof(StaticField, value);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001578 void *fieldPtr = (void*)
1579 (cUnit->method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vB]);
Ben Chenge9695e52009-06-16 16:11:47 -07001580
Ben Chengba4fc8b2009-06-01 13:00:29 -07001581 assert(fieldPtr != NULL);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001582 rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -07001583 rlSrc = loadValueWide(cUnit, rlSrc, kAnyReg);
1584 loadConstant(cUnit, tReg, (int) fieldPtr + valOffset);
jeffhao9e45c0b2010-02-03 10:24:05 -08001585#if defined(WITH_SELF_VERIFICATION)
1586 cUnit->heapMemOp = true;
1587#endif
Bill Buzbee1465db52009-09-23 17:17:35 -07001588 storePair(cUnit, tReg, rlSrc.lowReg, rlSrc.highReg);
jeffhao9e45c0b2010-02-03 10:24:05 -08001589#if defined(WITH_SELF_VERIFICATION)
1590 cUnit->heapMemOp = false;
Jeff Hao97319a82009-08-12 16:57:15 -07001591#endif
Ben Chengba4fc8b2009-06-01 13:00:29 -07001592 break;
1593 }
1594 case OP_NEW_INSTANCE: {
Ben Chenge9695e52009-06-16 16:11:47 -07001595 /*
1596 * Obey the calling convention and don't mess with the register
1597 * usage.
1598 */
Ben Chengba4fc8b2009-06-01 13:00:29 -07001599 ClassObject *classPtr = (void*)
1600 (cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vB]);
1601 assert(classPtr != NULL);
1602 assert(classPtr->status & CLASS_INITIALIZED);
Ben Cheng79d173c2009-09-29 16:12:51 -07001603 /*
1604 * If it is going to throw, it should not make to the trace to begin
Bill Buzbee1465db52009-09-23 17:17:35 -07001605 * with. However, Alloc might throw, so we need to genExportPC()
Ben Cheng79d173c2009-09-29 16:12:51 -07001606 */
1607 assert((classPtr->accessFlags & (ACC_INTERFACE|ACC_ABSTRACT)) == 0);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001608 dvmCompilerFlushAllRegs(cUnit); /* Everything to home location */
Bill Buzbee1465db52009-09-23 17:17:35 -07001609 genExportPC(cUnit, mir);
1610 loadConstant(cUnit, r2, (int)dvmAllocObject);
Ben Chenge9695e52009-06-16 16:11:47 -07001611 loadConstant(cUnit, r0, (int) classPtr);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001612 loadConstant(cUnit, r1, ALLOC_DONT_TRACK);
Bill Buzbee1465db52009-09-23 17:17:35 -07001613 opReg(cUnit, kOpBlx, r2);
Elliott Hughes6a555132010-02-25 15:41:42 -08001614 dvmCompilerClobberCallRegs(cUnit);
Ben Cheng4f489172009-09-27 17:08:35 -07001615 /* generate a branch over if allocation is successful */
Bill Buzbee1465db52009-09-23 17:17:35 -07001616 opRegImm(cUnit, kOpCmp, r0, 0); /* NULL? */
1617 ArmLIR *branchOver = opCondBranch(cUnit, kArmCondNe);
Ben Cheng4f489172009-09-27 17:08:35 -07001618 /*
1619 * OOM exception needs to be thrown here and cannot re-execute
1620 */
1621 loadConstant(cUnit, r0,
1622 (int) (cUnit->method->insns + mir->offset));
1623 genDispatchToHandler(cUnit, TEMPLATE_THROW_EXCEPTION_COMMON);
1624 /* noreturn */
1625
Bill Buzbee1465db52009-09-23 17:17:35 -07001626 ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel);
Ben Cheng4f489172009-09-27 17:08:35 -07001627 target->defMask = ENCODE_ALL;
1628 branchOver->generic.target = (LIR *) target;
Bill Buzbeec6f10662010-02-09 11:16:15 -08001629 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
1630 rlResult = dvmCompilerGetReturn(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07001631 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001632 break;
1633 }
1634 case OP_CHECK_CAST: {
Ben Chenge9695e52009-06-16 16:11:47 -07001635 /*
1636 * Obey the calling convention and don't mess with the register
1637 * usage.
1638 */
Ben Chengba4fc8b2009-06-01 13:00:29 -07001639 ClassObject *classPtr =
1640 (cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vB]);
Bill Buzbee4df41a52009-11-12 17:07:16 -08001641 /*
1642 * Note: It is possible that classPtr is NULL at this point,
1643 * even though this instruction has been successfully interpreted.
1644 * If the previous interpretation had a null source, the
1645 * interpreter would not have bothered to resolve the clazz.
1646 * Bail out to the interpreter in this case, and log it
1647 * so that we can tell if it happens frequently.
1648 */
1649 if (classPtr == NULL) {
1650 LOGD("null clazz in OP_CHECK_CAST, single-stepping");
1651 genInterpSingleStep(cUnit, mir);
1652 return false;
1653 }
Bill Buzbeec6f10662010-02-09 11:16:15 -08001654 dvmCompilerFlushAllRegs(cUnit); /* Everything to home location */
Ben Chengba4fc8b2009-06-01 13:00:29 -07001655 loadConstant(cUnit, r1, (int) classPtr );
Bill Buzbeec6f10662010-02-09 11:16:15 -08001656 rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001657 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
1658 opRegImm(cUnit, kOpCmp, rlSrc.lowReg, 0); /* Null? */
1659 ArmLIR *branch1 = opCondBranch(cUnit, kArmCondEq);
1660 /*
1661 * rlSrc.lowReg now contains object->clazz. Note that
1662 * it could have been allocated r0, but we're okay so long
1663 * as we don't do anything desctructive until r0 is loaded
1664 * with clazz.
1665 */
Ben Chengba4fc8b2009-06-01 13:00:29 -07001666 /* r0 now contains object->clazz */
Bill Buzbee1465db52009-09-23 17:17:35 -07001667 loadWordDisp(cUnit, rlSrc.lowReg, offsetof(Object, clazz), r0);
1668 loadConstant(cUnit, r2, (int)dvmInstanceofNonTrivial);
1669 opRegReg(cUnit, kOpCmp, r0, r1);
1670 ArmLIR *branch2 = opCondBranch(cUnit, kArmCondEq);
1671 opReg(cUnit, kOpBlx, r2);
Elliott Hughes6a555132010-02-25 15:41:42 -08001672 dvmCompilerClobberCallRegs(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07001673 /*
1674 * If null, check cast failed - punt to the interpreter. Because
1675 * interpreter will be the one throwing, we don't need to
1676 * genExportPC() here.
1677 */
Bill Buzbee270c1d62009-08-13 16:58:07 -07001678 genZeroCheck(cUnit, r0, mir->offset, NULL);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001679 /* check cast passed - branch target here */
Bill Buzbee1465db52009-09-23 17:17:35 -07001680 ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel);
Ben Chengd7d426a2009-09-22 11:23:36 -07001681 target->defMask = ENCODE_ALL;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001682 branch1->generic.target = (LIR *)target;
1683 branch2->generic.target = (LIR *)target;
1684 break;
1685 }
1686 default:
1687 return true;
1688 }
1689 return false;
1690}
1691
1692static bool handleFmt11x(CompilationUnit *cUnit, MIR *mir)
1693{
1694 OpCode dalvikOpCode = mir->dalvikInsn.opCode;
Bill Buzbee1465db52009-09-23 17:17:35 -07001695 RegLocation rlResult;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001696 switch (dalvikOpCode) {
1697 case OP_MOVE_EXCEPTION: {
1698 int offset = offsetof(InterpState, self);
1699 int exOffset = offsetof(Thread, exception);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001700 int selfReg = dvmCompilerAllocTemp(cUnit);
1701 int resetReg = dvmCompilerAllocTemp(cUnit);
1702 RegLocation rlDest = dvmCompilerGetDest(cUnit, mir, 0);
1703 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001704 loadWordDisp(cUnit, rGLUE, offset, selfReg);
Bill Buzbeef9f33282009-11-22 12:45:30 -08001705 loadConstant(cUnit, resetReg, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001706 loadWordDisp(cUnit, selfReg, exOffset, rlResult.lowReg);
Bill Buzbeef9f33282009-11-22 12:45:30 -08001707 storeWordDisp(cUnit, selfReg, exOffset, resetReg);
Bill Buzbee1465db52009-09-23 17:17:35 -07001708 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001709 break;
1710 }
1711 case OP_MOVE_RESULT:
1712 case OP_MOVE_RESULT_OBJECT: {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001713 RegLocation rlDest = dvmCompilerGetDest(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001714 RegLocation rlSrc = LOC_DALVIK_RETURN_VAL;
1715 rlSrc.fp = rlDest.fp;
1716 storeValue(cUnit, rlDest, rlSrc);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001717 break;
1718 }
1719 case OP_MOVE_RESULT_WIDE: {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001720 RegLocation rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -07001721 RegLocation rlSrc = LOC_DALVIK_RETURN_VAL_WIDE;
1722 rlSrc.fp = rlDest.fp;
1723 storeValueWide(cUnit, rlDest, rlSrc);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001724 break;
1725 }
1726 case OP_RETURN_WIDE: {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001727 RegLocation rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -07001728 RegLocation rlDest = LOC_DALVIK_RETURN_VAL_WIDE;
1729 rlDest.fp = rlSrc.fp;
1730 storeValueWide(cUnit, rlDest, rlSrc);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001731 genReturnCommon(cUnit,mir);
1732 break;
1733 }
1734 case OP_RETURN:
1735 case OP_RETURN_OBJECT: {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001736 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001737 RegLocation rlDest = LOC_DALVIK_RETURN_VAL;
1738 rlDest.fp = rlSrc.fp;
1739 storeValue(cUnit, rlDest, rlSrc);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001740 genReturnCommon(cUnit,mir);
1741 break;
1742 }
Bill Buzbee1465db52009-09-23 17:17:35 -07001743 case OP_MONITOR_EXIT:
Ben Chengba4fc8b2009-06-01 13:00:29 -07001744 case OP_MONITOR_ENTER:
Bill Buzbeed0937ef2009-12-22 16:15:39 -08001745#if defined(WITH_DEADLOCK_PREDICTION) || defined(WITH_MONITOR_TRACKING)
Ben Cheng5d90c202009-11-22 23:31:11 -08001746 genMonitorPortable(cUnit, mir);
Bill Buzbee1465db52009-09-23 17:17:35 -07001747#else
Ben Cheng5d90c202009-11-22 23:31:11 -08001748 genMonitor(cUnit, mir);
Bill Buzbee1465db52009-09-23 17:17:35 -07001749#endif
Ben Chengba4fc8b2009-06-01 13:00:29 -07001750 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001751 case OP_THROW: {
1752 genInterpSingleStep(cUnit, mir);
1753 break;
1754 }
1755 default:
1756 return true;
1757 }
1758 return false;
1759}
1760
Bill Buzbeed45ba372009-06-15 17:00:57 -07001761static bool handleFmt12x(CompilationUnit *cUnit, MIR *mir)
1762{
1763 OpCode opCode = mir->dalvikInsn.opCode;
Bill Buzbee1465db52009-09-23 17:17:35 -07001764 RegLocation rlDest;
1765 RegLocation rlSrc;
1766 RegLocation rlResult;
Bill Buzbeed45ba372009-06-15 17:00:57 -07001767
Ben Chengba4fc8b2009-06-01 13:00:29 -07001768 if ( (opCode >= OP_ADD_INT_2ADDR) && (opCode <= OP_REM_DOUBLE_2ADDR)) {
Ben Cheng5d90c202009-11-22 23:31:11 -08001769 return genArithOp( cUnit, mir );
Ben Chengba4fc8b2009-06-01 13:00:29 -07001770 }
1771
Bill Buzbee1465db52009-09-23 17:17:35 -07001772 if (mir->ssaRep->numUses == 2)
Bill Buzbeec6f10662010-02-09 11:16:15 -08001773 rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -07001774 else
Bill Buzbeec6f10662010-02-09 11:16:15 -08001775 rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001776 if (mir->ssaRep->numDefs == 2)
Bill Buzbeec6f10662010-02-09 11:16:15 -08001777 rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -07001778 else
Bill Buzbeec6f10662010-02-09 11:16:15 -08001779 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
Ben Chenge9695e52009-06-16 16:11:47 -07001780
Ben Chengba4fc8b2009-06-01 13:00:29 -07001781 switch (opCode) {
Bill Buzbee1465db52009-09-23 17:17:35 -07001782 case OP_DOUBLE_TO_INT:
Ben Chengba4fc8b2009-06-01 13:00:29 -07001783 case OP_INT_TO_FLOAT:
Ben Chengba4fc8b2009-06-01 13:00:29 -07001784 case OP_FLOAT_TO_INT:
Ben Chengba4fc8b2009-06-01 13:00:29 -07001785 case OP_DOUBLE_TO_FLOAT:
Ben Chengba4fc8b2009-06-01 13:00:29 -07001786 case OP_FLOAT_TO_DOUBLE:
Ben Chengba4fc8b2009-06-01 13:00:29 -07001787 case OP_INT_TO_DOUBLE:
Ben Chengba4fc8b2009-06-01 13:00:29 -07001788 case OP_FLOAT_TO_LONG:
Ben Chengba4fc8b2009-06-01 13:00:29 -07001789 case OP_LONG_TO_FLOAT:
Ben Chengba4fc8b2009-06-01 13:00:29 -07001790 case OP_DOUBLE_TO_LONG:
Ben Chengba4fc8b2009-06-01 13:00:29 -07001791 case OP_LONG_TO_DOUBLE:
Ben Cheng5d90c202009-11-22 23:31:11 -08001792 return genConversion(cUnit, mir);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001793 case OP_NEG_INT:
1794 case OP_NOT_INT:
Ben Cheng5d90c202009-11-22 23:31:11 -08001795 return genArithOpInt(cUnit, mir, rlDest, rlSrc, rlSrc);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001796 case OP_NEG_LONG:
1797 case OP_NOT_LONG:
Ben Cheng5d90c202009-11-22 23:31:11 -08001798 return genArithOpLong(cUnit, mir, rlDest, rlSrc, rlSrc);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001799 case OP_NEG_FLOAT:
Ben Cheng5d90c202009-11-22 23:31:11 -08001800 return genArithOpFloat(cUnit, mir, rlDest, rlSrc, rlSrc);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001801 case OP_NEG_DOUBLE:
Ben Cheng5d90c202009-11-22 23:31:11 -08001802 return genArithOpDouble(cUnit, mir, rlDest, rlSrc, rlSrc);
Bill Buzbee1465db52009-09-23 17:17:35 -07001803 case OP_MOVE_WIDE:
1804 storeValueWide(cUnit, rlDest, rlSrc);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001805 break;
Bill Buzbee1465db52009-09-23 17:17:35 -07001806 case OP_INT_TO_LONG:
Bill Buzbeec6f10662010-02-09 11:16:15 -08001807 rlSrc = dvmCompilerUpdateLoc(cUnit, rlSrc);
1808 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee964a7b02010-01-28 12:54:19 -08001809 //TUNING: shouldn't loadValueDirect already check for phys reg?
Bill Buzbee1465db52009-09-23 17:17:35 -07001810 if (rlSrc.location == kLocPhysReg) {
1811 genRegCopy(cUnit, rlResult.lowReg, rlSrc.lowReg);
1812 } else {
1813 loadValueDirect(cUnit, rlSrc, rlResult.lowReg);
1814 }
1815 opRegRegImm(cUnit, kOpAsr, rlResult.highReg,
1816 rlResult.lowReg, 31);
1817 storeValueWide(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001818 break;
Bill Buzbee1465db52009-09-23 17:17:35 -07001819 case OP_LONG_TO_INT:
Bill Buzbeec6f10662010-02-09 11:16:15 -08001820 rlSrc = dvmCompilerUpdateLocWide(cUnit, rlSrc);
1821 rlSrc = dvmCompilerWideToNarrow(cUnit, rlSrc);
Bill Buzbee1465db52009-09-23 17:17:35 -07001822 // Intentional fallthrough
Ben Chengba4fc8b2009-06-01 13:00:29 -07001823 case OP_MOVE:
1824 case OP_MOVE_OBJECT:
Bill Buzbee1465db52009-09-23 17:17:35 -07001825 storeValue(cUnit, rlDest, rlSrc);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001826 break;
1827 case OP_INT_TO_BYTE:
Bill Buzbee1465db52009-09-23 17:17:35 -07001828 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001829 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001830 opRegReg(cUnit, kOp2Byte, rlResult.lowReg, rlSrc.lowReg);
1831 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001832 break;
1833 case OP_INT_TO_SHORT:
Bill Buzbee1465db52009-09-23 17:17:35 -07001834 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001835 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001836 opRegReg(cUnit, kOp2Short, rlResult.lowReg, rlSrc.lowReg);
1837 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001838 break;
1839 case OP_INT_TO_CHAR:
Bill Buzbee1465db52009-09-23 17:17:35 -07001840 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001841 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001842 opRegReg(cUnit, kOp2Char, rlResult.lowReg, rlSrc.lowReg);
1843 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001844 break;
1845 case OP_ARRAY_LENGTH: {
1846 int lenOffset = offsetof(ArrayObject, length);
Bill Buzbee1465db52009-09-23 17:17:35 -07001847 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
1848 genNullCheck(cUnit, rlSrc.sRegLow, rlSrc.lowReg,
1849 mir->offset, NULL);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001850 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001851 loadWordDisp(cUnit, rlSrc.lowReg, lenOffset,
1852 rlResult.lowReg);
1853 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001854 break;
1855 }
1856 default:
1857 return true;
1858 }
1859 return false;
1860}
1861
1862static bool handleFmt21s(CompilationUnit *cUnit, MIR *mir)
1863{
1864 OpCode dalvikOpCode = mir->dalvikInsn.opCode;
Bill Buzbee1465db52009-09-23 17:17:35 -07001865 RegLocation rlDest;
1866 RegLocation rlResult;
1867 int BBBB = mir->dalvikInsn.vB;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001868 if (dalvikOpCode == OP_CONST_WIDE_16) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001869 rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
1870 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001871 loadConstantValue(cUnit, rlResult.lowReg, BBBB);
Bill Buzbee964a7b02010-01-28 12:54:19 -08001872 //TUNING: do high separately to avoid load dependency
Bill Buzbee1465db52009-09-23 17:17:35 -07001873 opRegRegImm(cUnit, kOpAsr, rlResult.highReg, rlResult.lowReg, 31);
1874 storeValueWide(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001875 } else if (dalvikOpCode == OP_CONST_16) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001876 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
1877 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001878 loadConstantValue(cUnit, rlResult.lowReg, BBBB);
1879 storeValue(cUnit, rlDest, rlResult);
1880 } else
Ben Chengba4fc8b2009-06-01 13:00:29 -07001881 return true;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001882 return false;
1883}
1884
1885/* Compare agaist zero */
1886static bool handleFmt21t(CompilationUnit *cUnit, MIR *mir, BasicBlock *bb,
Bill Buzbee89efc3d2009-07-28 11:22:22 -07001887 ArmLIR *labelList)
Ben Chengba4fc8b2009-06-01 13:00:29 -07001888{
1889 OpCode dalvikOpCode = mir->dalvikInsn.opCode;
Bill Buzbee89efc3d2009-07-28 11:22:22 -07001890 ArmConditionCode cond;
Bill Buzbeec6f10662010-02-09 11:16:15 -08001891 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001892 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
1893 opRegImm(cUnit, kOpCmp, rlSrc.lowReg, 0);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001894
Bill Buzbee270c1d62009-08-13 16:58:07 -07001895//TUNING: break this out to allow use of Thumb2 CB[N]Z
Ben Chengba4fc8b2009-06-01 13:00:29 -07001896 switch (dalvikOpCode) {
1897 case OP_IF_EQZ:
Bill Buzbee1465db52009-09-23 17:17:35 -07001898 cond = kArmCondEq;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001899 break;
1900 case OP_IF_NEZ:
Bill Buzbee1465db52009-09-23 17:17:35 -07001901 cond = kArmCondNe;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001902 break;
1903 case OP_IF_LTZ:
Bill Buzbee1465db52009-09-23 17:17:35 -07001904 cond = kArmCondLt;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001905 break;
1906 case OP_IF_GEZ:
Bill Buzbee1465db52009-09-23 17:17:35 -07001907 cond = kArmCondGe;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001908 break;
1909 case OP_IF_GTZ:
Bill Buzbee1465db52009-09-23 17:17:35 -07001910 cond = kArmCondGt;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001911 break;
1912 case OP_IF_LEZ:
Bill Buzbee1465db52009-09-23 17:17:35 -07001913 cond = kArmCondLe;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001914 break;
1915 default:
1916 cond = 0;
1917 LOGE("Unexpected opcode (%d) for Fmt21t\n", dalvikOpCode);
Bill Buzbeefc519dc2010-03-06 23:30:57 -08001918 dvmCompilerAbort(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001919 }
1920 genConditionalBranch(cUnit, cond, &labelList[bb->taken->id]);
1921 /* This mostly likely will be optimized away in a later phase */
1922 genUnconditionalBranch(cUnit, &labelList[bb->fallThrough->id]);
1923 return false;
1924}
1925
Elliott Hughesb4c05972010-02-24 16:36:18 -08001926static bool isPowerOfTwo(int x)
1927{
1928 return (x & (x - 1)) == 0;
1929}
1930
1931// Returns true if no more than two bits are set in 'x'.
1932static bool isPopCountLE2(unsigned int x)
1933{
1934 x &= x - 1;
1935 return (x & (x - 1)) == 0;
1936}
1937
1938// Returns the index of the lowest set bit in 'x'.
1939static int lowestSetBit(unsigned int x) {
1940 int bit_posn = 0;
1941 while ((x & 0xf) == 0) {
1942 bit_posn += 4;
1943 x >>= 4;
Bill Buzbee78cb0e22010-02-11 14:04:53 -08001944 }
Elliott Hughesb4c05972010-02-24 16:36:18 -08001945 while ((x & 1) == 0) {
1946 bit_posn++;
1947 x >>= 1;
1948 }
1949 return bit_posn;
1950}
1951
1952// Returns true if it added instructions to 'cUnit' to multiply 'rlSrc' by 'lit'
1953// and store the result in 'rlDest'.
1954static bool handleEasyMultiply(CompilationUnit *cUnit,
1955 RegLocation rlSrc, RegLocation rlDest, int lit)
1956{
1957 // Can we simplify this multiplication?
1958 bool powerOfTwo = false;
1959 bool popCountLE2 = false;
1960 bool powerOfTwoMinusOne = false;
1961 if (lit < 2) {
1962 // Avoid special cases.
1963 return false;
1964 } else if (isPowerOfTwo(lit)) {
1965 powerOfTwo = true;
1966 } else if (isPopCountLE2(lit)) {
1967 popCountLE2 = true;
1968 } else if (isPowerOfTwo(lit + 1)) {
1969 powerOfTwoMinusOne = true;
1970 } else {
1971 return false;
1972 }
1973 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
1974 RegLocation rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
1975 if (powerOfTwo) {
1976 // Shift.
1977 opRegRegImm(cUnit, kOpLsl, rlResult.lowReg, rlSrc.lowReg,
1978 lowestSetBit(lit));
1979 } else if (popCountLE2) {
1980 // Shift and add and shift.
1981 int firstBit = lowestSetBit(lit);
1982 int secondBit = lowestSetBit(lit ^ (1 << firstBit));
1983 genMultiplyByTwoBitMultiplier(cUnit, rlSrc, rlResult, lit,
1984 firstBit, secondBit);
1985 } else {
1986 // Reverse subtract: (src << (shift + 1)) - src.
1987 assert(powerOfTwoMinusOne);
1988 // TODO: rsb dst, src, src lsl#lowestSetBit(lit + 1)
1989 int tReg = dvmCompilerAllocTemp(cUnit);
1990 opRegRegImm(cUnit, kOpLsl, tReg, rlSrc.lowReg, lowestSetBit(lit + 1));
1991 opRegRegReg(cUnit, kOpSub, rlResult.lowReg, tReg, rlSrc.lowReg);
1992 }
1993 storeValue(cUnit, rlDest, rlResult);
1994 return true;
Bill Buzbee78cb0e22010-02-11 14:04:53 -08001995}
1996
Ben Chengba4fc8b2009-06-01 13:00:29 -07001997static bool handleFmt22b_Fmt22s(CompilationUnit *cUnit, MIR *mir)
1998{
1999 OpCode dalvikOpCode = mir->dalvikInsn.opCode;
Bill Buzbeec6f10662010-02-09 11:16:15 -08002000 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
2001 RegLocation rlDest = dvmCompilerGetDest(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07002002 RegLocation rlResult;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002003 int lit = mir->dalvikInsn.vC;
Ben Cheng4f489172009-09-27 17:08:35 -07002004 OpKind op = 0; /* Make gcc happy */
Bill Buzbee1465db52009-09-23 17:17:35 -07002005 int shiftOp = false;
2006 bool isDiv = false;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002007
Ben Chengba4fc8b2009-06-01 13:00:29 -07002008 int __aeabi_idivmod(int op1, int op2);
2009 int __aeabi_idiv(int op1, int op2);
2010
2011 switch (dalvikOpCode) {
Bill Buzbee1465db52009-09-23 17:17:35 -07002012 case OP_RSUB_INT_LIT8:
2013 case OP_RSUB_INT: {
2014 int tReg;
2015 //TUNING: add support for use of Arm rsub op
2016 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -08002017 tReg = dvmCompilerAllocTemp(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07002018 loadConstant(cUnit, tReg, lit);
Bill Buzbeec6f10662010-02-09 11:16:15 -08002019 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07002020 opRegRegReg(cUnit, kOpSub, rlResult.lowReg,
2021 tReg, rlSrc.lowReg);
2022 storeValue(cUnit, rlDest, rlResult);
2023 return false;
2024 break;
2025 }
2026
Ben Chengba4fc8b2009-06-01 13:00:29 -07002027 case OP_ADD_INT_LIT8:
2028 case OP_ADD_INT_LIT16:
Bill Buzbee1465db52009-09-23 17:17:35 -07002029 op = kOpAdd;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002030 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002031 case OP_MUL_INT_LIT8:
Bill Buzbee78cb0e22010-02-11 14:04:53 -08002032 case OP_MUL_INT_LIT16: {
Elliott Hughesb4c05972010-02-24 16:36:18 -08002033 if (handleEasyMultiply(cUnit, rlSrc, rlDest, lit)) {
2034 return false;
Bill Buzbee78cb0e22010-02-11 14:04:53 -08002035 }
Elliott Hughesb4c05972010-02-24 16:36:18 -08002036 op = kOpMul;
Bill Buzbee1465db52009-09-23 17:17:35 -07002037 break;
Bill Buzbee78cb0e22010-02-11 14:04:53 -08002038 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07002039 case OP_AND_INT_LIT8:
2040 case OP_AND_INT_LIT16:
Bill Buzbee1465db52009-09-23 17:17:35 -07002041 op = kOpAnd;
2042 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002043 case OP_OR_INT_LIT8:
2044 case OP_OR_INT_LIT16:
Bill Buzbee1465db52009-09-23 17:17:35 -07002045 op = kOpOr;
2046 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002047 case OP_XOR_INT_LIT8:
2048 case OP_XOR_INT_LIT16:
Bill Buzbee1465db52009-09-23 17:17:35 -07002049 op = kOpXor;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002050 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002051 case OP_SHL_INT_LIT8:
Bill Buzbee0e605272009-12-01 14:28:05 -08002052 lit &= 31;
Bill Buzbee1465db52009-09-23 17:17:35 -07002053 shiftOp = true;
2054 op = kOpLsl;
2055 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002056 case OP_SHR_INT_LIT8:
Bill Buzbee0e605272009-12-01 14:28:05 -08002057 lit &= 31;
Bill Buzbee1465db52009-09-23 17:17:35 -07002058 shiftOp = true;
2059 op = kOpAsr;
2060 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002061 case OP_USHR_INT_LIT8:
Bill Buzbee0e605272009-12-01 14:28:05 -08002062 lit &= 31;
Bill Buzbee1465db52009-09-23 17:17:35 -07002063 shiftOp = true;
2064 op = kOpLsr;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002065 break;
2066
2067 case OP_DIV_INT_LIT8:
2068 case OP_DIV_INT_LIT16:
Ben Chengba4fc8b2009-06-01 13:00:29 -07002069 case OP_REM_INT_LIT8:
2070 case OP_REM_INT_LIT16:
2071 if (lit == 0) {
2072 /* Let the interpreter deal with div by 0 */
2073 genInterpSingleStep(cUnit, mir);
2074 return false;
2075 }
Bill Buzbeec6f10662010-02-09 11:16:15 -08002076 dvmCompilerFlushAllRegs(cUnit); /* Everything to home location */
Bill Buzbee1465db52009-09-23 17:17:35 -07002077 loadValueDirectFixed(cUnit, rlSrc, r0);
Bill Buzbeec6f10662010-02-09 11:16:15 -08002078 dvmCompilerClobber(cUnit, r0);
Bill Buzbee1465db52009-09-23 17:17:35 -07002079 if ((dalvikOpCode == OP_DIV_INT_LIT8) ||
2080 (dalvikOpCode == OP_DIV_INT_LIT16)) {
2081 loadConstant(cUnit, r2, (int)__aeabi_idiv);
2082 isDiv = true;
2083 } else {
2084 loadConstant(cUnit, r2, (int)__aeabi_idivmod);
2085 isDiv = false;
2086 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07002087 loadConstant(cUnit, r1, lit);
Bill Buzbee1465db52009-09-23 17:17:35 -07002088 opReg(cUnit, kOpBlx, r2);
Elliott Hughes6a555132010-02-25 15:41:42 -08002089 dvmCompilerClobberCallRegs(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07002090 if (isDiv)
Bill Buzbeec6f10662010-02-09 11:16:15 -08002091 rlResult = dvmCompilerGetReturn(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07002092 else
Bill Buzbeec6f10662010-02-09 11:16:15 -08002093 rlResult = dvmCompilerGetReturnAlt(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07002094 storeValue(cUnit, rlDest, rlResult);
2095 return false;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002096 break;
2097 default:
2098 return true;
2099 }
Bill Buzbee1465db52009-09-23 17:17:35 -07002100 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -08002101 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07002102 // Avoid shifts by literal 0 - no support in Thumb. Change to copy
2103 if (shiftOp && (lit == 0)) {
2104 genRegCopy(cUnit, rlResult.lowReg, rlSrc.lowReg);
2105 } else {
2106 opRegRegImm(cUnit, op, rlResult.lowReg, rlSrc.lowReg, lit);
2107 }
2108 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002109 return false;
2110}
2111
2112static bool handleFmt22c(CompilationUnit *cUnit, MIR *mir)
2113{
2114 OpCode dalvikOpCode = mir->dalvikInsn.opCode;
2115 int fieldOffset;
2116
2117 if (dalvikOpCode >= OP_IGET && dalvikOpCode <= OP_IPUT_SHORT) {
2118 InstField *pInstField = (InstField *)
2119 cUnit->method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vC];
Ben Chengba4fc8b2009-06-01 13:00:29 -07002120
2121 assert(pInstField != NULL);
2122 fieldOffset = pInstField->byteOffset;
2123 } else {
Ben Chenga0e7b602009-10-13 23:09:01 -07002124 /* Deliberately break the code while make the compiler happy */
2125 fieldOffset = -1;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002126 }
2127 switch (dalvikOpCode) {
Ben Chengba4fc8b2009-06-01 13:00:29 -07002128 case OP_NEW_ARRAY: {
Bill Buzbee1465db52009-09-23 17:17:35 -07002129 // Generates a call - use explicit registers
Bill Buzbeec6f10662010-02-09 11:16:15 -08002130 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
2131 RegLocation rlDest = dvmCompilerGetDest(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07002132 RegLocation rlResult;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002133 void *classPtr = (void*)
2134 (cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vC]);
2135 assert(classPtr != NULL);
Bill Buzbeec6f10662010-02-09 11:16:15 -08002136 dvmCompilerFlushAllRegs(cUnit); /* Everything to home location */
Bill Buzbee1465db52009-09-23 17:17:35 -07002137 genExportPC(cUnit, mir);
2138 loadValueDirectFixed(cUnit, rlSrc, r1); /* Len */
Ben Chengba4fc8b2009-06-01 13:00:29 -07002139 loadConstant(cUnit, r0, (int) classPtr );
Bill Buzbee1465db52009-09-23 17:17:35 -07002140 loadConstant(cUnit, r3, (int)dvmAllocArrayByClass);
Ben Cheng4f489172009-09-27 17:08:35 -07002141 /*
2142 * "len < 0": bail to the interpreter to re-execute the
2143 * instruction
2144 */
Bill Buzbee89efc3d2009-07-28 11:22:22 -07002145 ArmLIR *pcrLabel =
Bill Buzbee1465db52009-09-23 17:17:35 -07002146 genRegImmCheck(cUnit, kArmCondMi, r1, 0, mir->offset, NULL);
Bill Buzbee270c1d62009-08-13 16:58:07 -07002147 loadConstant(cUnit, r2, ALLOC_DONT_TRACK);
Bill Buzbee1465db52009-09-23 17:17:35 -07002148 opReg(cUnit, kOpBlx, r3);
Elliott Hughes6a555132010-02-25 15:41:42 -08002149 dvmCompilerClobberCallRegs(cUnit);
Ben Cheng4f489172009-09-27 17:08:35 -07002150 /* generate a branch over if allocation is successful */
Bill Buzbee1465db52009-09-23 17:17:35 -07002151 opRegImm(cUnit, kOpCmp, r0, 0); /* NULL? */
2152 ArmLIR *branchOver = opCondBranch(cUnit, kArmCondNe);
Ben Cheng4f489172009-09-27 17:08:35 -07002153 /*
2154 * OOM exception needs to be thrown here and cannot re-execute
2155 */
2156 loadConstant(cUnit, r0,
2157 (int) (cUnit->method->insns + mir->offset));
2158 genDispatchToHandler(cUnit, TEMPLATE_THROW_EXCEPTION_COMMON);
2159 /* noreturn */
2160
Bill Buzbee1465db52009-09-23 17:17:35 -07002161 ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel);
Ben Cheng4f489172009-09-27 17:08:35 -07002162 target->defMask = ENCODE_ALL;
2163 branchOver->generic.target = (LIR *) target;
Bill Buzbeec6f10662010-02-09 11:16:15 -08002164 rlResult = dvmCompilerGetReturn(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07002165 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002166 break;
2167 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07002168 case OP_INSTANCE_OF: {
Bill Buzbee1465db52009-09-23 17:17:35 -07002169 // May generate a call - use explicit registers
Bill Buzbeec6f10662010-02-09 11:16:15 -08002170 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
2171 RegLocation rlDest = dvmCompilerGetDest(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07002172 RegLocation rlResult;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002173 ClassObject *classPtr =
2174 (cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vC]);
Bill Buzbee480e6782010-01-27 15:43:08 -08002175 /*
2176 * Note: It is possible that classPtr is NULL at this point,
2177 * even though this instruction has been successfully interpreted.
2178 * If the previous interpretation had a null source, the
2179 * interpreter would not have bothered to resolve the clazz.
2180 * Bail out to the interpreter in this case, and log it
2181 * so that we can tell if it happens frequently.
2182 */
2183 if (classPtr == NULL) {
2184 LOGD("null clazz in OP_INSTANCE_OF, single-stepping");
2185 genInterpSingleStep(cUnit, mir);
2186 break;
2187 }
Bill Buzbeec6f10662010-02-09 11:16:15 -08002188 dvmCompilerFlushAllRegs(cUnit); /* Everything to home location */
Bill Buzbee1465db52009-09-23 17:17:35 -07002189 loadValueDirectFixed(cUnit, rlSrc, r0); /* Ref */
Ben Chengba4fc8b2009-06-01 13:00:29 -07002190 loadConstant(cUnit, r2, (int) classPtr );
Bill Buzbee270c1d62009-08-13 16:58:07 -07002191//TUNING: compare to 0 primative to allow use of CB[N]Z
Bill Buzbee1465db52009-09-23 17:17:35 -07002192 opRegImm(cUnit, kOpCmp, r0, 0); /* NULL? */
Ben Cheng752c7942009-06-22 10:50:07 -07002193 /* When taken r0 has NULL which can be used for store directly */
Bill Buzbee1465db52009-09-23 17:17:35 -07002194 ArmLIR *branch1 = opCondBranch(cUnit, kArmCondEq);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002195 /* r1 now contains object->clazz */
Bill Buzbee270c1d62009-08-13 16:58:07 -07002196 loadWordDisp(cUnit, r0, offsetof(Object, clazz), r1);
Bill Buzbee1465db52009-09-23 17:17:35 -07002197 /* r1 now contains object->clazz */
2198 loadConstant(cUnit, r3, (int)dvmInstanceofNonTrivial);
Ben Cheng752c7942009-06-22 10:50:07 -07002199 loadConstant(cUnit, r0, 1); /* Assume true */
Bill Buzbee1465db52009-09-23 17:17:35 -07002200 opRegReg(cUnit, kOpCmp, r1, r2);
2201 ArmLIR *branch2 = opCondBranch(cUnit, kArmCondEq);
2202 genRegCopy(cUnit, r0, r1);
2203 genRegCopy(cUnit, r1, r2);
2204 opReg(cUnit, kOpBlx, r3);
Elliott Hughes6a555132010-02-25 15:41:42 -08002205 dvmCompilerClobberCallRegs(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002206 /* branch target here */
Bill Buzbee1465db52009-09-23 17:17:35 -07002207 ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel);
Ben Chengd7d426a2009-09-22 11:23:36 -07002208 target->defMask = ENCODE_ALL;
Bill Buzbeec6f10662010-02-09 11:16:15 -08002209 rlResult = dvmCompilerGetReturn(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07002210 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002211 branch1->generic.target = (LIR *)target;
2212 branch2->generic.target = (LIR *)target;
2213 break;
2214 }
2215 case OP_IGET_WIDE:
2216 genIGetWide(cUnit, mir, fieldOffset);
2217 break;
2218 case OP_IGET:
2219 case OP_IGET_OBJECT:
Bill Buzbee1465db52009-09-23 17:17:35 -07002220 genIGet(cUnit, mir, kWord, fieldOffset);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002221 break;
2222 case OP_IGET_BOOLEAN:
Bill Buzbee1465db52009-09-23 17:17:35 -07002223 genIGet(cUnit, mir, kUnsignedByte, fieldOffset);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002224 break;
2225 case OP_IGET_BYTE:
Bill Buzbee1465db52009-09-23 17:17:35 -07002226 genIGet(cUnit, mir, kSignedByte, fieldOffset);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002227 break;
2228 case OP_IGET_CHAR:
Bill Buzbee1465db52009-09-23 17:17:35 -07002229 genIGet(cUnit, mir, kUnsignedHalf, fieldOffset);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002230 break;
2231 case OP_IGET_SHORT:
Bill Buzbee1465db52009-09-23 17:17:35 -07002232 genIGet(cUnit, mir, kSignedHalf, fieldOffset);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002233 break;
2234 case OP_IPUT_WIDE:
2235 genIPutWide(cUnit, mir, fieldOffset);
2236 break;
2237 case OP_IPUT:
2238 case OP_IPUT_OBJECT:
Bill Buzbee1465db52009-09-23 17:17:35 -07002239 genIPut(cUnit, mir, kWord, fieldOffset);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002240 break;
2241 case OP_IPUT_SHORT:
2242 case OP_IPUT_CHAR:
Bill Buzbee1465db52009-09-23 17:17:35 -07002243 genIPut(cUnit, mir, kUnsignedHalf, fieldOffset);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002244 break;
2245 case OP_IPUT_BYTE:
2246 case OP_IPUT_BOOLEAN:
Bill Buzbee1465db52009-09-23 17:17:35 -07002247 genIPut(cUnit, mir, kUnsignedByte, fieldOffset);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002248 break;
2249 default:
2250 return true;
2251 }
2252 return false;
2253}
2254
2255static bool handleFmt22cs(CompilationUnit *cUnit, MIR *mir)
2256{
2257 OpCode dalvikOpCode = mir->dalvikInsn.opCode;
2258 int fieldOffset = mir->dalvikInsn.vC;
2259 switch (dalvikOpCode) {
2260 case OP_IGET_QUICK:
2261 case OP_IGET_OBJECT_QUICK:
Bill Buzbee1465db52009-09-23 17:17:35 -07002262 genIGet(cUnit, mir, kWord, fieldOffset);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002263 break;
2264 case OP_IPUT_QUICK:
2265 case OP_IPUT_OBJECT_QUICK:
Bill Buzbee1465db52009-09-23 17:17:35 -07002266 genIPut(cUnit, mir, kWord, fieldOffset);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002267 break;
2268 case OP_IGET_WIDE_QUICK:
2269 genIGetWide(cUnit, mir, fieldOffset);
2270 break;
2271 case OP_IPUT_WIDE_QUICK:
2272 genIPutWide(cUnit, mir, fieldOffset);
2273 break;
2274 default:
2275 return true;
2276 }
2277 return false;
2278
2279}
2280
2281/* Compare agaist zero */
2282static bool handleFmt22t(CompilationUnit *cUnit, MIR *mir, BasicBlock *bb,
Bill Buzbee89efc3d2009-07-28 11:22:22 -07002283 ArmLIR *labelList)
Ben Chengba4fc8b2009-06-01 13:00:29 -07002284{
2285 OpCode dalvikOpCode = mir->dalvikInsn.opCode;
Bill Buzbee89efc3d2009-07-28 11:22:22 -07002286 ArmConditionCode cond;
Bill Buzbeec6f10662010-02-09 11:16:15 -08002287 RegLocation rlSrc1 = dvmCompilerGetSrc(cUnit, mir, 0);
2288 RegLocation rlSrc2 = dvmCompilerGetSrc(cUnit, mir, 1);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002289
Bill Buzbee1465db52009-09-23 17:17:35 -07002290 rlSrc1 = loadValue(cUnit, rlSrc1, kCoreReg);
2291 rlSrc2 = loadValue(cUnit, rlSrc2, kCoreReg);
2292 opRegReg(cUnit, kOpCmp, rlSrc1.lowReg, rlSrc2.lowReg);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002293
2294 switch (dalvikOpCode) {
2295 case OP_IF_EQ:
Bill Buzbee1465db52009-09-23 17:17:35 -07002296 cond = kArmCondEq;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002297 break;
2298 case OP_IF_NE:
Bill Buzbee1465db52009-09-23 17:17:35 -07002299 cond = kArmCondNe;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002300 break;
2301 case OP_IF_LT:
Bill Buzbee1465db52009-09-23 17:17:35 -07002302 cond = kArmCondLt;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002303 break;
2304 case OP_IF_GE:
Bill Buzbee1465db52009-09-23 17:17:35 -07002305 cond = kArmCondGe;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002306 break;
2307 case OP_IF_GT:
Bill Buzbee1465db52009-09-23 17:17:35 -07002308 cond = kArmCondGt;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002309 break;
2310 case OP_IF_LE:
Bill Buzbee1465db52009-09-23 17:17:35 -07002311 cond = kArmCondLe;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002312 break;
2313 default:
2314 cond = 0;
2315 LOGE("Unexpected opcode (%d) for Fmt22t\n", dalvikOpCode);
Bill Buzbeefc519dc2010-03-06 23:30:57 -08002316 dvmCompilerAbort(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002317 }
2318 genConditionalBranch(cUnit, cond, &labelList[bb->taken->id]);
2319 /* This mostly likely will be optimized away in a later phase */
2320 genUnconditionalBranch(cUnit, &labelList[bb->fallThrough->id]);
2321 return false;
2322}
2323
2324static bool handleFmt22x_Fmt32x(CompilationUnit *cUnit, MIR *mir)
2325{
2326 OpCode opCode = mir->dalvikInsn.opCode;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002327
2328 switch (opCode) {
2329 case OP_MOVE_16:
2330 case OP_MOVE_OBJECT_16:
2331 case OP_MOVE_FROM16:
Ben Chenge9695e52009-06-16 16:11:47 -07002332 case OP_MOVE_OBJECT_FROM16: {
Bill Buzbeec6f10662010-02-09 11:16:15 -08002333 storeValue(cUnit, dvmCompilerGetDest(cUnit, mir, 0),
2334 dvmCompilerGetSrc(cUnit, mir, 0));
Ben Chengba4fc8b2009-06-01 13:00:29 -07002335 break;
Ben Chenge9695e52009-06-16 16:11:47 -07002336 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07002337 case OP_MOVE_WIDE_16:
Ben Chenge9695e52009-06-16 16:11:47 -07002338 case OP_MOVE_WIDE_FROM16: {
Bill Buzbeec6f10662010-02-09 11:16:15 -08002339 storeValueWide(cUnit, dvmCompilerGetDestWide(cUnit, mir, 0, 1),
2340 dvmCompilerGetSrcWide(cUnit, mir, 0, 1));
Ben Chengba4fc8b2009-06-01 13:00:29 -07002341 break;
Ben Chenge9695e52009-06-16 16:11:47 -07002342 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07002343 default:
2344 return true;
2345 }
2346 return false;
2347}
2348
2349static bool handleFmt23x(CompilationUnit *cUnit, MIR *mir)
2350{
2351 OpCode opCode = mir->dalvikInsn.opCode;
Bill Buzbee1465db52009-09-23 17:17:35 -07002352 RegLocation rlSrc1;
2353 RegLocation rlSrc2;
2354 RegLocation rlDest;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002355
2356 if ( (opCode >= OP_ADD_INT) && (opCode <= OP_REM_DOUBLE)) {
Ben Cheng5d90c202009-11-22 23:31:11 -08002357 return genArithOp( cUnit, mir );
Ben Chengba4fc8b2009-06-01 13:00:29 -07002358 }
2359
Bill Buzbee1465db52009-09-23 17:17:35 -07002360 /* APUTs have 3 sources and no targets */
2361 if (mir->ssaRep->numDefs == 0) {
2362 if (mir->ssaRep->numUses == 3) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08002363 rlDest = dvmCompilerGetSrc(cUnit, mir, 0);
2364 rlSrc1 = dvmCompilerGetSrc(cUnit, mir, 1);
2365 rlSrc2 = dvmCompilerGetSrc(cUnit, mir, 2);
Bill Buzbee1465db52009-09-23 17:17:35 -07002366 } else {
2367 assert(mir->ssaRep->numUses == 4);
Bill Buzbeec6f10662010-02-09 11:16:15 -08002368 rlDest = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
2369 rlSrc1 = dvmCompilerGetSrc(cUnit, mir, 2);
2370 rlSrc2 = dvmCompilerGetSrc(cUnit, mir, 3);
Bill Buzbee1465db52009-09-23 17:17:35 -07002371 }
2372 } else {
2373 /* Two sources and 1 dest. Deduce the operand sizes */
2374 if (mir->ssaRep->numUses == 4) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08002375 rlSrc1 = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
2376 rlSrc2 = dvmCompilerGetSrcWide(cUnit, mir, 2, 3);
Bill Buzbee1465db52009-09-23 17:17:35 -07002377 } else {
2378 assert(mir->ssaRep->numUses == 2);
Bill Buzbeec6f10662010-02-09 11:16:15 -08002379 rlSrc1 = dvmCompilerGetSrc(cUnit, mir, 0);
2380 rlSrc2 = dvmCompilerGetSrc(cUnit, mir, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -07002381 }
2382 if (mir->ssaRep->numDefs == 2) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08002383 rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -07002384 } else {
2385 assert(mir->ssaRep->numDefs == 1);
Bill Buzbeec6f10662010-02-09 11:16:15 -08002386 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07002387 }
2388 }
2389
2390
Ben Chengba4fc8b2009-06-01 13:00:29 -07002391 switch (opCode) {
Bill Buzbeed45ba372009-06-15 17:00:57 -07002392 case OP_CMPL_FLOAT:
2393 case OP_CMPG_FLOAT:
2394 case OP_CMPL_DOUBLE:
2395 case OP_CMPG_DOUBLE:
Ben Cheng5d90c202009-11-22 23:31:11 -08002396 return genCmpFP(cUnit, mir, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002397 case OP_CMP_LONG:
Bill Buzbee1465db52009-09-23 17:17:35 -07002398 genCmpLong(cUnit, mir, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002399 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002400 case OP_AGET_WIDE:
Bill Buzbee1465db52009-09-23 17:17:35 -07002401 genArrayGet(cUnit, mir, kLong, rlSrc1, rlSrc2, rlDest, 3);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002402 break;
2403 case OP_AGET:
2404 case OP_AGET_OBJECT:
Bill Buzbee1465db52009-09-23 17:17:35 -07002405 genArrayGet(cUnit, mir, kWord, rlSrc1, rlSrc2, rlDest, 2);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002406 break;
2407 case OP_AGET_BOOLEAN:
Bill Buzbee1465db52009-09-23 17:17:35 -07002408 genArrayGet(cUnit, mir, kUnsignedByte, rlSrc1, rlSrc2, rlDest, 0);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002409 break;
2410 case OP_AGET_BYTE:
Bill Buzbee1465db52009-09-23 17:17:35 -07002411 genArrayGet(cUnit, mir, kSignedByte, rlSrc1, rlSrc2, rlDest, 0);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002412 break;
2413 case OP_AGET_CHAR:
Bill Buzbee1465db52009-09-23 17:17:35 -07002414 genArrayGet(cUnit, mir, kUnsignedHalf, rlSrc1, rlSrc2, rlDest, 1);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002415 break;
2416 case OP_AGET_SHORT:
Bill Buzbee1465db52009-09-23 17:17:35 -07002417 genArrayGet(cUnit, mir, kSignedHalf, rlSrc1, rlSrc2, rlDest, 1);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002418 break;
2419 case OP_APUT_WIDE:
Bill Buzbee1465db52009-09-23 17:17:35 -07002420 genArrayPut(cUnit, mir, kLong, rlSrc1, rlSrc2, rlDest, 3);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002421 break;
2422 case OP_APUT:
Bill Buzbee1465db52009-09-23 17:17:35 -07002423 genArrayPut(cUnit, mir, kWord, rlSrc1, rlSrc2, rlDest, 2);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002424 break;
Bill Buzbeebe6534f2010-03-12 16:01:35 -08002425 case OP_APUT_OBJECT:
2426 genArrayObjectPut(cUnit, mir, rlSrc1, rlSrc2, rlDest, 2);
2427 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002428 case OP_APUT_SHORT:
2429 case OP_APUT_CHAR:
Bill Buzbee1465db52009-09-23 17:17:35 -07002430 genArrayPut(cUnit, mir, kUnsignedHalf, rlSrc1, rlSrc2, rlDest, 1);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002431 break;
2432 case OP_APUT_BYTE:
2433 case OP_APUT_BOOLEAN:
Bill Buzbee1465db52009-09-23 17:17:35 -07002434 genArrayPut(cUnit, mir, kUnsignedByte, rlSrc1, rlSrc2, rlDest, 0);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002435 break;
2436 default:
2437 return true;
2438 }
2439 return false;
2440}
2441
Ben Cheng6c10a972009-10-29 14:39:18 -07002442/*
2443 * Find the matching case.
2444 *
2445 * return values:
2446 * r0 (low 32-bit): pc of the chaining cell corresponding to the resolved case,
2447 * including default which is placed at MIN(size, MAX_CHAINED_SWITCH_CASES).
2448 * r1 (high 32-bit): the branch offset of the matching case (only for indexes
2449 * above MAX_CHAINED_SWITCH_CASES).
2450 *
2451 * Instructions around the call are:
2452 *
2453 * mov r2, pc
2454 * blx &findPackedSwitchIndex
2455 * mov pc, r0
2456 * .align4
2457 * chaining cell for case 0 [8 bytes]
2458 * chaining cell for case 1 [8 bytes]
2459 * :
2460 * chaining cell for case MIN(size, MAX_CHAINED_SWITCH_CASES)-1 [8 bytes]
2461 * chaining cell for case default [8 bytes]
2462 * noChain exit
2463 */
2464s8 findPackedSwitchIndex(const u2* switchData, int testVal, int pc)
2465{
2466 int size;
2467 int firstKey;
2468 const int *entries;
2469 int index;
2470 int jumpIndex;
2471 int caseDPCOffset = 0;
2472 /* In Thumb mode pc is 4 ahead of the "mov r2, pc" instruction */
2473 int chainingPC = (pc + 4) & ~3;
2474
2475 /*
2476 * Packed switch data format:
2477 * ushort ident = 0x0100 magic value
2478 * ushort size number of entries in the table
2479 * int first_key first (and lowest) switch case value
2480 * int targets[size] branch targets, relative to switch opcode
2481 *
2482 * Total size is (4+size*2) 16-bit code units.
2483 */
2484 size = switchData[1];
2485 assert(size > 0);
2486
2487 firstKey = switchData[2];
2488 firstKey |= switchData[3] << 16;
2489
2490
2491 /* The entries are guaranteed to be aligned on a 32-bit boundary;
2492 * we can treat them as a native int array.
2493 */
2494 entries = (const int*) &switchData[4];
2495 assert(((u4)entries & 0x3) == 0);
2496
2497 index = testVal - firstKey;
2498
2499 /* Jump to the default cell */
2500 if (index < 0 || index >= size) {
2501 jumpIndex = MIN(size, MAX_CHAINED_SWITCH_CASES);
2502 /* Jump to the non-chaining exit point */
2503 } else if (index >= MAX_CHAINED_SWITCH_CASES) {
2504 jumpIndex = MAX_CHAINED_SWITCH_CASES + 1;
2505 caseDPCOffset = entries[index];
2506 /* Jump to the inline chaining cell */
2507 } else {
2508 jumpIndex = index;
2509 }
2510
2511 chainingPC += jumpIndex * 8;
2512 return (((s8) caseDPCOffset) << 32) | (u8) chainingPC;
2513}
2514
2515/* See comments for findPackedSwitchIndex */
2516s8 findSparseSwitchIndex(const u2* switchData, int testVal, int pc)
2517{
2518 int size;
2519 const int *keys;
2520 const int *entries;
2521 int chainingPC = (pc + 4) & ~3;
2522 int i;
2523
2524 /*
2525 * Sparse switch data format:
2526 * ushort ident = 0x0200 magic value
2527 * ushort size number of entries in the table; > 0
2528 * int keys[size] keys, sorted low-to-high; 32-bit aligned
2529 * int targets[size] branch targets, relative to switch opcode
2530 *
2531 * Total size is (2+size*4) 16-bit code units.
2532 */
2533
2534 size = switchData[1];
2535 assert(size > 0);
2536
2537 /* The keys are guaranteed to be aligned on a 32-bit boundary;
2538 * we can treat them as a native int array.
2539 */
2540 keys = (const int*) &switchData[2];
2541 assert(((u4)keys & 0x3) == 0);
2542
2543 /* The entries are guaranteed to be aligned on a 32-bit boundary;
2544 * we can treat them as a native int array.
2545 */
2546 entries = keys + size;
2547 assert(((u4)entries & 0x3) == 0);
2548
2549 /*
2550 * Run through the list of keys, which are guaranteed to
2551 * be sorted low-to-high.
2552 *
2553 * Most tables have 3-4 entries. Few have more than 10. A binary
2554 * search here is probably not useful.
2555 */
2556 for (i = 0; i < size; i++) {
2557 int k = keys[i];
2558 if (k == testVal) {
2559 /* MAX_CHAINED_SWITCH_CASES + 1 is the start of the overflow case */
2560 int jumpIndex = (i < MAX_CHAINED_SWITCH_CASES) ?
2561 i : MAX_CHAINED_SWITCH_CASES + 1;
2562 chainingPC += jumpIndex * 8;
2563 return (((s8) entries[i]) << 32) | (u8) chainingPC;
2564 } else if (k > testVal) {
2565 break;
2566 }
2567 }
2568 return chainingPC + MIN(size, MAX_CHAINED_SWITCH_CASES) * 8;
2569}
2570
Ben Chengba4fc8b2009-06-01 13:00:29 -07002571static bool handleFmt31t(CompilationUnit *cUnit, MIR *mir)
2572{
2573 OpCode dalvikOpCode = mir->dalvikInsn.opCode;
2574 switch (dalvikOpCode) {
2575 case OP_FILL_ARRAY_DATA: {
Bill Buzbeec6f10662010-02-09 11:16:15 -08002576 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07002577 // Making a call - use explicit registers
Bill Buzbeec6f10662010-02-09 11:16:15 -08002578 dvmCompilerFlushAllRegs(cUnit); /* Everything to home location */
Bill Buzbee1465db52009-09-23 17:17:35 -07002579 genExportPC(cUnit, mir);
2580 loadValueDirectFixed(cUnit, rlSrc, r0);
Bill Buzbeefd023aa2009-11-02 09:23:49 -08002581 loadConstant(cUnit, r2, (int)dvmInterpHandleFillArrayData);
Ben Cheng6c10a972009-10-29 14:39:18 -07002582 loadConstant(cUnit, r1,
2583 (int) (cUnit->method->insns + mir->offset + mir->dalvikInsn.vB));
Bill Buzbee1465db52009-09-23 17:17:35 -07002584 opReg(cUnit, kOpBlx, r2);
Elliott Hughes6a555132010-02-25 15:41:42 -08002585 dvmCompilerClobberCallRegs(cUnit);
Bill Buzbeefd023aa2009-11-02 09:23:49 -08002586 /* generate a branch over if successful */
2587 opRegImm(cUnit, kOpCmp, r0, 0); /* NULL? */
2588 ArmLIR *branchOver = opCondBranch(cUnit, kArmCondNe);
2589 loadConstant(cUnit, r0,
2590 (int) (cUnit->method->insns + mir->offset));
2591 genDispatchToHandler(cUnit, TEMPLATE_THROW_EXCEPTION_COMMON);
2592 ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel);
2593 target->defMask = ENCODE_ALL;
2594 branchOver->generic.target = (LIR *) target;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002595 break;
2596 }
2597 /*
Ben Cheng6c10a972009-10-29 14:39:18 -07002598 * Compute the goto target of up to
2599 * MIN(switchSize, MAX_CHAINED_SWITCH_CASES) + 1 chaining cells.
2600 * See the comment before findPackedSwitchIndex for the code layout.
Ben Chengba4fc8b2009-06-01 13:00:29 -07002601 */
2602 case OP_PACKED_SWITCH:
2603 case OP_SPARSE_SWITCH: {
Bill Buzbeec6f10662010-02-09 11:16:15 -08002604 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
2605 dvmCompilerFlushAllRegs(cUnit); /* Everything to home location */
Bill Buzbee1465db52009-09-23 17:17:35 -07002606 loadValueDirectFixed(cUnit, rlSrc, r1);
Bill Buzbeec6f10662010-02-09 11:16:15 -08002607 dvmCompilerLockAllTemps(cUnit);
Ben Cheng6c10a972009-10-29 14:39:18 -07002608 const u2 *switchData =
2609 cUnit->method->insns + mir->offset + mir->dalvikInsn.vB;
2610 u2 size = switchData[1];
2611
Ben Chengba4fc8b2009-06-01 13:00:29 -07002612 if (dalvikOpCode == OP_PACKED_SWITCH) {
Ben Cheng6c10a972009-10-29 14:39:18 -07002613 loadConstant(cUnit, r4PC, (int)findPackedSwitchIndex);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002614 } else {
Ben Cheng6c10a972009-10-29 14:39:18 -07002615 loadConstant(cUnit, r4PC, (int)findSparseSwitchIndex);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002616 }
Ben Cheng6c10a972009-10-29 14:39:18 -07002617 /* r0 <- Addr of the switch data */
2618 loadConstant(cUnit, r0,
2619 (int) (cUnit->method->insns + mir->offset + mir->dalvikInsn.vB));
2620 /* r2 <- pc of the instruction following the blx */
2621 opRegReg(cUnit, kOpMov, r2, rpc);
Bill Buzbee1465db52009-09-23 17:17:35 -07002622 opReg(cUnit, kOpBlx, r4PC);
Elliott Hughes6a555132010-02-25 15:41:42 -08002623 dvmCompilerClobberCallRegs(cUnit);
Ben Cheng6c10a972009-10-29 14:39:18 -07002624 /* pc <- computed goto target */
2625 opRegReg(cUnit, kOpMov, rpc, r0);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002626 break;
2627 }
2628 default:
2629 return true;
2630 }
2631 return false;
2632}
2633
2634static bool handleFmt35c_3rc(CompilationUnit *cUnit, MIR *mir, BasicBlock *bb,
Bill Buzbee89efc3d2009-07-28 11:22:22 -07002635 ArmLIR *labelList)
Ben Chengba4fc8b2009-06-01 13:00:29 -07002636{
Bill Buzbee9bc3df32009-07-30 10:52:29 -07002637 ArmLIR *retChainingCell = NULL;
Bill Buzbee89efc3d2009-07-28 11:22:22 -07002638 ArmLIR *pcrLabel = NULL;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002639
Bill Buzbeef4ce16f2009-07-28 13:28:25 -07002640 if (bb->fallThrough != NULL)
2641 retChainingCell = &labelList[bb->fallThrough->id];
2642
Ben Chengba4fc8b2009-06-01 13:00:29 -07002643 DecodedInstruction *dInsn = &mir->dalvikInsn;
2644 switch (mir->dalvikInsn.opCode) {
2645 /*
2646 * calleeMethod = this->clazz->vtable[
2647 * method->clazz->pDvmDex->pResMethods[BBBB]->methodIndex
2648 * ]
2649 */
2650 case OP_INVOKE_VIRTUAL:
2651 case OP_INVOKE_VIRTUAL_RANGE: {
Bill Buzbee89efc3d2009-07-28 11:22:22 -07002652 ArmLIR *predChainingCell = &labelList[bb->taken->id];
Ben Chengba4fc8b2009-06-01 13:00:29 -07002653 int methodIndex =
2654 cUnit->method->clazz->pDvmDex->pResMethods[dInsn->vB]->
2655 methodIndex;
2656
2657 if (mir->dalvikInsn.opCode == OP_INVOKE_VIRTUAL)
2658 genProcessArgsNoRange(cUnit, mir, dInsn, &pcrLabel);
2659 else
2660 genProcessArgsRange(cUnit, mir, dInsn, &pcrLabel);
2661
Ben Cheng38329f52009-07-07 14:19:20 -07002662 genInvokeVirtualCommon(cUnit, mir, methodIndex,
2663 retChainingCell,
2664 predChainingCell,
2665 pcrLabel);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002666 break;
2667 }
2668 /*
2669 * calleeMethod = method->clazz->super->vtable[method->clazz->pDvmDex
2670 * ->pResMethods[BBBB]->methodIndex]
2671 */
2672 /* TODO - not excersized in RunPerf.jar */
2673 case OP_INVOKE_SUPER:
2674 case OP_INVOKE_SUPER_RANGE: {
2675 int mIndex = cUnit->method->clazz->pDvmDex->
2676 pResMethods[dInsn->vB]->methodIndex;
2677 const Method *calleeMethod =
2678 cUnit->method->clazz->super->vtable[mIndex];
2679
2680 if (mir->dalvikInsn.opCode == OP_INVOKE_SUPER)
2681 genProcessArgsNoRange(cUnit, mir, dInsn, &pcrLabel);
2682 else
2683 genProcessArgsRange(cUnit, mir, dInsn, &pcrLabel);
2684
2685 /* r0 = calleeMethod */
2686 loadConstant(cUnit, r0, (int) calleeMethod);
2687
Ben Cheng38329f52009-07-07 14:19:20 -07002688 genInvokeSingletonCommon(cUnit, mir, bb, labelList, pcrLabel,
2689 calleeMethod);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002690 break;
2691 }
2692 /* calleeMethod = method->clazz->pDvmDex->pResMethods[BBBB] */
2693 case OP_INVOKE_DIRECT:
2694 case OP_INVOKE_DIRECT_RANGE: {
2695 const Method *calleeMethod =
2696 cUnit->method->clazz->pDvmDex->pResMethods[dInsn->vB];
2697
2698 if (mir->dalvikInsn.opCode == OP_INVOKE_DIRECT)
2699 genProcessArgsNoRange(cUnit, mir, dInsn, &pcrLabel);
2700 else
2701 genProcessArgsRange(cUnit, mir, dInsn, &pcrLabel);
2702
2703 /* r0 = calleeMethod */
2704 loadConstant(cUnit, r0, (int) calleeMethod);
2705
Ben Cheng38329f52009-07-07 14:19:20 -07002706 genInvokeSingletonCommon(cUnit, mir, bb, labelList, pcrLabel,
2707 calleeMethod);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002708 break;
2709 }
2710 /* calleeMethod = method->clazz->pDvmDex->pResMethods[BBBB] */
2711 case OP_INVOKE_STATIC:
2712 case OP_INVOKE_STATIC_RANGE: {
2713 const Method *calleeMethod =
2714 cUnit->method->clazz->pDvmDex->pResMethods[dInsn->vB];
2715
2716 if (mir->dalvikInsn.opCode == OP_INVOKE_STATIC)
2717 genProcessArgsNoRange(cUnit, mir, dInsn,
2718 NULL /* no null check */);
2719 else
2720 genProcessArgsRange(cUnit, mir, dInsn,
2721 NULL /* no null check */);
2722
2723 /* r0 = calleeMethod */
2724 loadConstant(cUnit, r0, (int) calleeMethod);
2725
Ben Cheng38329f52009-07-07 14:19:20 -07002726 genInvokeSingletonCommon(cUnit, mir, bb, labelList, pcrLabel,
2727 calleeMethod);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002728 break;
2729 }
Bill Buzbee1465db52009-09-23 17:17:35 -07002730 /*
Ben Chengba4fc8b2009-06-01 13:00:29 -07002731 * calleeMethod = dvmFindInterfaceMethodInCache(this->clazz,
2732 * BBBB, method, method->clazz->pDvmDex)
Ben Cheng38329f52009-07-07 14:19:20 -07002733 *
2734 * Given "invoke-interface {v0}", the following is the generated code:
2735 *
2736 * 0x426a9abe : ldr r0, [r5, #0] --+
2737 * 0x426a9ac0 : mov r7, r5 |
2738 * 0x426a9ac2 : sub r7, #24 |
2739 * 0x426a9ac4 : cmp r0, #0 | genProcessArgsNoRange
2740 * 0x426a9ac6 : beq 0x426a9afe |
2741 * 0x426a9ac8 : stmia r7, <r0> --+
2742 * 0x426a9aca : ldr r4, [pc, #104] --> r4 <- dalvikPC of this invoke
2743 * 0x426a9acc : add r1, pc, #52 --> r1 <- &retChainingCell
2744 * 0x426a9ace : add r2, pc, #60 --> r2 <- &predictedChainingCell
2745 * 0x426a9ad0 : blx_1 0x426a918c --+ TEMPLATE_INVOKE_METHOD_
2746 * 0x426a9ad2 : blx_2 see above --+ PREDICTED_CHAIN
2747 * 0x426a9ad4 : b 0x426a9b0c --> off to the predicted chain
2748 * 0x426a9ad6 : b 0x426a9afe --> punt to the interpreter
Ben Chenga8e64a72009-10-20 13:01:36 -07002749 * 0x426a9ad8 : mov r8, r1 --+
2750 * 0x426a9ada : mov r9, r2 |
2751 * 0x426a9adc : mov r10, r3 |
Ben Cheng38329f52009-07-07 14:19:20 -07002752 * 0x426a9ade : mov r0, r3 |
2753 * 0x426a9ae0 : mov r1, #74 | dvmFindInterfaceMethodInCache
2754 * 0x426a9ae2 : ldr r2, [pc, #76] |
2755 * 0x426a9ae4 : ldr r3, [pc, #68] |
2756 * 0x426a9ae6 : ldr r7, [pc, #64] |
2757 * 0x426a9ae8 : blx r7 --+
Ben Chenga8e64a72009-10-20 13:01:36 -07002758 * 0x426a9aea : mov r1, r8 --> r1 <- rechain count
Ben Cheng38329f52009-07-07 14:19:20 -07002759 * 0x426a9aec : cmp r1, #0 --> compare against 0
2760 * 0x426a9aee : bgt 0x426a9af8 --> >=0? don't rechain
2761 * 0x426a9af0 : ldr r7, [r6, #96] --+
Ben Chenga8e64a72009-10-20 13:01:36 -07002762 * 0x426a9af2 : mov r2, r9 | dvmJitToPatchPredictedChain
2763 * 0x426a9af4 : mov r3, r10 |
Ben Cheng38329f52009-07-07 14:19:20 -07002764 * 0x426a9af6 : blx r7 --+
2765 * 0x426a9af8 : add r1, pc, #8 --> r1 <- &retChainingCell
2766 * 0x426a9afa : blx_1 0x426a9098 --+ TEMPLATE_INVOKE_METHOD_NO_OPT
2767 * 0x426a9afc : blx_2 see above --+
2768 * -------- reconstruct dalvik PC : 0x428b786c @ +0x001e
2769 * 0x426a9afe (0042): ldr r0, [pc, #52]
2770 * Exception_Handling:
2771 * 0x426a9b00 (0044): ldr r1, [r6, #84]
2772 * 0x426a9b02 (0046): blx r1
2773 * 0x426a9b04 (0048): .align4
2774 * -------- chaining cell (hot): 0x0021
2775 * 0x426a9b04 (0048): ldr r0, [r6, #92]
2776 * 0x426a9b06 (004a): blx r0
2777 * 0x426a9b08 (004c): data 0x7872(30834)
2778 * 0x426a9b0a (004e): data 0x428b(17035)
2779 * 0x426a9b0c (0050): .align4
2780 * -------- chaining cell (predicted)
2781 * 0x426a9b0c (0050): data 0x0000(0) --> will be patched into bx
2782 * 0x426a9b0e (0052): data 0x0000(0)
2783 * 0x426a9b10 (0054): data 0x0000(0) --> class
2784 * 0x426a9b12 (0056): data 0x0000(0)
2785 * 0x426a9b14 (0058): data 0x0000(0) --> method
2786 * 0x426a9b16 (005a): data 0x0000(0)
2787 * 0x426a9b18 (005c): data 0x0000(0) --> reset count
2788 * 0x426a9b1a (005e): data 0x0000(0)
2789 * 0x426a9b28 (006c): .word (0xad0392a5)
2790 * 0x426a9b2c (0070): .word (0x6e750)
2791 * 0x426a9b30 (0074): .word (0x4109a618)
2792 * 0x426a9b34 (0078): .word (0x428b786c)
Ben Chengba4fc8b2009-06-01 13:00:29 -07002793 */
2794 case OP_INVOKE_INTERFACE:
2795 case OP_INVOKE_INTERFACE_RANGE: {
Bill Buzbee89efc3d2009-07-28 11:22:22 -07002796 ArmLIR *predChainingCell = &labelList[bb->taken->id];
Ben Chengba4fc8b2009-06-01 13:00:29 -07002797 int methodIndex = dInsn->vB;
2798
Bill Buzbee1465db52009-09-23 17:17:35 -07002799 /* Ensure that nothing is both live and dirty */
Bill Buzbeec6f10662010-02-09 11:16:15 -08002800 dvmCompilerFlushAllRegs(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07002801
Ben Chengba4fc8b2009-06-01 13:00:29 -07002802 if (mir->dalvikInsn.opCode == OP_INVOKE_INTERFACE)
2803 genProcessArgsNoRange(cUnit, mir, dInsn, &pcrLabel);
2804 else
2805 genProcessArgsRange(cUnit, mir, dInsn, &pcrLabel);
2806
Ben Cheng38329f52009-07-07 14:19:20 -07002807 /* "this" is already left in r0 by genProcessArgs* */
2808
2809 /* r4PC = dalvikCallsite */
2810 loadConstant(cUnit, r4PC,
2811 (int) (cUnit->method->insns + mir->offset));
2812
2813 /* r1 = &retChainingCell */
Bill Buzbee270c1d62009-08-13 16:58:07 -07002814 ArmLIR *addrRetChain =
Bill Buzbee1465db52009-09-23 17:17:35 -07002815 opRegRegImm(cUnit, kOpAdd, r1, rpc, 0);
Ben Cheng38329f52009-07-07 14:19:20 -07002816 addrRetChain->generic.target = (LIR *) retChainingCell;
2817
2818 /* r2 = &predictedChainingCell */
Bill Buzbee89efc3d2009-07-28 11:22:22 -07002819 ArmLIR *predictedChainingCell =
Bill Buzbee1465db52009-09-23 17:17:35 -07002820 opRegRegImm(cUnit, kOpAdd, r2, rpc, 0);
Ben Cheng38329f52009-07-07 14:19:20 -07002821 predictedChainingCell->generic.target = (LIR *) predChainingCell;
2822
2823 genDispatchToHandler(cUnit, TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN);
2824
2825 /* return through lr - jump to the chaining cell */
2826 genUnconditionalBranch(cUnit, predChainingCell);
2827
2828 /*
2829 * null-check on "this" may have been eliminated, but we still need
2830 * a PC-reconstruction label for stack overflow bailout.
2831 */
2832 if (pcrLabel == NULL) {
2833 int dPC = (int) (cUnit->method->insns + mir->offset);
Bill Buzbee89efc3d2009-07-28 11:22:22 -07002834 pcrLabel = dvmCompilerNew(sizeof(ArmLIR), true);
Bill Buzbee1465db52009-09-23 17:17:35 -07002835 pcrLabel->opCode = ARM_PSEUDO_kPCReconstruction_CELL;
Ben Cheng38329f52009-07-07 14:19:20 -07002836 pcrLabel->operands[0] = dPC;
2837 pcrLabel->operands[1] = mir->offset;
2838 /* Insert the place holder to the growable list */
2839 dvmInsertGrowableList(&cUnit->pcReconstructionList, pcrLabel);
2840 }
2841
2842 /* return through lr+2 - punt to the interpreter */
2843 genUnconditionalBranch(cUnit, pcrLabel);
2844
2845 /*
2846 * return through lr+4 - fully resolve the callee method.
2847 * r1 <- count
2848 * r2 <- &predictedChainCell
2849 * r3 <- this->class
2850 * r4 <- dPC
2851 * r7 <- this->class->vtable
2852 */
2853
2854 /* Save count, &predictedChainCell, and class to high regs first */
Bill Buzbee1465db52009-09-23 17:17:35 -07002855 genRegCopy(cUnit, r8, r1);
2856 genRegCopy(cUnit, r9, r2);
2857 genRegCopy(cUnit, r10, r3);
Ben Cheng38329f52009-07-07 14:19:20 -07002858
Ben Chengba4fc8b2009-06-01 13:00:29 -07002859 /* r0 now contains this->clazz */
Bill Buzbee1465db52009-09-23 17:17:35 -07002860 genRegCopy(cUnit, r0, r3);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002861
2862 /* r1 = BBBB */
2863 loadConstant(cUnit, r1, dInsn->vB);
2864
2865 /* r2 = method (caller) */
2866 loadConstant(cUnit, r2, (int) cUnit->method);
2867
2868 /* r3 = pDvmDex */
2869 loadConstant(cUnit, r3, (int) cUnit->method->clazz->pDvmDex);
2870
2871 loadConstant(cUnit, r7,
2872 (intptr_t) dvmFindInterfaceMethodInCache);
Bill Buzbee1465db52009-09-23 17:17:35 -07002873 opReg(cUnit, kOpBlx, r7);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002874
2875 /* r0 = calleeMethod (returned from dvmFindInterfaceMethodInCache */
2876
Bill Buzbee1465db52009-09-23 17:17:35 -07002877 genRegCopy(cUnit, r1, r8);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002878
Ben Cheng38329f52009-07-07 14:19:20 -07002879 /* Check if rechain limit is reached */
Bill Buzbee1465db52009-09-23 17:17:35 -07002880 opRegImm(cUnit, kOpCmp, r1, 0);
Ben Cheng38329f52009-07-07 14:19:20 -07002881
Bill Buzbee1465db52009-09-23 17:17:35 -07002882 ArmLIR *bypassRechaining = opCondBranch(cUnit, kArmCondGt);
Ben Cheng38329f52009-07-07 14:19:20 -07002883
Bill Buzbee270c1d62009-08-13 16:58:07 -07002884 loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
2885 jitToInterpEntries.dvmJitToPatchPredictedChain), r7);
Ben Cheng38329f52009-07-07 14:19:20 -07002886
Bill Buzbee1465db52009-09-23 17:17:35 -07002887 genRegCopy(cUnit, r2, r9);
2888 genRegCopy(cUnit, r3, r10);
Ben Cheng38329f52009-07-07 14:19:20 -07002889
2890 /*
2891 * r0 = calleeMethod
2892 * r2 = &predictedChainingCell
2893 * r3 = class
2894 *
2895 * &returnChainingCell has been loaded into r1 but is not needed
2896 * when patching the chaining cell and will be clobbered upon
2897 * returning so it will be reconstructed again.
2898 */
Bill Buzbee1465db52009-09-23 17:17:35 -07002899 opReg(cUnit, kOpBlx, r7);
Ben Cheng38329f52009-07-07 14:19:20 -07002900
2901 /* r1 = &retChainingCell */
Bill Buzbee1465db52009-09-23 17:17:35 -07002902 addrRetChain = opRegRegImm(cUnit, kOpAdd, r1, rpc, 0);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002903 addrRetChain->generic.target = (LIR *) retChainingCell;
Ben Cheng38329f52009-07-07 14:19:20 -07002904
2905 bypassRechaining->generic.target = (LIR *) addrRetChain;
2906
Ben Chengba4fc8b2009-06-01 13:00:29 -07002907 /*
2908 * r0 = this, r1 = calleeMethod,
2909 * r1 = &ChainingCell,
2910 * r4PC = callsiteDPC,
2911 */
2912 genDispatchToHandler(cUnit, TEMPLATE_INVOKE_METHOD_NO_OPT);
Ben Cheng86717f72010-03-05 15:27:21 -08002913#if defined(JIT_STATS)
2914 gDvmJit.invokePolymorphic++;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002915#endif
2916 /* Handle exceptions using the interpreter */
2917 genTrap(cUnit, mir->offset, pcrLabel);
2918 break;
2919 }
2920 /* NOP */
2921 case OP_INVOKE_DIRECT_EMPTY: {
2922 return false;
2923 }
2924 case OP_FILLED_NEW_ARRAY:
2925 case OP_FILLED_NEW_ARRAY_RANGE: {
2926 /* Just let the interpreter deal with these */
2927 genInterpSingleStep(cUnit, mir);
2928 break;
2929 }
2930 default:
2931 return true;
2932 }
2933 return false;
2934}
2935
2936static bool handleFmt35ms_3rms(CompilationUnit *cUnit, MIR *mir,
Bill Buzbee89efc3d2009-07-28 11:22:22 -07002937 BasicBlock *bb, ArmLIR *labelList)
Ben Chengba4fc8b2009-06-01 13:00:29 -07002938{
Bill Buzbee89efc3d2009-07-28 11:22:22 -07002939 ArmLIR *retChainingCell = &labelList[bb->fallThrough->id];
2940 ArmLIR *predChainingCell = &labelList[bb->taken->id];
2941 ArmLIR *pcrLabel = NULL;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002942
2943 DecodedInstruction *dInsn = &mir->dalvikInsn;
2944 switch (mir->dalvikInsn.opCode) {
2945 /* calleeMethod = this->clazz->vtable[BBBB] */
2946 case OP_INVOKE_VIRTUAL_QUICK_RANGE:
2947 case OP_INVOKE_VIRTUAL_QUICK: {
2948 int methodIndex = dInsn->vB;
2949 if (mir->dalvikInsn.opCode == OP_INVOKE_VIRTUAL_QUICK)
2950 genProcessArgsNoRange(cUnit, mir, dInsn, &pcrLabel);
2951 else
2952 genProcessArgsRange(cUnit, mir, dInsn, &pcrLabel);
2953
Ben Cheng38329f52009-07-07 14:19:20 -07002954 genInvokeVirtualCommon(cUnit, mir, methodIndex,
2955 retChainingCell,
2956 predChainingCell,
2957 pcrLabel);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002958 break;
2959 }
2960 /* calleeMethod = method->clazz->super->vtable[BBBB] */
2961 case OP_INVOKE_SUPER_QUICK:
2962 case OP_INVOKE_SUPER_QUICK_RANGE: {
2963 const Method *calleeMethod =
2964 cUnit->method->clazz->super->vtable[dInsn->vB];
2965
2966 if (mir->dalvikInsn.opCode == OP_INVOKE_SUPER_QUICK)
2967 genProcessArgsNoRange(cUnit, mir, dInsn, &pcrLabel);
2968 else
2969 genProcessArgsRange(cUnit, mir, dInsn, &pcrLabel);
2970
2971 /* r0 = calleeMethod */
2972 loadConstant(cUnit, r0, (int) calleeMethod);
2973
Ben Cheng38329f52009-07-07 14:19:20 -07002974 genInvokeSingletonCommon(cUnit, mir, bb, labelList, pcrLabel,
2975 calleeMethod);
2976 /* Handle exceptions using the interpreter */
2977 genTrap(cUnit, mir->offset, pcrLabel);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002978 break;
2979 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07002980 default:
2981 return true;
2982 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07002983 return false;
2984}
2985
2986/*
Bill Buzbeefd023aa2009-11-02 09:23:49 -08002987 * This operation is complex enough that we'll do it partly inline
2988 * and partly with a handler. NOTE: the handler uses hardcoded
2989 * values for string object offsets and must be revisitied if the
2990 * layout changes.
2991 */
2992static bool genInlinedCompareTo(CompilationUnit *cUnit, MIR *mir)
2993{
2994#if defined(USE_GLOBAL_STRING_DEFS)
2995 return false;
2996#else
2997 ArmLIR *rollback;
Bill Buzbeec6f10662010-02-09 11:16:15 -08002998 RegLocation rlThis = dvmCompilerGetSrc(cUnit, mir, 0);
2999 RegLocation rlComp = dvmCompilerGetSrc(cUnit, mir, 1);
Bill Buzbeefd023aa2009-11-02 09:23:49 -08003000
3001 loadValueDirectFixed(cUnit, rlThis, r0);
3002 loadValueDirectFixed(cUnit, rlComp, r1);
3003 /* Test objects for NULL */
3004 rollback = genNullCheck(cUnit, rlThis.sRegLow, r0, mir->offset, NULL);
3005 genNullCheck(cUnit, rlComp.sRegLow, r1, mir->offset, rollback);
3006 /*
3007 * TUNING: we could check for object pointer equality before invoking
3008 * handler. Unclear whether the gain would be worth the added code size
3009 * expansion.
3010 */
3011 genDispatchToHandler(cUnit, TEMPLATE_STRING_COMPARETO);
Bill Buzbeec6f10662010-02-09 11:16:15 -08003012 storeValue(cUnit, inlinedTarget(cUnit, mir, false),
3013 dvmCompilerGetReturn(cUnit));
Bill Buzbeefd023aa2009-11-02 09:23:49 -08003014 return true;
3015#endif
3016}
3017
3018static bool genInlinedIndexOf(CompilationUnit *cUnit, MIR *mir, bool singleI)
3019{
3020#if defined(USE_GLOBAL_STRING_DEFS)
3021 return false;
3022#else
Bill Buzbeec6f10662010-02-09 11:16:15 -08003023 RegLocation rlThis = dvmCompilerGetSrc(cUnit, mir, 0);
3024 RegLocation rlChar = dvmCompilerGetSrc(cUnit, mir, 1);
Bill Buzbeefd023aa2009-11-02 09:23:49 -08003025
3026 loadValueDirectFixed(cUnit, rlThis, r0);
3027 loadValueDirectFixed(cUnit, rlChar, r1);
3028 if (!singleI) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08003029 RegLocation rlStart = dvmCompilerGetSrc(cUnit, mir, 2);
Bill Buzbeefd023aa2009-11-02 09:23:49 -08003030 loadValueDirectFixed(cUnit, rlStart, r2);
3031 } else {
3032 loadConstant(cUnit, r2, 0);
3033 }
3034 /* Test objects for NULL */
3035 genNullCheck(cUnit, rlThis.sRegLow, r0, mir->offset, NULL);
3036 genDispatchToHandler(cUnit, TEMPLATE_STRING_INDEXOF);
Bill Buzbeec6f10662010-02-09 11:16:15 -08003037 storeValue(cUnit, inlinedTarget(cUnit, mir, false),
3038 dvmCompilerGetReturn(cUnit));
Bill Buzbeefd023aa2009-11-02 09:23:49 -08003039 return true;
3040#endif
3041}
3042
Bill Buzbee1f748632010-03-02 16:14:41 -08003043static bool genInlinedStringLength(CompilationUnit *cUnit, MIR *mir)
3044{
3045 RegLocation rlObj = dvmCompilerGetSrc(cUnit, mir, 0);
3046 RegLocation rlDest = inlinedTarget(cUnit, mir, false);
3047 rlObj = loadValue(cUnit, rlObj, kCoreReg);
3048 RegLocation rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
3049 genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset, NULL);
3050 loadWordDisp(cUnit, rlObj.lowReg, gDvm.offJavaLangString_count,
3051 rlResult.lowReg);
3052 storeValue(cUnit, rlDest, rlResult);
3053 return false;
3054}
3055
3056static bool genInlinedStringCharAt(CompilationUnit *cUnit, MIR *mir)
3057{
3058 int contents = offsetof(ArrayObject, contents);
3059 RegLocation rlObj = dvmCompilerGetSrc(cUnit, mir, 0);
3060 RegLocation rlIdx = dvmCompilerGetSrc(cUnit, mir, 1);
3061 RegLocation rlDest = inlinedTarget(cUnit, mir, false);
3062 RegLocation rlResult;
3063 rlObj = loadValue(cUnit, rlObj, kCoreReg);
3064 rlIdx = loadValue(cUnit, rlIdx, kCoreReg);
3065 int regMax = dvmCompilerAllocTemp(cUnit);
3066 int regOff = dvmCompilerAllocTemp(cUnit);
3067 int regPtr = dvmCompilerAllocTemp(cUnit);
3068 ArmLIR *pcrLabel = genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg,
3069 mir->offset, NULL);
3070 loadWordDisp(cUnit, rlObj.lowReg, gDvm.offJavaLangString_count, regMax);
3071 loadWordDisp(cUnit, rlObj.lowReg, gDvm.offJavaLangString_offset, regOff);
3072 loadWordDisp(cUnit, rlObj.lowReg, gDvm.offJavaLangString_value, regPtr);
3073 genBoundsCheck(cUnit, rlIdx.lowReg, regMax, mir->offset, pcrLabel);
3074 dvmCompilerFreeTemp(cUnit, regMax);
3075 opRegImm(cUnit, kOpAdd, regPtr, contents);
3076 opRegReg(cUnit, kOpAdd, regOff, rlIdx.lowReg);
3077 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
3078 loadBaseIndexed(cUnit, regPtr, regOff, rlResult.lowReg, 1, kUnsignedHalf);
3079 storeValue(cUnit, rlDest, rlResult);
3080 return false;
3081}
3082
3083static bool genInlinedAbsInt(CompilationUnit *cUnit, MIR *mir)
3084{
3085 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
3086 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
3087 RegLocation rlDest = inlinedTarget(cUnit, mir, false);;
3088 RegLocation rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
3089 int signReg = dvmCompilerAllocTemp(cUnit);
3090 /*
3091 * abs(x) = y<=x>>31, (x+y)^y.
3092 * Thumb2's IT block also yields 3 instructions, but imposes
3093 * scheduling constraints.
3094 */
3095 opRegRegImm(cUnit, kOpAsr, signReg, rlSrc.lowReg, 31);
3096 opRegRegReg(cUnit, kOpAdd, rlResult.lowReg, rlSrc.lowReg, signReg);
3097 opRegReg(cUnit, kOpXor, rlResult.lowReg, signReg);
3098 storeValue(cUnit, rlDest, rlResult);
3099 return false;
3100}
3101
3102static bool genInlinedAbsLong(CompilationUnit *cUnit, MIR *mir)
3103{
3104 RegLocation rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
3105 RegLocation rlDest = inlinedTargetWide(cUnit, mir, false);
3106 rlSrc = loadValueWide(cUnit, rlSrc, kCoreReg);
3107 RegLocation rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
3108 int signReg = dvmCompilerAllocTemp(cUnit);
3109 /*
3110 * abs(x) = y<=x>>31, (x+y)^y.
3111 * Thumb2 IT block allows slightly shorter sequence,
3112 * but introduces a scheduling barrier. Stick with this
3113 * mechanism for now.
3114 */
3115 opRegRegImm(cUnit, kOpAsr, signReg, rlSrc.highReg, 31);
3116 opRegRegReg(cUnit, kOpAdd, rlResult.lowReg, rlSrc.lowReg, signReg);
3117 opRegRegReg(cUnit, kOpAdc, rlResult.highReg, rlSrc.highReg, signReg);
3118 opRegReg(cUnit, kOpXor, rlResult.lowReg, signReg);
3119 opRegReg(cUnit, kOpXor, rlResult.highReg, signReg);
3120 storeValueWide(cUnit, rlDest, rlResult);
3121 return false;
3122}
Bill Buzbeefd023aa2009-11-02 09:23:49 -08003123
3124/*
Bill Buzbeece46c942009-11-20 15:41:34 -08003125 * NOTE: Handles both range and non-range versions (arguments
3126 * have already been normalized by this point).
Ben Chengba4fc8b2009-06-01 13:00:29 -07003127 */
Bill Buzbeece46c942009-11-20 15:41:34 -08003128static bool handleExecuteInline(CompilationUnit *cUnit, MIR *mir)
Ben Chengba4fc8b2009-06-01 13:00:29 -07003129{
3130 DecodedInstruction *dInsn = &mir->dalvikInsn;
3131 switch( mir->dalvikInsn.opCode) {
Bill Buzbeece46c942009-11-20 15:41:34 -08003132 case OP_EXECUTE_INLINE_RANGE:
Ben Chengba4fc8b2009-06-01 13:00:29 -07003133 case OP_EXECUTE_INLINE: {
3134 unsigned int i;
3135 const InlineOperation* inLineTable = dvmGetInlineOpsTable();
Bill Buzbee50a6bf22009-07-08 13:08:04 -07003136 int offset = offsetof(InterpState, retval);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003137 int operation = dInsn->vB;
Bill Buzbee1465db52009-09-23 17:17:35 -07003138 int tReg1;
3139 int tReg2;
Bill Buzbee50a6bf22009-07-08 13:08:04 -07003140 switch (operation) {
3141 case INLINE_EMPTYINLINEMETHOD:
3142 return false; /* Nop */
3143 case INLINE_STRING_LENGTH:
3144 return genInlinedStringLength(cUnit, mir);
3145 case INLINE_MATH_ABS_INT:
3146 return genInlinedAbsInt(cUnit, mir);
3147 case INLINE_MATH_ABS_LONG:
3148 return genInlinedAbsLong(cUnit, mir);
3149 case INLINE_MATH_MIN_INT:
3150 return genInlinedMinMaxInt(cUnit, mir, true);
3151 case INLINE_MATH_MAX_INT:
3152 return genInlinedMinMaxInt(cUnit, mir, false);
3153 case INLINE_STRING_CHARAT:
3154 return genInlinedStringCharAt(cUnit, mir);
3155 case INLINE_MATH_SQRT:
3156 if (genInlineSqrt(cUnit, mir))
Bill Buzbee9727c3d2009-08-01 11:32:36 -07003157 return false;
Bill Buzbee50a6bf22009-07-08 13:08:04 -07003158 else
3159 break; /* Handle with C routine */
Bill Buzbee50a6bf22009-07-08 13:08:04 -07003160 case INLINE_MATH_ABS_FLOAT:
Bill Buzbee1465db52009-09-23 17:17:35 -07003161 if (genInlinedAbsFloat(cUnit, mir))
3162 return false;
3163 else
3164 break;
Bill Buzbee50a6bf22009-07-08 13:08:04 -07003165 case INLINE_MATH_ABS_DOUBLE:
Bill Buzbee1465db52009-09-23 17:17:35 -07003166 if (genInlinedAbsDouble(cUnit, mir))
3167 return false;
3168 else
3169 break;
Bill Buzbee50a6bf22009-07-08 13:08:04 -07003170 case INLINE_STRING_COMPARETO:
Bill Buzbeefd023aa2009-11-02 09:23:49 -08003171 if (genInlinedCompareTo(cUnit, mir))
3172 return false;
3173 else
3174 break;
Bill Buzbee12ba0152009-09-03 14:03:09 -07003175 case INLINE_STRING_INDEXOF_I:
Bill Buzbeefd023aa2009-11-02 09:23:49 -08003176 if (genInlinedIndexOf(cUnit, mir, true /* I */))
3177 return false;
3178 else
3179 break;
Bill Buzbee12ba0152009-09-03 14:03:09 -07003180 case INLINE_STRING_INDEXOF_II:
Bill Buzbeefd023aa2009-11-02 09:23:49 -08003181 if (genInlinedIndexOf(cUnit, mir, false /* I */))
3182 return false;
3183 else
3184 break;
3185 case INLINE_STRING_EQUALS:
3186 case INLINE_MATH_COS:
3187 case INLINE_MATH_SIN:
3188 break; /* Handle with C routine */
Bill Buzbee50a6bf22009-07-08 13:08:04 -07003189 default:
Bill Buzbeefc519dc2010-03-06 23:30:57 -08003190 dvmCompilerAbort(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003191 }
Bill Buzbeec6f10662010-02-09 11:16:15 -08003192 dvmCompilerFlushAllRegs(cUnit); /* Everything to home location */
Elliott Hughes6a555132010-02-25 15:41:42 -08003193 dvmCompilerClobberCallRegs(cUnit);
Bill Buzbeec6f10662010-02-09 11:16:15 -08003194 dvmCompilerClobber(cUnit, r4PC);
3195 dvmCompilerClobber(cUnit, r7);
Bill Buzbee1465db52009-09-23 17:17:35 -07003196 opRegRegImm(cUnit, kOpAdd, r4PC, rGLUE, offset);
3197 opImm(cUnit, kOpPush, (1<<r4PC) | (1<<r7));
Ben Chengba4fc8b2009-06-01 13:00:29 -07003198 loadConstant(cUnit, r4PC, (int)inLineTable[operation].func);
Bill Buzbee1465db52009-09-23 17:17:35 -07003199 genExportPC(cUnit, mir);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003200 for (i=0; i < dInsn->vA; i++) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08003201 loadValueDirect(cUnit, dvmCompilerGetSrc(cUnit, mir, i), i);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003202 }
Bill Buzbee1465db52009-09-23 17:17:35 -07003203 opReg(cUnit, kOpBlx, r4PC);
3204 opRegImm(cUnit, kOpAdd, r13, 8);
Bill Buzbeece46c942009-11-20 15:41:34 -08003205 opRegImm(cUnit, kOpCmp, r0, 0); /* NULL? */
3206 ArmLIR *branchOver = opCondBranch(cUnit, kArmCondNe);
3207 loadConstant(cUnit, r0,
3208 (int) (cUnit->method->insns + mir->offset));
3209 genDispatchToHandler(cUnit, TEMPLATE_THROW_EXCEPTION_COMMON);
3210 ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel);
3211 target->defMask = ENCODE_ALL;
3212 branchOver->generic.target = (LIR *) target;
Ben Chengba4fc8b2009-06-01 13:00:29 -07003213 break;
3214 }
3215 default:
3216 return true;
3217 }
3218 return false;
3219}
3220
3221static bool handleFmt51l(CompilationUnit *cUnit, MIR *mir)
3222{
Bill Buzbee1465db52009-09-23 17:17:35 -07003223 //TUNING: We're using core regs here - not optimal when target is a double
Bill Buzbeec6f10662010-02-09 11:16:15 -08003224 RegLocation rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
3225 RegLocation rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07003226 loadConstantValue(cUnit, rlResult.lowReg,
3227 mir->dalvikInsn.vB_wide & 0xFFFFFFFFUL);
3228 loadConstantValue(cUnit, rlResult.highReg,
3229 (mir->dalvikInsn.vB_wide>>32) & 0xFFFFFFFFUL);
3230 storeValueWide(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003231 return false;
3232}
3233
Ben Chengba4fc8b2009-06-01 13:00:29 -07003234/*
3235 * The following are special processing routines that handle transfer of
3236 * controls between compiled code and the interpreter. Certain VM states like
3237 * Dalvik PC and special-purpose registers are reconstructed here.
3238 */
3239
Ben Cheng1efc9c52009-06-08 18:25:27 -07003240/* Chaining cell for code that may need warmup. */
3241static void handleNormalChainingCell(CompilationUnit *cUnit,
3242 unsigned int offset)
Ben Chengba4fc8b2009-06-01 13:00:29 -07003243{
Bill Buzbee270c1d62009-08-13 16:58:07 -07003244 loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
3245 jitToInterpEntries.dvmJitToInterpNormal), r0);
Bill Buzbee1465db52009-09-23 17:17:35 -07003246 opReg(cUnit, kOpBlx, r0);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003247 addWordData(cUnit, (int) (cUnit->method->insns + offset), true);
3248}
3249
3250/*
Ben Cheng1efc9c52009-06-08 18:25:27 -07003251 * Chaining cell for instructions that immediately following already translated
3252 * code.
Ben Chengba4fc8b2009-06-01 13:00:29 -07003253 */
Ben Cheng1efc9c52009-06-08 18:25:27 -07003254static void handleHotChainingCell(CompilationUnit *cUnit,
3255 unsigned int offset)
Ben Chengba4fc8b2009-06-01 13:00:29 -07003256{
Bill Buzbee270c1d62009-08-13 16:58:07 -07003257 loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
Ben Cheng40094c12010-02-24 20:58:44 -08003258 jitToInterpEntries.dvmJitToInterpTraceSelect), r0);
Bill Buzbee1465db52009-09-23 17:17:35 -07003259 opReg(cUnit, kOpBlx, r0);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003260 addWordData(cUnit, (int) (cUnit->method->insns + offset), true);
3261}
3262
Bill Buzbee9c4b7c82009-09-10 10:10:38 -07003263#if defined(WITH_SELF_VERIFICATION) || defined(WITH_JIT_TUNING)
Jeff Hao97319a82009-08-12 16:57:15 -07003264/* Chaining cell for branches that branch back into the same basic block */
3265static void handleBackwardBranchChainingCell(CompilationUnit *cUnit,
3266 unsigned int offset)
3267{
Bill Buzbee9c4b7c82009-09-10 10:10:38 -07003268#if defined(WITH_SELF_VERIFICATION)
Bill Buzbee1465db52009-09-23 17:17:35 -07003269 newLIR3(cUnit, kThumbLdrRRI5, r0, rGLUE,
Ben Cheng40094c12010-02-24 20:58:44 -08003270 offsetof(InterpState,
3271 jitToInterpEntries.dvmJitToInterpBackwardBranch) >> 2);
Bill Buzbee9c4b7c82009-09-10 10:10:38 -07003272#else
Bill Buzbee1465db52009-09-23 17:17:35 -07003273 newLIR3(cUnit, kThumbLdrRRI5, r0, rGLUE,
Bill Buzbee9c4b7c82009-09-10 10:10:38 -07003274 offsetof(InterpState, jitToInterpEntries.dvmJitToInterpNormal) >> 2);
3275#endif
Bill Buzbee1465db52009-09-23 17:17:35 -07003276 newLIR1(cUnit, kThumbBlxR, r0);
Jeff Hao97319a82009-08-12 16:57:15 -07003277 addWordData(cUnit, (int) (cUnit->method->insns + offset), true);
3278}
3279
3280#endif
Ben Chengba4fc8b2009-06-01 13:00:29 -07003281/* Chaining cell for monomorphic method invocations. */
Ben Cheng38329f52009-07-07 14:19:20 -07003282static void handleInvokeSingletonChainingCell(CompilationUnit *cUnit,
3283 const Method *callee)
Ben Chengba4fc8b2009-06-01 13:00:29 -07003284{
Bill Buzbee270c1d62009-08-13 16:58:07 -07003285 loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
Ben Cheng40094c12010-02-24 20:58:44 -08003286 jitToInterpEntries.dvmJitToInterpTraceSelect), r0);
Bill Buzbee1465db52009-09-23 17:17:35 -07003287 opReg(cUnit, kOpBlx, r0);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003288 addWordData(cUnit, (int) (callee->insns), true);
3289}
3290
Ben Cheng38329f52009-07-07 14:19:20 -07003291/* Chaining cell for monomorphic method invocations. */
3292static void handleInvokePredictedChainingCell(CompilationUnit *cUnit)
3293{
3294
3295 /* Should not be executed in the initial state */
3296 addWordData(cUnit, PREDICTED_CHAIN_BX_PAIR_INIT, true);
3297 /* To be filled: class */
3298 addWordData(cUnit, PREDICTED_CHAIN_CLAZZ_INIT, true);
3299 /* To be filled: method */
3300 addWordData(cUnit, PREDICTED_CHAIN_METHOD_INIT, true);
3301 /*
3302 * Rechain count. The initial value of 0 here will trigger chaining upon
3303 * the first invocation of this callsite.
3304 */
3305 addWordData(cUnit, PREDICTED_CHAIN_COUNTER_INIT, true);
3306}
3307
Ben Chengba4fc8b2009-06-01 13:00:29 -07003308/* Load the Dalvik PC into r0 and jump to the specified target */
3309static void handlePCReconstruction(CompilationUnit *cUnit,
Bill Buzbee89efc3d2009-07-28 11:22:22 -07003310 ArmLIR *targetLabel)
Ben Chengba4fc8b2009-06-01 13:00:29 -07003311{
Bill Buzbee89efc3d2009-07-28 11:22:22 -07003312 ArmLIR **pcrLabel =
3313 (ArmLIR **) cUnit->pcReconstructionList.elemList;
Ben Chengba4fc8b2009-06-01 13:00:29 -07003314 int numElems = cUnit->pcReconstructionList.numUsed;
3315 int i;
3316 for (i = 0; i < numElems; i++) {
3317 dvmCompilerAppendLIR(cUnit, (LIR *) pcrLabel[i]);
3318 /* r0 = dalvik PC */
3319 loadConstant(cUnit, r0, pcrLabel[i]->operands[0]);
3320 genUnconditionalBranch(cUnit, targetLabel);
3321 }
3322}
3323
Bill Buzbee1465db52009-09-23 17:17:35 -07003324static char *extendedMIROpNames[kMirOpLast - kMirOpFirst] = {
3325 "kMirOpPhi",
3326 "kMirOpNullNRangeUpCheck",
3327 "kMirOpNullNRangeDownCheck",
3328 "kMirOpLowerBound",
3329 "kMirOpPunt",
Ben Cheng4238ec22009-08-24 16:32:22 -07003330};
3331
3332/*
3333 * vA = arrayReg;
3334 * vB = idxReg;
3335 * vC = endConditionReg;
3336 * arg[0] = maxC
3337 * arg[1] = minC
3338 * arg[2] = loopBranchConditionCode
3339 */
3340static void genHoistedChecksForCountUpLoop(CompilationUnit *cUnit, MIR *mir)
3341{
Bill Buzbee1465db52009-09-23 17:17:35 -07003342 /*
3343 * NOTE: these synthesized blocks don't have ssa names assigned
3344 * for Dalvik registers. However, because they dominate the following
3345 * blocks we can simply use the Dalvik name w/ subscript 0 as the
3346 * ssa name.
3347 */
Ben Cheng4238ec22009-08-24 16:32:22 -07003348 DecodedInstruction *dInsn = &mir->dalvikInsn;
3349 const int lenOffset = offsetof(ArrayObject, length);
Ben Cheng4238ec22009-08-24 16:32:22 -07003350 const int maxC = dInsn->arg[0];
3351 const int minC = dInsn->arg[1];
Bill Buzbee1465db52009-09-23 17:17:35 -07003352 int regLength;
3353 RegLocation rlArray = cUnit->regLocation[mir->dalvikInsn.vA];
3354 RegLocation rlIdxEnd = cUnit->regLocation[mir->dalvikInsn.vC];
Ben Cheng4238ec22009-08-24 16:32:22 -07003355
3356 /* regArray <- arrayRef */
Bill Buzbee1465db52009-09-23 17:17:35 -07003357 rlArray = loadValue(cUnit, rlArray, kCoreReg);
3358 rlIdxEnd = loadValue(cUnit, rlIdxEnd, kCoreReg);
3359 genRegImmCheck(cUnit, kArmCondEq, rlArray.lowReg, 0, 0,
Ben Cheng4238ec22009-08-24 16:32:22 -07003360 (ArmLIR *) cUnit->loopAnalysis->branchToPCR);
3361
3362 /* regLength <- len(arrayRef) */
Bill Buzbeec6f10662010-02-09 11:16:15 -08003363 regLength = dvmCompilerAllocTemp(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07003364 loadWordDisp(cUnit, rlArray.lowReg, lenOffset, regLength);
Ben Cheng4238ec22009-08-24 16:32:22 -07003365
3366 int delta = maxC;
3367 /*
3368 * If the loop end condition is ">=" instead of ">", then the largest value
3369 * of the index is "endCondition - 1".
3370 */
3371 if (dInsn->arg[2] == OP_IF_GE) {
3372 delta--;
3373 }
3374
3375 if (delta) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08003376 int tReg = dvmCompilerAllocTemp(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07003377 opRegRegImm(cUnit, kOpAdd, tReg, rlIdxEnd.lowReg, delta);
3378 rlIdxEnd.lowReg = tReg;
Bill Buzbeec6f10662010-02-09 11:16:15 -08003379 dvmCompilerFreeTemp(cUnit, tReg);
Ben Cheng4238ec22009-08-24 16:32:22 -07003380 }
3381 /* Punt if "regIdxEnd < len(Array)" is false */
Bill Buzbee1465db52009-09-23 17:17:35 -07003382 genRegRegCheck(cUnit, kArmCondGe, rlIdxEnd.lowReg, regLength, 0,
Ben Cheng0fd31e42009-09-03 14:40:16 -07003383 (ArmLIR *) cUnit->loopAnalysis->branchToPCR);
Ben Cheng4238ec22009-08-24 16:32:22 -07003384}
3385
3386/*
3387 * vA = arrayReg;
3388 * vB = idxReg;
3389 * vC = endConditionReg;
3390 * arg[0] = maxC
3391 * arg[1] = minC
3392 * arg[2] = loopBranchConditionCode
3393 */
3394static void genHoistedChecksForCountDownLoop(CompilationUnit *cUnit, MIR *mir)
3395{
3396 DecodedInstruction *dInsn = &mir->dalvikInsn;
3397 const int lenOffset = offsetof(ArrayObject, length);
Bill Buzbeec6f10662010-02-09 11:16:15 -08003398 const int regLength = dvmCompilerAllocTemp(cUnit);
Ben Cheng4238ec22009-08-24 16:32:22 -07003399 const int maxC = dInsn->arg[0];
3400 const int minC = dInsn->arg[1];
Bill Buzbee1465db52009-09-23 17:17:35 -07003401 RegLocation rlArray = cUnit->regLocation[mir->dalvikInsn.vA];
3402 RegLocation rlIdxInit = cUnit->regLocation[mir->dalvikInsn.vB];
Ben Cheng4238ec22009-08-24 16:32:22 -07003403
3404 /* regArray <- arrayRef */
Bill Buzbee1465db52009-09-23 17:17:35 -07003405 rlArray = loadValue(cUnit, rlArray, kCoreReg);
3406 rlIdxInit = loadValue(cUnit, rlIdxInit, kCoreReg);
3407 genRegImmCheck(cUnit, kArmCondEq, rlArray.lowReg, 0, 0,
Ben Cheng4238ec22009-08-24 16:32:22 -07003408 (ArmLIR *) cUnit->loopAnalysis->branchToPCR);
3409
3410 /* regLength <- len(arrayRef) */
Bill Buzbee1465db52009-09-23 17:17:35 -07003411 loadWordDisp(cUnit, rlArray.lowReg, lenOffset, regLength);
Ben Cheng4238ec22009-08-24 16:32:22 -07003412
3413 if (maxC) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08003414 int tReg = dvmCompilerAllocTemp(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07003415 opRegRegImm(cUnit, kOpAdd, tReg, rlIdxInit.lowReg, maxC);
3416 rlIdxInit.lowReg = tReg;
Bill Buzbeec6f10662010-02-09 11:16:15 -08003417 dvmCompilerFreeTemp(cUnit, tReg);
Ben Cheng4238ec22009-08-24 16:32:22 -07003418 }
3419
3420 /* Punt if "regIdxInit < len(Array)" is false */
Bill Buzbee1465db52009-09-23 17:17:35 -07003421 genRegRegCheck(cUnit, kArmCondGe, rlIdxInit.lowReg, regLength, 0,
Ben Cheng0fd31e42009-09-03 14:40:16 -07003422 (ArmLIR *) cUnit->loopAnalysis->branchToPCR);
Ben Cheng4238ec22009-08-24 16:32:22 -07003423}
3424
3425/*
3426 * vA = idxReg;
3427 * vB = minC;
3428 */
3429static void genHoistedLowerBoundCheck(CompilationUnit *cUnit, MIR *mir)
3430{
3431 DecodedInstruction *dInsn = &mir->dalvikInsn;
Ben Cheng4238ec22009-08-24 16:32:22 -07003432 const int minC = dInsn->vB;
Bill Buzbee1465db52009-09-23 17:17:35 -07003433 RegLocation rlIdx = cUnit->regLocation[mir->dalvikInsn.vA];
Ben Cheng4238ec22009-08-24 16:32:22 -07003434
3435 /* regIdx <- initial index value */
Bill Buzbee1465db52009-09-23 17:17:35 -07003436 rlIdx = loadValue(cUnit, rlIdx, kCoreReg);
Ben Cheng4238ec22009-08-24 16:32:22 -07003437
3438 /* Punt if "regIdxInit + minC >= 0" is false */
Bill Buzbee1465db52009-09-23 17:17:35 -07003439 genRegImmCheck(cUnit, kArmCondLt, rlIdx.lowReg, -minC, 0,
Ben Cheng4238ec22009-08-24 16:32:22 -07003440 (ArmLIR *) cUnit->loopAnalysis->branchToPCR);
3441}
3442
3443/* Extended MIR instructions like PHI */
3444static void handleExtendedMIR(CompilationUnit *cUnit, MIR *mir)
3445{
Bill Buzbee1465db52009-09-23 17:17:35 -07003446 int opOffset = mir->dalvikInsn.opCode - kMirOpFirst;
Ben Cheng4238ec22009-08-24 16:32:22 -07003447 char *msg = dvmCompilerNew(strlen(extendedMIROpNames[opOffset]) + 1,
3448 false);
3449 strcpy(msg, extendedMIROpNames[opOffset]);
Bill Buzbee1465db52009-09-23 17:17:35 -07003450 newLIR1(cUnit, kArmPseudoExtended, (int) msg);
Ben Cheng4238ec22009-08-24 16:32:22 -07003451
3452 switch (mir->dalvikInsn.opCode) {
Bill Buzbee1465db52009-09-23 17:17:35 -07003453 case kMirOpPhi: {
Ben Cheng4238ec22009-08-24 16:32:22 -07003454 char *ssaString = dvmCompilerGetSSAString(cUnit, mir->ssaRep);
Bill Buzbee1465db52009-09-23 17:17:35 -07003455 newLIR1(cUnit, kArmPseudoSSARep, (int) ssaString);
Ben Cheng4238ec22009-08-24 16:32:22 -07003456 break;
3457 }
Bill Buzbee1465db52009-09-23 17:17:35 -07003458 case kMirOpNullNRangeUpCheck: {
Ben Cheng4238ec22009-08-24 16:32:22 -07003459 genHoistedChecksForCountUpLoop(cUnit, mir);
3460 break;
3461 }
Bill Buzbee1465db52009-09-23 17:17:35 -07003462 case kMirOpNullNRangeDownCheck: {
Ben Cheng4238ec22009-08-24 16:32:22 -07003463 genHoistedChecksForCountDownLoop(cUnit, mir);
3464 break;
3465 }
Bill Buzbee1465db52009-09-23 17:17:35 -07003466 case kMirOpLowerBound: {
Ben Cheng4238ec22009-08-24 16:32:22 -07003467 genHoistedLowerBoundCheck(cUnit, mir);
3468 break;
3469 }
Bill Buzbee1465db52009-09-23 17:17:35 -07003470 case kMirOpPunt: {
Ben Cheng4238ec22009-08-24 16:32:22 -07003471 genUnconditionalBranch(cUnit,
3472 (ArmLIR *) cUnit->loopAnalysis->branchToPCR);
3473 break;
3474 }
3475 default:
3476 break;
3477 }
3478}
3479
3480/*
3481 * Create a PC-reconstruction cell for the starting offset of this trace.
3482 * Since the PCR cell is placed near the end of the compiled code which is
3483 * usually out of range for a conditional branch, we put two branches (one
3484 * branch over to the loop body and one layover branch to the actual PCR) at the
3485 * end of the entry block.
3486 */
3487static void setupLoopEntryBlock(CompilationUnit *cUnit, BasicBlock *entry,
3488 ArmLIR *bodyLabel)
3489{
3490 /* Set up the place holder to reconstruct this Dalvik PC */
3491 ArmLIR *pcrLabel = dvmCompilerNew(sizeof(ArmLIR), true);
Bill Buzbee1465db52009-09-23 17:17:35 -07003492 pcrLabel->opCode = ARM_PSEUDO_kPCReconstruction_CELL;
Ben Cheng4238ec22009-08-24 16:32:22 -07003493 pcrLabel->operands[0] =
3494 (int) (cUnit->method->insns + entry->startOffset);
3495 pcrLabel->operands[1] = entry->startOffset;
3496 /* Insert the place holder to the growable list */
3497 dvmInsertGrowableList(&cUnit->pcReconstructionList, pcrLabel);
3498
3499 /*
3500 * Next, create two branches - one branch over to the loop body and the
3501 * other branch to the PCR cell to punt.
3502 */
3503 ArmLIR *branchToBody = dvmCompilerNew(sizeof(ArmLIR), true);
Bill Buzbee1465db52009-09-23 17:17:35 -07003504 branchToBody->opCode = kThumbBUncond;
Ben Cheng4238ec22009-08-24 16:32:22 -07003505 branchToBody->generic.target = (LIR *) bodyLabel;
Ben Chengdcf3e5d2009-09-11 13:42:05 -07003506 setupResourceMasks(branchToBody);
Ben Cheng4238ec22009-08-24 16:32:22 -07003507 cUnit->loopAnalysis->branchToBody = (LIR *) branchToBody;
3508
3509 ArmLIR *branchToPCR = dvmCompilerNew(sizeof(ArmLIR), true);
Bill Buzbee1465db52009-09-23 17:17:35 -07003510 branchToPCR->opCode = kThumbBUncond;
Ben Cheng4238ec22009-08-24 16:32:22 -07003511 branchToPCR->generic.target = (LIR *) pcrLabel;
Ben Chengdcf3e5d2009-09-11 13:42:05 -07003512 setupResourceMasks(branchToPCR);
Ben Cheng4238ec22009-08-24 16:32:22 -07003513 cUnit->loopAnalysis->branchToPCR = (LIR *) branchToPCR;
3514}
3515
Ben Chengba4fc8b2009-06-01 13:00:29 -07003516void dvmCompilerMIR2LIR(CompilationUnit *cUnit)
3517{
3518 /* Used to hold the labels of each block */
Bill Buzbee89efc3d2009-07-28 11:22:22 -07003519 ArmLIR *labelList =
3520 dvmCompilerNew(sizeof(ArmLIR) * cUnit->numBlocks, true);
Ben Chengcec26f62010-01-15 15:29:33 -08003521 GrowableList chainingListByType[kChainingCellGap];
Ben Chengba4fc8b2009-06-01 13:00:29 -07003522 int i;
3523
3524 /*
Ben Cheng38329f52009-07-07 14:19:20 -07003525 * Initialize various types chaining lists.
Ben Chengba4fc8b2009-06-01 13:00:29 -07003526 */
Ben Chengcec26f62010-01-15 15:29:33 -08003527 for (i = 0; i < kChainingCellGap; i++) {
Ben Chengba4fc8b2009-06-01 13:00:29 -07003528 dvmInitGrowableList(&chainingListByType[i], 2);
3529 }
3530
3531 BasicBlock **blockList = cUnit->blockList;
3532
Bill Buzbee6e963e12009-06-17 16:56:19 -07003533 if (cUnit->executionCount) {
3534 /*
3535 * Reserve 6 bytes at the beginning of the trace
3536 * +----------------------------+
3537 * | execution count (4 bytes) |
3538 * +----------------------------+
3539 * | chain cell offset (2 bytes)|
3540 * +----------------------------+
3541 * ...and then code to increment the execution
3542 * count:
3543 * mov r0, pc @ move adr of "mov r0,pc" + 4 to r0
3544 * sub r0, #10 @ back up to addr of executionCount
3545 * ldr r1, [r0]
3546 * add r1, #1
3547 * str r1, [r0]
3548 */
Bill Buzbee1465db52009-09-23 17:17:35 -07003549 newLIR1(cUnit, kArm16BitData, 0);
3550 newLIR1(cUnit, kArm16BitData, 0);
Ben Chengcc6600c2009-06-22 14:45:16 -07003551 cUnit->chainCellOffsetLIR =
Bill Buzbee1465db52009-09-23 17:17:35 -07003552 (LIR *) newLIR1(cUnit, kArm16BitData, CHAIN_CELL_OFFSET_TAG);
Bill Buzbee6e963e12009-06-17 16:56:19 -07003553 cUnit->headerSize = 6;
Bill Buzbee270c1d62009-08-13 16:58:07 -07003554 /* Thumb instruction used directly here to ensure correct size */
Bill Buzbee1465db52009-09-23 17:17:35 -07003555 newLIR2(cUnit, kThumbMovRR_H2L, r0, rpc);
3556 newLIR2(cUnit, kThumbSubRI8, r0, 10);
3557 newLIR3(cUnit, kThumbLdrRRI5, r1, r0, 0);
3558 newLIR2(cUnit, kThumbAddRI8, r1, 1);
3559 newLIR3(cUnit, kThumbStrRRI5, r1, r0, 0);
Bill Buzbee6e963e12009-06-17 16:56:19 -07003560 } else {
3561 /* Just reserve 2 bytes for the chain cell offset */
Ben Chengcc6600c2009-06-22 14:45:16 -07003562 cUnit->chainCellOffsetLIR =
Bill Buzbee1465db52009-09-23 17:17:35 -07003563 (LIR *) newLIR1(cUnit, kArm16BitData, CHAIN_CELL_OFFSET_TAG);
Bill Buzbee6e963e12009-06-17 16:56:19 -07003564 cUnit->headerSize = 2;
3565 }
Ben Cheng1efc9c52009-06-08 18:25:27 -07003566
Ben Chengba4fc8b2009-06-01 13:00:29 -07003567 /* Handle the content in each basic block */
3568 for (i = 0; i < cUnit->numBlocks; i++) {
3569 blockList[i]->visited = true;
3570 MIR *mir;
3571
3572 labelList[i].operands[0] = blockList[i]->startOffset;
3573
Ben Chengcec26f62010-01-15 15:29:33 -08003574 if (blockList[i]->blockType >= kChainingCellGap) {
Ben Chengba4fc8b2009-06-01 13:00:29 -07003575 /*
3576 * Append the label pseudo LIR first. Chaining cells will be handled
3577 * separately afterwards.
3578 */
3579 dvmCompilerAppendLIR(cUnit, (LIR *) &labelList[i]);
3580 }
3581
Bill Buzbee1465db52009-09-23 17:17:35 -07003582 if (blockList[i]->blockType == kEntryBlock) {
3583 labelList[i].opCode = ARM_PSEUDO_kEntryBlock;
Ben Cheng4238ec22009-08-24 16:32:22 -07003584 if (blockList[i]->firstMIRInsn == NULL) {
3585 continue;
3586 } else {
3587 setupLoopEntryBlock(cUnit, blockList[i],
3588 &labelList[blockList[i]->fallThrough->id]);
3589 }
Bill Buzbee1465db52009-09-23 17:17:35 -07003590 } else if (blockList[i]->blockType == kExitBlock) {
3591 labelList[i].opCode = ARM_PSEUDO_kExitBlock;
Ben Cheng4238ec22009-08-24 16:32:22 -07003592 goto gen_fallthrough;
Bill Buzbee1465db52009-09-23 17:17:35 -07003593 } else if (blockList[i]->blockType == kDalvikByteCode) {
3594 labelList[i].opCode = kArmPseudoNormalBlockLabel;
Ben Chenge9695e52009-06-16 16:11:47 -07003595 /* Reset the register state */
Bill Buzbeec6f10662010-02-09 11:16:15 -08003596 dvmCompilerResetRegPool(cUnit);
3597 dvmCompilerClobberAllRegs(cUnit);
3598 dvmCompilerResetNullCheck(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003599 } else {
3600 switch (blockList[i]->blockType) {
Bill Buzbee1465db52009-09-23 17:17:35 -07003601 case kChainingCellNormal:
3602 labelList[i].opCode = ARM_PSEUDO_kChainingCellNormal;
Ben Chengba4fc8b2009-06-01 13:00:29 -07003603 /* handle the codegen later */
3604 dvmInsertGrowableList(
Bill Buzbee1465db52009-09-23 17:17:35 -07003605 &chainingListByType[kChainingCellNormal], (void *) i);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003606 break;
Bill Buzbee1465db52009-09-23 17:17:35 -07003607 case kChainingCellInvokeSingleton:
Ben Cheng38329f52009-07-07 14:19:20 -07003608 labelList[i].opCode =
Bill Buzbee1465db52009-09-23 17:17:35 -07003609 ARM_PSEUDO_kChainingCellInvokeSingleton;
Ben Chengba4fc8b2009-06-01 13:00:29 -07003610 labelList[i].operands[0] =
3611 (int) blockList[i]->containingMethod;
3612 /* handle the codegen later */
3613 dvmInsertGrowableList(
Bill Buzbee1465db52009-09-23 17:17:35 -07003614 &chainingListByType[kChainingCellInvokeSingleton],
Ben Cheng38329f52009-07-07 14:19:20 -07003615 (void *) i);
3616 break;
Bill Buzbee1465db52009-09-23 17:17:35 -07003617 case kChainingCellInvokePredicted:
Ben Cheng38329f52009-07-07 14:19:20 -07003618 labelList[i].opCode =
Bill Buzbee1465db52009-09-23 17:17:35 -07003619 ARM_PSEUDO_kChainingCellInvokePredicted;
Ben Cheng38329f52009-07-07 14:19:20 -07003620 /* handle the codegen later */
3621 dvmInsertGrowableList(
Bill Buzbee1465db52009-09-23 17:17:35 -07003622 &chainingListByType[kChainingCellInvokePredicted],
Ben Cheng38329f52009-07-07 14:19:20 -07003623 (void *) i);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003624 break;
Bill Buzbee1465db52009-09-23 17:17:35 -07003625 case kChainingCellHot:
Ben Chengba4fc8b2009-06-01 13:00:29 -07003626 labelList[i].opCode =
Bill Buzbee1465db52009-09-23 17:17:35 -07003627 ARM_PSEUDO_kChainingCellHot;
Ben Chengba4fc8b2009-06-01 13:00:29 -07003628 /* handle the codegen later */
3629 dvmInsertGrowableList(
Bill Buzbee1465db52009-09-23 17:17:35 -07003630 &chainingListByType[kChainingCellHot],
Ben Chengba4fc8b2009-06-01 13:00:29 -07003631 (void *) i);
3632 break;
Bill Buzbee1465db52009-09-23 17:17:35 -07003633 case kPCReconstruction:
Ben Chengba4fc8b2009-06-01 13:00:29 -07003634 /* Make sure exception handling block is next */
3635 labelList[i].opCode =
Bill Buzbee1465db52009-09-23 17:17:35 -07003636 ARM_PSEUDO_kPCReconstruction_BLOCK_LABEL;
Ben Chengba4fc8b2009-06-01 13:00:29 -07003637 assert (i == cUnit->numBlocks - 2);
3638 handlePCReconstruction(cUnit, &labelList[i+1]);
3639 break;
Bill Buzbee1465db52009-09-23 17:17:35 -07003640 case kExceptionHandling:
3641 labelList[i].opCode = kArmPseudoEHBlockLabel;
Ben Chengba4fc8b2009-06-01 13:00:29 -07003642 if (cUnit->pcReconstructionList.numUsed) {
Bill Buzbee270c1d62009-08-13 16:58:07 -07003643 loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
3644 jitToInterpEntries.dvmJitToInterpPunt),
3645 r1);
Bill Buzbee1465db52009-09-23 17:17:35 -07003646 opReg(cUnit, kOpBlx, r1);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003647 }
3648 break;
Bill Buzbee9c4b7c82009-09-10 10:10:38 -07003649#if defined(WITH_SELF_VERIFICATION) || defined(WITH_JIT_TUNING)
Bill Buzbee1465db52009-09-23 17:17:35 -07003650 case kChainingCellBackwardBranch:
Jeff Hao97319a82009-08-12 16:57:15 -07003651 labelList[i].opCode =
Bill Buzbee1465db52009-09-23 17:17:35 -07003652 ARM_PSEUDO_kChainingCellBackwardBranch;
Jeff Hao97319a82009-08-12 16:57:15 -07003653 /* handle the codegen later */
3654 dvmInsertGrowableList(
Bill Buzbee1465db52009-09-23 17:17:35 -07003655 &chainingListByType[kChainingCellBackwardBranch],
Jeff Hao97319a82009-08-12 16:57:15 -07003656 (void *) i);
3657 break;
3658#endif
Ben Chengba4fc8b2009-06-01 13:00:29 -07003659 default:
3660 break;
3661 }
3662 continue;
3663 }
Ben Chenge9695e52009-06-16 16:11:47 -07003664
Bill Buzbee89efc3d2009-07-28 11:22:22 -07003665 ArmLIR *headLIR = NULL;
Ben Chenge9695e52009-06-16 16:11:47 -07003666
Ben Chengba4fc8b2009-06-01 13:00:29 -07003667 for (mir = blockList[i]->firstMIRInsn; mir; mir = mir->next) {
Bill Buzbee1465db52009-09-23 17:17:35 -07003668
Bill Buzbeec6f10662010-02-09 11:16:15 -08003669 dvmCompilerResetRegPool(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07003670 if (gDvmJit.disableOpt & (1 << kTrackLiveTemps)) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08003671 dvmCompilerClobberAllRegs(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07003672 }
3673
3674 if (gDvmJit.disableOpt & (1 << kSuppressLoads)) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08003675 dvmCompilerResetDefTracking(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07003676 }
3677
3678 if (mir->dalvikInsn.opCode >= kMirOpFirst) {
Ben Cheng4238ec22009-08-24 16:32:22 -07003679 handleExtendedMIR(cUnit, mir);
3680 continue;
3681 }
3682
Bill Buzbee1465db52009-09-23 17:17:35 -07003683
Ben Chengba4fc8b2009-06-01 13:00:29 -07003684 OpCode dalvikOpCode = mir->dalvikInsn.opCode;
3685 InstructionFormat dalvikFormat =
3686 dexGetInstrFormat(gDvm.instrFormat, dalvikOpCode);
Bill Buzbee89efc3d2009-07-28 11:22:22 -07003687 ArmLIR *boundaryLIR =
Bill Buzbee1465db52009-09-23 17:17:35 -07003688 newLIR2(cUnit, ARM_PSEUDO_kDalvikByteCode_BOUNDARY,
Ben Chengccd6c012009-10-15 14:52:45 -07003689 mir->offset,
3690 (int) dvmCompilerGetDalvikDisassembly(&mir->dalvikInsn)
3691 );
Ben Cheng4238ec22009-08-24 16:32:22 -07003692 if (mir->ssaRep) {
3693 char *ssaString = dvmCompilerGetSSAString(cUnit, mir->ssaRep);
Bill Buzbee1465db52009-09-23 17:17:35 -07003694 newLIR1(cUnit, kArmPseudoSSARep, (int) ssaString);
Ben Cheng4238ec22009-08-24 16:32:22 -07003695 }
3696
Ben Chenge9695e52009-06-16 16:11:47 -07003697 /* Remember the first LIR for this block */
3698 if (headLIR == NULL) {
3699 headLIR = boundaryLIR;
Ben Chengd7d426a2009-09-22 11:23:36 -07003700 /* Set the first boundaryLIR as a scheduling barrier */
3701 headLIR->defMask = ENCODE_ALL;
Ben Chenge9695e52009-06-16 16:11:47 -07003702 }
Ben Cheng4238ec22009-08-24 16:32:22 -07003703
Ben Chengba4fc8b2009-06-01 13:00:29 -07003704 bool notHandled;
3705 /*
3706 * Debugging: screen the opcode first to see if it is in the
3707 * do[-not]-compile list
3708 */
3709 bool singleStepMe =
3710 gDvmJit.includeSelectedOp !=
3711 ((gDvmJit.opList[dalvikOpCode >> 3] &
3712 (1 << (dalvikOpCode & 0x7))) !=
3713 0);
3714 if (singleStepMe || cUnit->allSingleStep) {
3715 notHandled = false;
3716 genInterpSingleStep(cUnit, mir);
3717 } else {
3718 opcodeCoverage[dalvikOpCode]++;
3719 switch (dalvikFormat) {
3720 case kFmt10t:
3721 case kFmt20t:
3722 case kFmt30t:
3723 notHandled = handleFmt10t_Fmt20t_Fmt30t(cUnit,
3724 mir, blockList[i], labelList);
3725 break;
3726 case kFmt10x:
3727 notHandled = handleFmt10x(cUnit, mir);
3728 break;
3729 case kFmt11n:
3730 case kFmt31i:
3731 notHandled = handleFmt11n_Fmt31i(cUnit, mir);
3732 break;
3733 case kFmt11x:
3734 notHandled = handleFmt11x(cUnit, mir);
3735 break;
3736 case kFmt12x:
3737 notHandled = handleFmt12x(cUnit, mir);
3738 break;
3739 case kFmt20bc:
3740 notHandled = handleFmt20bc(cUnit, mir);
3741 break;
3742 case kFmt21c:
3743 case kFmt31c:
3744 notHandled = handleFmt21c_Fmt31c(cUnit, mir);
3745 break;
3746 case kFmt21h:
3747 notHandled = handleFmt21h(cUnit, mir);
3748 break;
3749 case kFmt21s:
3750 notHandled = handleFmt21s(cUnit, mir);
3751 break;
3752 case kFmt21t:
3753 notHandled = handleFmt21t(cUnit, mir, blockList[i],
3754 labelList);
3755 break;
3756 case kFmt22b:
3757 case kFmt22s:
3758 notHandled = handleFmt22b_Fmt22s(cUnit, mir);
3759 break;
3760 case kFmt22c:
3761 notHandled = handleFmt22c(cUnit, mir);
3762 break;
3763 case kFmt22cs:
3764 notHandled = handleFmt22cs(cUnit, mir);
3765 break;
3766 case kFmt22t:
3767 notHandled = handleFmt22t(cUnit, mir, blockList[i],
3768 labelList);
3769 break;
3770 case kFmt22x:
3771 case kFmt32x:
3772 notHandled = handleFmt22x_Fmt32x(cUnit, mir);
3773 break;
3774 case kFmt23x:
3775 notHandled = handleFmt23x(cUnit, mir);
3776 break;
3777 case kFmt31t:
3778 notHandled = handleFmt31t(cUnit, mir);
3779 break;
3780 case kFmt3rc:
3781 case kFmt35c:
3782 notHandled = handleFmt35c_3rc(cUnit, mir, blockList[i],
3783 labelList);
3784 break;
3785 case kFmt3rms:
3786 case kFmt35ms:
3787 notHandled = handleFmt35ms_3rms(cUnit, mir,blockList[i],
3788 labelList);
3789 break;
3790 case kFmt3inline:
Andy McFaddenb0a05412009-11-19 10:23:41 -08003791 case kFmt3rinline:
Bill Buzbeece46c942009-11-20 15:41:34 -08003792 notHandled = handleExecuteInline(cUnit, mir);
Andy McFaddenb0a05412009-11-19 10:23:41 -08003793 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07003794 case kFmt51l:
3795 notHandled = handleFmt51l(cUnit, mir);
3796 break;
3797 default:
3798 notHandled = true;
3799 break;
3800 }
3801 }
3802 if (notHandled) {
3803 LOGE("%#06x: Opcode 0x%x (%s) / Fmt %d not handled\n",
3804 mir->offset,
3805 dalvikOpCode, getOpcodeName(dalvikOpCode),
3806 dalvikFormat);
Bill Buzbeefc519dc2010-03-06 23:30:57 -08003807 dvmCompilerAbort(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003808 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07003809 }
3810 }
Ben Cheng4238ec22009-08-24 16:32:22 -07003811
Bill Buzbee1465db52009-09-23 17:17:35 -07003812 if (blockList[i]->blockType == kEntryBlock) {
Ben Cheng4238ec22009-08-24 16:32:22 -07003813 dvmCompilerAppendLIR(cUnit,
3814 (LIR *) cUnit->loopAnalysis->branchToBody);
3815 dvmCompilerAppendLIR(cUnit,
3816 (LIR *) cUnit->loopAnalysis->branchToPCR);
3817 }
3818
3819 if (headLIR) {
3820 /*
3821 * Eliminate redundant loads/stores and delay stores into later
3822 * slots
3823 */
3824 dvmCompilerApplyLocalOptimizations(cUnit, (LIR *) headLIR,
3825 cUnit->lastLIRInsn);
3826 }
3827
3828gen_fallthrough:
Ben Cheng1efc9c52009-06-08 18:25:27 -07003829 /*
3830 * Check if the block is terminated due to trace length constraint -
3831 * insert an unconditional branch to the chaining cell.
3832 */
3833 if (blockList[i]->needFallThroughBranch) {
3834 genUnconditionalBranch(cUnit,
3835 &labelList[blockList[i]->fallThrough->id]);
3836 }
3837
Ben Chengba4fc8b2009-06-01 13:00:29 -07003838 }
3839
Ben Chenge9695e52009-06-16 16:11:47 -07003840 /* Handle the chaining cells in predefined order */
Ben Chengcec26f62010-01-15 15:29:33 -08003841 for (i = 0; i < kChainingCellGap; i++) {
Ben Chengba4fc8b2009-06-01 13:00:29 -07003842 size_t j;
3843 int *blockIdList = (int *) chainingListByType[i].elemList;
3844
3845 cUnit->numChainingCells[i] = chainingListByType[i].numUsed;
3846
3847 /* No chaining cells of this type */
3848 if (cUnit->numChainingCells[i] == 0)
3849 continue;
3850
3851 /* Record the first LIR for a new type of chaining cell */
3852 cUnit->firstChainingLIR[i] = (LIR *) &labelList[blockIdList[0]];
3853
3854 for (j = 0; j < chainingListByType[i].numUsed; j++) {
3855 int blockId = blockIdList[j];
3856
3857 /* Align this chaining cell first */
Bill Buzbee1465db52009-09-23 17:17:35 -07003858 newLIR0(cUnit, kArmPseudoPseudoAlign4);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003859
3860 /* Insert the pseudo chaining instruction */
3861 dvmCompilerAppendLIR(cUnit, (LIR *) &labelList[blockId]);
3862
3863
3864 switch (blockList[blockId]->blockType) {
Bill Buzbee1465db52009-09-23 17:17:35 -07003865 case kChainingCellNormal:
Ben Cheng1efc9c52009-06-08 18:25:27 -07003866 handleNormalChainingCell(cUnit,
Ben Chengba4fc8b2009-06-01 13:00:29 -07003867 blockList[blockId]->startOffset);
3868 break;
Bill Buzbee1465db52009-09-23 17:17:35 -07003869 case kChainingCellInvokeSingleton:
Ben Cheng38329f52009-07-07 14:19:20 -07003870 handleInvokeSingletonChainingCell(cUnit,
Ben Chengba4fc8b2009-06-01 13:00:29 -07003871 blockList[blockId]->containingMethod);
3872 break;
Bill Buzbee1465db52009-09-23 17:17:35 -07003873 case kChainingCellInvokePredicted:
Ben Cheng38329f52009-07-07 14:19:20 -07003874 handleInvokePredictedChainingCell(cUnit);
3875 break;
Bill Buzbee1465db52009-09-23 17:17:35 -07003876 case kChainingCellHot:
Ben Cheng1efc9c52009-06-08 18:25:27 -07003877 handleHotChainingCell(cUnit,
Ben Chengba4fc8b2009-06-01 13:00:29 -07003878 blockList[blockId]->startOffset);
3879 break;
Bill Buzbee9c4b7c82009-09-10 10:10:38 -07003880#if defined(WITH_SELF_VERIFICATION) || defined(WITH_JIT_TUNING)
Bill Buzbee1465db52009-09-23 17:17:35 -07003881 case kChainingCellBackwardBranch:
Jeff Hao97319a82009-08-12 16:57:15 -07003882 handleBackwardBranchChainingCell(cUnit,
3883 blockList[blockId]->startOffset);
3884 break;
3885#endif
Ben Chengba4fc8b2009-06-01 13:00:29 -07003886 default:
Bill Buzbee1465db52009-09-23 17:17:35 -07003887 LOGE("Bad blocktype %d", blockList[blockId]->blockType);
Bill Buzbeefc519dc2010-03-06 23:30:57 -08003888 dvmCompilerAbort(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003889 }
3890 }
3891 }
Ben Chenge9695e52009-06-16 16:11:47 -07003892
Ben Chengcec26f62010-01-15 15:29:33 -08003893 /* Mark the bottom of chaining cells */
3894 cUnit->chainingCellBottom = (LIR *) newLIR0(cUnit, kArmChainingCellBottom);
3895
Ben Cheng6c10a972009-10-29 14:39:18 -07003896 /*
3897 * Generate the branch to the dvmJitToInterpNoChain entry point at the end
3898 * of all chaining cells for the overflow cases.
3899 */
3900 if (cUnit->switchOverflowPad) {
3901 loadConstant(cUnit, r0, (int) cUnit->switchOverflowPad);
3902 loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
3903 jitToInterpEntries.dvmJitToInterpNoChain), r2);
3904 opRegReg(cUnit, kOpAdd, r1, r1);
3905 opRegRegReg(cUnit, kOpAdd, r4PC, r0, r1);
Ben Cheng86717f72010-03-05 15:27:21 -08003906#if defined(JIT_STATS)
Ben Cheng6c10a972009-10-29 14:39:18 -07003907 loadConstant(cUnit, r0, kSwitchOverflow);
3908#endif
3909 opReg(cUnit, kOpBlx, r2);
3910 }
3911
Ben Chenge9695e52009-06-16 16:11:47 -07003912 dvmCompilerApplyGlobalOptimizations(cUnit);
jeffhao9e45c0b2010-02-03 10:24:05 -08003913
3914#if defined(WITH_SELF_VERIFICATION)
3915 selfVerificationBranchInsertPass(cUnit);
3916#endif
Ben Chengba4fc8b2009-06-01 13:00:29 -07003917}
3918
3919/* Accept the work and start compiling */
Bill Buzbee716f1202009-07-23 13:22:09 -07003920bool dvmCompilerDoWork(CompilerWorkOrder *work)
Ben Chengba4fc8b2009-06-01 13:00:29 -07003921{
Ben Chengccd6c012009-10-15 14:52:45 -07003922 bool res;
Ben Chengba4fc8b2009-06-01 13:00:29 -07003923
Ben Cheng6999d842010-01-26 16:46:15 -08003924 if (gDvmJit.codeCacheFull) {
Ben Chengccd6c012009-10-15 14:52:45 -07003925 return false;
3926 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07003927
Ben Chengccd6c012009-10-15 14:52:45 -07003928 switch (work->kind) {
3929 case kWorkOrderMethod:
3930 res = dvmCompileMethod(work->info, &work->result);
3931 break;
3932 case kWorkOrderTrace:
3933 /* Start compilation with maximally allowed trace length */
Bill Buzbeefc519dc2010-03-06 23:30:57 -08003934 res = dvmCompileTrace(work->info, JIT_MAX_TRACE_LEN, &work->result,
3935 work->bailPtr);
Ben Chengccd6c012009-10-15 14:52:45 -07003936 break;
3937 case kWorkOrderTraceDebug: {
3938 bool oldPrintMe = gDvmJit.printMe;
3939 gDvmJit.printMe = true;
3940 /* Start compilation with maximally allowed trace length */
Bill Buzbeefc519dc2010-03-06 23:30:57 -08003941 res = dvmCompileTrace(work->info, JIT_MAX_TRACE_LEN, &work->result,
3942 work->bailPtr);
Ben Chengccd6c012009-10-15 14:52:45 -07003943 gDvmJit.printMe = oldPrintMe;;
3944 break;
3945 }
3946 default:
3947 res = false;
Bill Buzbeefc519dc2010-03-06 23:30:57 -08003948 LOGE("Jit: unknown work order type");
3949 assert(0); // Bail if debug build, discard oteherwise
Ben Chengccd6c012009-10-15 14:52:45 -07003950 }
3951 return res;
Ben Chengba4fc8b2009-06-01 13:00:29 -07003952}
3953
Ben Chengba4fc8b2009-06-01 13:00:29 -07003954/* Architectural-specific debugging helpers go here */
3955void dvmCompilerArchDump(void)
3956{
3957 /* Print compiled opcode in this VM instance */
3958 int i, start, streak;
3959 char buf[1024];
3960
3961 streak = i = 0;
3962 buf[0] = 0;
3963 while (opcodeCoverage[i] == 0 && i < 256) {
3964 i++;
3965 }
3966 if (i == 256) {
3967 return;
3968 }
3969 for (start = i++, streak = 1; i < 256; i++) {
3970 if (opcodeCoverage[i]) {
3971 streak++;
3972 } else {
3973 if (streak == 1) {
3974 sprintf(buf+strlen(buf), "%x,", start);
3975 } else {
3976 sprintf(buf+strlen(buf), "%x-%x,", start, start + streak - 1);
3977 }
3978 streak = 0;
3979 while (opcodeCoverage[i] == 0 && i < 256) {
3980 i++;
3981 }
3982 if (i < 256) {
3983 streak = 1;
3984 start = i;
3985 }
3986 }
3987 }
3988 if (streak) {
3989 if (streak == 1) {
3990 sprintf(buf+strlen(buf), "%x", start);
3991 } else {
3992 sprintf(buf+strlen(buf), "%x-%x", start, start + streak - 1);
3993 }
3994 }
3995 if (strlen(buf)) {
Ben Cheng8b258bf2009-06-24 17:27:07 -07003996 LOGD("dalvik.vm.jit.op = %s", buf);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003997 }
3998}
Ben Chengd7d426a2009-09-22 11:23:36 -07003999
4000/* Common initialization routine for an architecture family */
4001bool dvmCompilerArchInit()
4002{
4003 int i;
4004
Bill Buzbee1465db52009-09-23 17:17:35 -07004005 for (i = 0; i < kArmLast; i++) {
Ben Chengd7d426a2009-09-22 11:23:36 -07004006 if (EncodingMap[i].opCode != i) {
4007 LOGE("Encoding order for %s is wrong: expecting %d, seeing %d",
4008 EncodingMap[i].name, i, EncodingMap[i].opCode);
Bill Buzbeefc519dc2010-03-06 23:30:57 -08004009 dvmAbort(); // OK to dvmAbort - build error
Ben Chengd7d426a2009-09-22 11:23:36 -07004010 }
4011 }
4012
Ben Cheng5d90c202009-11-22 23:31:11 -08004013 return dvmCompilerArchVariantInit();
4014}
4015
4016void *dvmCompilerGetInterpretTemplate()
4017{
4018 return (void*) ((int)gDvmJit.codeCache +
4019 templateEntryOffsets[TEMPLATE_INTERPRET]);
4020}
4021
4022/* Needed by the ld/st optmizatons */
4023ArmLIR* dvmCompilerRegCopyNoInsert(CompilationUnit *cUnit, int rDest, int rSrc)
4024{
4025 return genRegCopyNoInsert(cUnit, rDest, rSrc);
4026}
4027
4028/* Needed by the register allocator */
4029ArmLIR* dvmCompilerRegCopy(CompilationUnit *cUnit, int rDest, int rSrc)
4030{
4031 return genRegCopy(cUnit, rDest, rSrc);
4032}
4033
4034/* Needed by the register allocator */
4035void dvmCompilerRegCopyWide(CompilationUnit *cUnit, int destLo, int destHi,
4036 int srcLo, int srcHi)
4037{
4038 genRegCopyWide(cUnit, destLo, destHi, srcLo, srcHi);
4039}
4040
4041void dvmCompilerFlushRegImpl(CompilationUnit *cUnit, int rBase,
4042 int displacement, int rSrc, OpSize size)
4043{
4044 storeBaseDisp(cUnit, rBase, displacement, rSrc, size);
4045}
4046
4047void dvmCompilerFlushRegWideImpl(CompilationUnit *cUnit, int rBase,
4048 int displacement, int rSrcLo, int rSrcHi)
4049{
4050 storeBaseDispWide(cUnit, rBase, displacement, rSrcLo, rSrcHi);
Ben Chengd7d426a2009-09-22 11:23:36 -07004051}