blob: 4048c0a6dba486f9a1b6ff63b42b79f50724dd79 [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);
Bill Buzbeec6f10662010-02-09 11:16:15 -080046 dvmCompilerColbberCallRegs(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);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800109 dvmCompilerColbberCallRegs(cUnit);
110 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);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800162 dvmCompilerColbberCallRegs(cUnit);
163 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
Ben Chengba4fc8b2009-06-01 13:00:29 -0700244/* Generate a unconditional branch to go to the interpreter */
Bill Buzbee89efc3d2009-07-28 11:22:22 -0700245static inline ArmLIR *genTrap(CompilationUnit *cUnit, int dOffset,
246 ArmLIR *pcrLabel)
Ben Chengba4fc8b2009-06-01 13:00:29 -0700247{
Bill Buzbee1465db52009-09-23 17:17:35 -0700248 ArmLIR *branch = opNone(cUnit, kOpUncondBr);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700249 return genCheckCommon(cUnit, dOffset, branch, pcrLabel);
250}
251
252/* Load a wide field from an object instance */
253static void genIGetWide(CompilationUnit *cUnit, MIR *mir, int fieldOffset)
254{
255 DecodedInstruction *dInsn = &mir->dalvikInsn;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800256 RegLocation rlObj = dvmCompilerGetSrc(cUnit, mir, 0);
257 RegLocation rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -0700258 RegLocation rlResult;
259 rlObj = loadValue(cUnit, rlObj, kCoreReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800260 int regPtr = dvmCompilerAllocTemp(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700261
Bill Buzbee1465db52009-09-23 17:17:35 -0700262 assert(rlDest.wide);
Ben Chenge9695e52009-06-16 16:11:47 -0700263
Bill Buzbee1465db52009-09-23 17:17:35 -0700264 genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset,
265 NULL);/* null object? */
266 opRegRegImm(cUnit, kOpAdd, regPtr, rlObj.lowReg, fieldOffset);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800267 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
jeffhao9e45c0b2010-02-03 10:24:05 -0800268#if defined(WITH_SELF_VERIFICATION)
269 cUnit->heapMemOp = true;
270#endif
Bill Buzbee1465db52009-09-23 17:17:35 -0700271 loadPair(cUnit, regPtr, rlResult.lowReg, rlResult.highReg);
jeffhao9e45c0b2010-02-03 10:24:05 -0800272#if defined(WITH_SELF_VERIFICATION)
273 cUnit->heapMemOp = false;
Jeff Hao97319a82009-08-12 16:57:15 -0700274#endif
Bill Buzbeec6f10662010-02-09 11:16:15 -0800275 dvmCompilerFreeTemp(cUnit, regPtr);
Bill Buzbee1465db52009-09-23 17:17:35 -0700276 storeValueWide(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700277}
278
279/* Store a wide field to an object instance */
280static void genIPutWide(CompilationUnit *cUnit, MIR *mir, int fieldOffset)
281{
282 DecodedInstruction *dInsn = &mir->dalvikInsn;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800283 RegLocation rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
284 RegLocation rlObj = dvmCompilerGetSrc(cUnit, mir, 2);
Bill Buzbee1465db52009-09-23 17:17:35 -0700285 rlObj = loadValue(cUnit, rlObj, kCoreReg);
286 int regPtr;
287 rlSrc = loadValueWide(cUnit, rlSrc, kAnyReg);
288 genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset,
289 NULL);/* null object? */
Bill Buzbeec6f10662010-02-09 11:16:15 -0800290 regPtr = dvmCompilerAllocTemp(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700291 opRegRegImm(cUnit, kOpAdd, regPtr, rlObj.lowReg, fieldOffset);
jeffhao9e45c0b2010-02-03 10:24:05 -0800292#if defined(WITH_SELF_VERIFICATION)
293 cUnit->heapMemOp = true;
294#endif
Bill Buzbee1465db52009-09-23 17:17:35 -0700295 storePair(cUnit, regPtr, rlSrc.lowReg, rlSrc.highReg);
jeffhao9e45c0b2010-02-03 10:24:05 -0800296#if defined(WITH_SELF_VERIFICATION)
297 cUnit->heapMemOp = false;
Jeff Hao97319a82009-08-12 16:57:15 -0700298#endif
Bill Buzbeec6f10662010-02-09 11:16:15 -0800299 dvmCompilerFreeTemp(cUnit, regPtr);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700300}
301
302/*
303 * Load a field from an object instance
304 *
Ben Chengba4fc8b2009-06-01 13:00:29 -0700305 */
Bill Buzbee270c1d62009-08-13 16:58:07 -0700306static void genIGet(CompilationUnit *cUnit, MIR *mir, OpSize size,
Ben Chengba4fc8b2009-06-01 13:00:29 -0700307 int fieldOffset)
308{
Bill Buzbee1465db52009-09-23 17:17:35 -0700309 int regPtr;
310 RegLocation rlResult;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700311 DecodedInstruction *dInsn = &mir->dalvikInsn;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800312 RegLocation rlObj = dvmCompilerGetSrc(cUnit, mir, 0);
313 RegLocation rlDest = dvmCompilerGetDest(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -0700314 rlObj = loadValue(cUnit, rlObj, kCoreReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800315 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -0700316 genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset,
317 NULL);/* null object? */
jeffhao9e45c0b2010-02-03 10:24:05 -0800318#if defined(WITH_SELF_VERIFICATION)
319 cUnit->heapMemOp = true;
320#endif
Ben Cheng5d90c202009-11-22 23:31:11 -0800321 loadBaseDisp(cUnit, mir, rlObj.lowReg, fieldOffset, rlResult.lowReg,
322 size, rlObj.sRegLow);
jeffhao9e45c0b2010-02-03 10:24:05 -0800323#if defined(WITH_SELF_VERIFICATION)
324 cUnit->heapMemOp = false;
Jeff Hao97319a82009-08-12 16:57:15 -0700325#endif
Bill Buzbee1465db52009-09-23 17:17:35 -0700326 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700327}
328
329/*
330 * Store a field to an object instance
331 *
Ben Chengba4fc8b2009-06-01 13:00:29 -0700332 */
Bill Buzbee270c1d62009-08-13 16:58:07 -0700333static void genIPut(CompilationUnit *cUnit, MIR *mir, OpSize size,
Ben Chengba4fc8b2009-06-01 13:00:29 -0700334 int fieldOffset)
335{
336 DecodedInstruction *dInsn = &mir->dalvikInsn;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800337 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
338 RegLocation rlObj = dvmCompilerGetSrc(cUnit, mir, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -0700339 rlObj = loadValue(cUnit, rlObj, kCoreReg);
340 rlSrc = loadValue(cUnit, rlSrc, kAnyReg);
341 int regPtr;
342 genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset,
343 NULL);/* null object? */
jeffhao9e45c0b2010-02-03 10:24:05 -0800344#if defined(WITH_SELF_VERIFICATION)
345 cUnit->heapMemOp = true;
346#endif
Bill Buzbee1465db52009-09-23 17:17:35 -0700347 storeBaseDisp(cUnit, rlObj.lowReg, fieldOffset, rlSrc.lowReg, size);
jeffhao9e45c0b2010-02-03 10:24:05 -0800348#if defined(WITH_SELF_VERIFICATION)
349 cUnit->heapMemOp = false;
Jeff Hao97319a82009-08-12 16:57:15 -0700350#endif
Ben Chengba4fc8b2009-06-01 13:00:29 -0700351}
352
353
Ben Chengba4fc8b2009-06-01 13:00:29 -0700354/*
355 * Generate array load
Ben Chengba4fc8b2009-06-01 13:00:29 -0700356 */
Bill Buzbee270c1d62009-08-13 16:58:07 -0700357static void genArrayGet(CompilationUnit *cUnit, MIR *mir, OpSize size,
Bill Buzbee1465db52009-09-23 17:17:35 -0700358 RegLocation rlArray, RegLocation rlIndex,
359 RegLocation rlDest, int scale)
Ben Chengba4fc8b2009-06-01 13:00:29 -0700360{
361 int lenOffset = offsetof(ArrayObject, length);
362 int dataOffset = offsetof(ArrayObject, contents);
Bill Buzbee1465db52009-09-23 17:17:35 -0700363 RegLocation rlResult;
364 rlArray = loadValue(cUnit, rlArray, kCoreReg);
365 rlIndex = loadValue(cUnit, rlIndex, kCoreReg);
366 int regPtr;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700367
368 /* null object? */
Ben Cheng4238ec22009-08-24 16:32:22 -0700369 ArmLIR * pcrLabel = NULL;
370
371 if (!(mir->OptimizationFlags & MIR_IGNORE_NULL_CHECK)) {
Bill Buzbee1465db52009-09-23 17:17:35 -0700372 pcrLabel = genNullCheck(cUnit, rlArray.sRegLow,
373 rlArray.lowReg, mir->offset, NULL);
Ben Cheng4238ec22009-08-24 16:32:22 -0700374 }
375
Bill Buzbeec6f10662010-02-09 11:16:15 -0800376 regPtr = dvmCompilerAllocTemp(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700377
Ben Cheng4238ec22009-08-24 16:32:22 -0700378 if (!(mir->OptimizationFlags & MIR_IGNORE_RANGE_CHECK)) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800379 int regLen = dvmCompilerAllocTemp(cUnit);
Ben Cheng4238ec22009-08-24 16:32:22 -0700380 /* Get len */
Bill Buzbee1465db52009-09-23 17:17:35 -0700381 loadWordDisp(cUnit, rlArray.lowReg, lenOffset, regLen);
382 /* regPtr -> array data */
383 opRegRegImm(cUnit, kOpAdd, regPtr, rlArray.lowReg, dataOffset);
384 genBoundsCheck(cUnit, rlIndex.lowReg, regLen, mir->offset,
385 pcrLabel);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800386 dvmCompilerFreeTemp(cUnit, regLen);
Ben Cheng4238ec22009-08-24 16:32:22 -0700387 } else {
Bill Buzbee1465db52009-09-23 17:17:35 -0700388 /* regPtr -> array data */
389 opRegRegImm(cUnit, kOpAdd, regPtr, rlArray.lowReg, dataOffset);
Ben Cheng4238ec22009-08-24 16:32:22 -0700390 }
Bill Buzbee1465db52009-09-23 17:17:35 -0700391 if ((size == kLong) || (size == kDouble)) {
392 if (scale) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800393 int rNewIndex = dvmCompilerAllocTemp(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700394 opRegRegImm(cUnit, kOpLsl, rNewIndex, rlIndex.lowReg, scale);
395 opRegReg(cUnit, kOpAdd, regPtr, rNewIndex);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800396 dvmCompilerFreeTemp(cUnit, rNewIndex);
Bill Buzbee1465db52009-09-23 17:17:35 -0700397 } else {
398 opRegReg(cUnit, kOpAdd, regPtr, rlIndex.lowReg);
399 }
Bill Buzbeec6f10662010-02-09 11:16:15 -0800400 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
jeffhao9e45c0b2010-02-03 10:24:05 -0800401#if defined(WITH_SELF_VERIFICATION)
402 cUnit->heapMemOp = true;
403#endif
Bill Buzbee1465db52009-09-23 17:17:35 -0700404 loadPair(cUnit, regPtr, rlResult.lowReg, rlResult.highReg);
jeffhao9e45c0b2010-02-03 10:24:05 -0800405#if defined(WITH_SELF_VERIFICATION)
406 cUnit->heapMemOp = false;
407#endif
Bill Buzbeec6f10662010-02-09 11:16:15 -0800408 dvmCompilerFreeTemp(cUnit, regPtr);
Bill Buzbee1465db52009-09-23 17:17:35 -0700409 storeValueWide(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700410 } else {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800411 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
jeffhao9e45c0b2010-02-03 10:24:05 -0800412#if defined(WITH_SELF_VERIFICATION)
413 cUnit->heapMemOp = true;
414#endif
Bill Buzbee1465db52009-09-23 17:17:35 -0700415 loadBaseIndexed(cUnit, regPtr, rlIndex.lowReg, rlResult.lowReg,
416 scale, size);
jeffhao9e45c0b2010-02-03 10:24:05 -0800417#if defined(WITH_SELF_VERIFICATION)
418 cUnit->heapMemOp = false;
419#endif
Bill Buzbeec6f10662010-02-09 11:16:15 -0800420 dvmCompilerFreeTemp(cUnit, regPtr);
Bill Buzbee1465db52009-09-23 17:17:35 -0700421 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700422 }
423}
424
Ben Chengba4fc8b2009-06-01 13:00:29 -0700425/*
426 * Generate array store
427 *
Ben Chengba4fc8b2009-06-01 13:00:29 -0700428 */
Bill Buzbee270c1d62009-08-13 16:58:07 -0700429static void genArrayPut(CompilationUnit *cUnit, MIR *mir, OpSize size,
Bill Buzbee1465db52009-09-23 17:17:35 -0700430 RegLocation rlArray, RegLocation rlIndex,
431 RegLocation rlSrc, int scale)
Ben Chengba4fc8b2009-06-01 13:00:29 -0700432{
433 int lenOffset = offsetof(ArrayObject, length);
434 int dataOffset = offsetof(ArrayObject, contents);
435
Bill Buzbee1465db52009-09-23 17:17:35 -0700436 int regPtr;
437 rlArray = loadValue(cUnit, rlArray, kCoreReg);
438 rlIndex = loadValue(cUnit, rlIndex, kCoreReg);
Ben Chenge9695e52009-06-16 16:11:47 -0700439
Bill Buzbeec6f10662010-02-09 11:16:15 -0800440 if (dvmCompilerIsTemp(cUnit, rlArray.lowReg)) {
441 dvmCompilerClobber(cUnit, rlArray.lowReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700442 regPtr = rlArray.lowReg;
443 } else {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800444 regPtr = dvmCompilerAllocTemp(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700445 genRegCopy(cUnit, regPtr, rlArray.lowReg);
446 }
Ben Chenge9695e52009-06-16 16:11:47 -0700447
Ben Cheng1efc9c52009-06-08 18:25:27 -0700448 /* null object? */
Ben Cheng4238ec22009-08-24 16:32:22 -0700449 ArmLIR * pcrLabel = NULL;
450
451 if (!(mir->OptimizationFlags & MIR_IGNORE_NULL_CHECK)) {
Bill Buzbee1465db52009-09-23 17:17:35 -0700452 pcrLabel = genNullCheck(cUnit, rlArray.sRegLow, rlArray.lowReg,
453 mir->offset, NULL);
Ben Cheng4238ec22009-08-24 16:32:22 -0700454 }
455
456 if (!(mir->OptimizationFlags & MIR_IGNORE_RANGE_CHECK)) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800457 int regLen = dvmCompilerAllocTemp(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700458 //NOTE: max live temps(4) here.
Ben Cheng4238ec22009-08-24 16:32:22 -0700459 /* Get len */
Bill Buzbee1465db52009-09-23 17:17:35 -0700460 loadWordDisp(cUnit, rlArray.lowReg, lenOffset, regLen);
461 /* regPtr -> array data */
462 opRegImm(cUnit, kOpAdd, regPtr, dataOffset);
463 genBoundsCheck(cUnit, rlIndex.lowReg, regLen, mir->offset,
464 pcrLabel);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800465 dvmCompilerFreeTemp(cUnit, regLen);
Ben Cheng4238ec22009-08-24 16:32:22 -0700466 } else {
Bill Buzbee1465db52009-09-23 17:17:35 -0700467 /* regPtr -> array data */
468 opRegImm(cUnit, kOpAdd, regPtr, dataOffset);
Ben Cheng4238ec22009-08-24 16:32:22 -0700469 }
Bill Buzbee1465db52009-09-23 17:17:35 -0700470 /* at this point, regPtr points to array, 2 live temps */
Bill Buzbee1465db52009-09-23 17:17:35 -0700471 if ((size == kLong) || (size == kDouble)) {
472 //TODO: need specific wide routine that can handle fp regs
473 if (scale) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800474 int rNewIndex = dvmCompilerAllocTemp(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700475 opRegRegImm(cUnit, kOpLsl, rNewIndex, rlIndex.lowReg, scale);
476 opRegReg(cUnit, kOpAdd, regPtr, rNewIndex);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800477 dvmCompilerFreeTemp(cUnit, rNewIndex);
Bill Buzbee1465db52009-09-23 17:17:35 -0700478 } else {
479 opRegReg(cUnit, kOpAdd, regPtr, rlIndex.lowReg);
480 }
481 rlSrc = loadValueWide(cUnit, rlSrc, kAnyReg);
jeffhao9e45c0b2010-02-03 10:24:05 -0800482#if defined(WITH_SELF_VERIFICATION)
483 cUnit->heapMemOp = true;
484#endif
Bill Buzbee1465db52009-09-23 17:17:35 -0700485 storePair(cUnit, regPtr, rlSrc.lowReg, rlSrc.highReg);
jeffhao9e45c0b2010-02-03 10:24:05 -0800486#if defined(WITH_SELF_VERIFICATION)
487 cUnit->heapMemOp = false;
488#endif
Bill Buzbeec6f10662010-02-09 11:16:15 -0800489 dvmCompilerFreeTemp(cUnit, regPtr);
Bill Buzbee270c1d62009-08-13 16:58:07 -0700490 } else {
Bill Buzbee1465db52009-09-23 17:17:35 -0700491 rlSrc = loadValue(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 storeBaseIndexed(cUnit, regPtr, rlIndex.lowReg, rlSrc.lowReg,
496 scale, size);
jeffhao9e45c0b2010-02-03 10:24:05 -0800497#if defined(WITH_SELF_VERIFICATION)
498 cUnit->heapMemOp = false;
Jeff Hao97319a82009-08-12 16:57:15 -0700499#endif
jeffhao9e45c0b2010-02-03 10:24:05 -0800500 }
Ben Chengba4fc8b2009-06-01 13:00:29 -0700501}
502
Ben Cheng5d90c202009-11-22 23:31:11 -0800503static bool genShiftOpLong(CompilationUnit *cUnit, MIR *mir,
504 RegLocation rlDest, RegLocation rlSrc1,
505 RegLocation rlShift)
Ben Chengba4fc8b2009-06-01 13:00:29 -0700506{
Ben Chenge9695e52009-06-16 16:11:47 -0700507 /*
508 * Don't mess with the regsiters here as there is a particular calling
509 * convention to the out-of-line handler.
510 */
Bill Buzbee1465db52009-09-23 17:17:35 -0700511 RegLocation rlResult;
512
513 loadValueDirectWideFixed(cUnit, rlSrc1, r0, r1);
514 loadValueDirect(cUnit, rlShift, r2);
Ben Chenge9695e52009-06-16 16:11:47 -0700515 switch( mir->dalvikInsn.opCode) {
516 case OP_SHL_LONG:
517 case OP_SHL_LONG_2ADDR:
518 genDispatchToHandler(cUnit, TEMPLATE_SHL_LONG);
519 break;
520 case OP_SHR_LONG:
521 case OP_SHR_LONG_2ADDR:
522 genDispatchToHandler(cUnit, TEMPLATE_SHR_LONG);
523 break;
524 case OP_USHR_LONG:
525 case OP_USHR_LONG_2ADDR:
526 genDispatchToHandler(cUnit, TEMPLATE_USHR_LONG);
527 break;
528 default:
529 return true;
530 }
Bill Buzbeec6f10662010-02-09 11:16:15 -0800531 rlResult = dvmCompilerGetReturnWide(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700532 storeValueWide(cUnit, rlDest, rlResult);
Ben Chenge9695e52009-06-16 16:11:47 -0700533 return false;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700534}
Ben Chenge9695e52009-06-16 16:11:47 -0700535
Ben Cheng5d90c202009-11-22 23:31:11 -0800536static bool genArithOpLong(CompilationUnit *cUnit, MIR *mir,
537 RegLocation rlDest, RegLocation rlSrc1,
538 RegLocation rlSrc2)
Ben Chengba4fc8b2009-06-01 13:00:29 -0700539{
Bill Buzbee1465db52009-09-23 17:17:35 -0700540 RegLocation rlResult;
541 OpKind firstOp = kOpBkpt;
542 OpKind secondOp = kOpBkpt;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700543 bool callOut = false;
544 void *callTgt;
545 int retReg = r0;
546 /* TODO - find proper .h file to declare these */
547 long long __aeabi_ldivmod(long long op1, long long op2);
548
549 switch (mir->dalvikInsn.opCode) {
550 case OP_NOT_LONG:
Bill Buzbee1465db52009-09-23 17:17:35 -0700551 rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800552 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -0700553 opRegReg(cUnit, kOpMvn, rlResult.lowReg, rlSrc2.lowReg);
554 opRegReg(cUnit, kOpMvn, rlResult.highReg, rlSrc2.highReg);
555 storeValueWide(cUnit, rlDest, rlResult);
556 return false;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700557 break;
558 case OP_ADD_LONG:
559 case OP_ADD_LONG_2ADDR:
Bill Buzbee1465db52009-09-23 17:17:35 -0700560 firstOp = kOpAdd;
561 secondOp = kOpAdc;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700562 break;
563 case OP_SUB_LONG:
564 case OP_SUB_LONG_2ADDR:
Bill Buzbee1465db52009-09-23 17:17:35 -0700565 firstOp = kOpSub;
566 secondOp = kOpSbc;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700567 break;
568 case OP_MUL_LONG:
569 case OP_MUL_LONG_2ADDR:
Bill Buzbee1465db52009-09-23 17:17:35 -0700570 genMulLong(cUnit, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700571 return false;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700572 case OP_DIV_LONG:
573 case OP_DIV_LONG_2ADDR:
574 callOut = true;
575 retReg = r0;
576 callTgt = (void*)__aeabi_ldivmod;
577 break;
578 /* NOTE - result is in r2/r3 instead of r0/r1 */
579 case OP_REM_LONG:
580 case OP_REM_LONG_2ADDR:
581 callOut = true;
582 callTgt = (void*)__aeabi_ldivmod;
583 retReg = r2;
584 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700585 case OP_AND_LONG_2ADDR:
Bill Buzbee1465db52009-09-23 17:17:35 -0700586 case OP_AND_LONG:
587 firstOp = kOpAnd;
588 secondOp = kOpAnd;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700589 break;
590 case OP_OR_LONG:
591 case OP_OR_LONG_2ADDR:
Bill Buzbee1465db52009-09-23 17:17:35 -0700592 firstOp = kOpOr;
593 secondOp = kOpOr;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700594 break;
595 case OP_XOR_LONG:
596 case OP_XOR_LONG_2ADDR:
Bill Buzbee1465db52009-09-23 17:17:35 -0700597 firstOp = kOpXor;
598 secondOp = kOpXor;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700599 break;
Ben Chenge9695e52009-06-16 16:11:47 -0700600 case OP_NEG_LONG: {
Bill Buzbee51ecf602010-01-14 14:27:52 -0800601 //TUNING: can improve this using Thumb2 code
Bill Buzbeec6f10662010-02-09 11:16:15 -0800602 int tReg = dvmCompilerAllocTemp(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700603 rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800604 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee51ecf602010-01-14 14:27:52 -0800605 loadConstantValue(cUnit, tReg, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -0700606 opRegRegReg(cUnit, kOpSub, rlResult.lowReg,
Bill Buzbee51ecf602010-01-14 14:27:52 -0800607 tReg, rlSrc2.lowReg);
608 opRegReg(cUnit, kOpSbc, tReg, rlSrc2.highReg);
609 genRegCopy(cUnit, rlResult.highReg, tReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700610 storeValueWide(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700611 return false;
Ben Chenge9695e52009-06-16 16:11:47 -0700612 }
Ben Chengba4fc8b2009-06-01 13:00:29 -0700613 default:
614 LOGE("Invalid long arith op");
615 dvmAbort();
616 }
617 if (!callOut) {
Bill Buzbee1465db52009-09-23 17:17:35 -0700618 genLong3Addr(cUnit, firstOp, secondOp, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700619 } else {
Bill Buzbee1465db52009-09-23 17:17:35 -0700620 // Adjust return regs in to handle case of rem returning r2/r3
Bill Buzbeec6f10662010-02-09 11:16:15 -0800621 dvmCompilerFlushAllRegs(cUnit); /* Send everything to home location */
Bill Buzbee1465db52009-09-23 17:17:35 -0700622 loadValueDirectWideFixed(cUnit, rlSrc1, r0, r1);
623 loadConstant(cUnit, rlr, (int) callTgt);
624 loadValueDirectWideFixed(cUnit, rlSrc2, r2, r3);
625 opReg(cUnit, kOpBlx, rlr);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800626 dvmCompilerColbberCallRegs(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700627 if (retReg == r0)
Bill Buzbeec6f10662010-02-09 11:16:15 -0800628 rlResult = dvmCompilerGetReturnWide(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700629 else
Bill Buzbeec6f10662010-02-09 11:16:15 -0800630 rlResult = dvmCompilerGetReturnWideAlt(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700631 storeValueWide(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700632 }
633 return false;
634}
635
Ben Cheng5d90c202009-11-22 23:31:11 -0800636static bool genArithOpInt(CompilationUnit *cUnit, MIR *mir,
637 RegLocation rlDest, RegLocation rlSrc1,
638 RegLocation rlSrc2)
Ben Chengba4fc8b2009-06-01 13:00:29 -0700639{
Bill Buzbee1465db52009-09-23 17:17:35 -0700640 OpKind op = kOpBkpt;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700641 bool callOut = false;
642 bool checkZero = false;
Bill Buzbee1465db52009-09-23 17:17:35 -0700643 bool unary = false;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700644 int retReg = r0;
645 void *callTgt;
Bill Buzbee1465db52009-09-23 17:17:35 -0700646 RegLocation rlResult;
Bill Buzbee0e605272009-12-01 14:28:05 -0800647 bool shiftOp = false;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700648
649 /* TODO - find proper .h file to declare these */
650 int __aeabi_idivmod(int op1, int op2);
651 int __aeabi_idiv(int op1, int op2);
652
653 switch (mir->dalvikInsn.opCode) {
654 case OP_NEG_INT:
Bill Buzbee1465db52009-09-23 17:17:35 -0700655 op = kOpNeg;
656 unary = true;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700657 break;
658 case OP_NOT_INT:
Bill Buzbee1465db52009-09-23 17:17:35 -0700659 op = kOpMvn;
660 unary = true;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700661 break;
662 case OP_ADD_INT:
663 case OP_ADD_INT_2ADDR:
Bill Buzbee1465db52009-09-23 17:17:35 -0700664 op = kOpAdd;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700665 break;
666 case OP_SUB_INT:
667 case OP_SUB_INT_2ADDR:
Bill Buzbee1465db52009-09-23 17:17:35 -0700668 op = kOpSub;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700669 break;
670 case OP_MUL_INT:
671 case OP_MUL_INT_2ADDR:
Bill Buzbee1465db52009-09-23 17:17:35 -0700672 op = kOpMul;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700673 break;
674 case OP_DIV_INT:
675 case OP_DIV_INT_2ADDR:
676 callOut = true;
677 checkZero = true;
678 callTgt = __aeabi_idiv;
679 retReg = r0;
680 break;
681 /* NOTE: returns in r1 */
682 case OP_REM_INT:
683 case OP_REM_INT_2ADDR:
684 callOut = true;
685 checkZero = true;
686 callTgt = __aeabi_idivmod;
687 retReg = r1;
688 break;
689 case OP_AND_INT:
690 case OP_AND_INT_2ADDR:
Bill Buzbee1465db52009-09-23 17:17:35 -0700691 op = kOpAnd;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700692 break;
693 case OP_OR_INT:
694 case OP_OR_INT_2ADDR:
Bill Buzbee1465db52009-09-23 17:17:35 -0700695 op = kOpOr;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700696 break;
697 case OP_XOR_INT:
698 case OP_XOR_INT_2ADDR:
Bill Buzbee1465db52009-09-23 17:17:35 -0700699 op = kOpXor;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700700 break;
701 case OP_SHL_INT:
702 case OP_SHL_INT_2ADDR:
Bill Buzbee0e605272009-12-01 14:28:05 -0800703 shiftOp = true;
Bill Buzbee1465db52009-09-23 17:17:35 -0700704 op = kOpLsl;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700705 break;
706 case OP_SHR_INT:
707 case OP_SHR_INT_2ADDR:
Bill Buzbee0e605272009-12-01 14:28:05 -0800708 shiftOp = true;
Bill Buzbee1465db52009-09-23 17:17:35 -0700709 op = kOpAsr;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700710 break;
711 case OP_USHR_INT:
712 case OP_USHR_INT_2ADDR:
Bill Buzbee0e605272009-12-01 14:28:05 -0800713 shiftOp = true;
Bill Buzbee1465db52009-09-23 17:17:35 -0700714 op = kOpLsr;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700715 break;
716 default:
717 LOGE("Invalid word arith op: 0x%x(%d)",
718 mir->dalvikInsn.opCode, mir->dalvikInsn.opCode);
719 dvmAbort();
720 }
721 if (!callOut) {
Bill Buzbee1465db52009-09-23 17:17:35 -0700722 rlSrc1 = loadValue(cUnit, rlSrc1, kCoreReg);
723 if (unary) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800724 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -0700725 opRegReg(cUnit, op, rlResult.lowReg,
726 rlSrc1.lowReg);
Ben Chenge9695e52009-06-16 16:11:47 -0700727 } else {
Bill Buzbee1465db52009-09-23 17:17:35 -0700728 rlSrc2 = loadValue(cUnit, rlSrc2, kCoreReg);
Bill Buzbee0e605272009-12-01 14:28:05 -0800729 if (shiftOp) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800730 int tReg = dvmCompilerAllocTemp(cUnit);
Bill Buzbee0e605272009-12-01 14:28:05 -0800731 opRegRegImm(cUnit, kOpAnd, tReg, rlSrc2.lowReg, 31);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800732 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee0e605272009-12-01 14:28:05 -0800733 opRegRegReg(cUnit, op, rlResult.lowReg,
734 rlSrc1.lowReg, tReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800735 dvmCompilerFreeTemp(cUnit, tReg);
Bill Buzbee0e605272009-12-01 14:28:05 -0800736 } else {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800737 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee0e605272009-12-01 14:28:05 -0800738 opRegRegReg(cUnit, op, rlResult.lowReg,
739 rlSrc1.lowReg, rlSrc2.lowReg);
740 }
Ben Chenge9695e52009-06-16 16:11:47 -0700741 }
Bill Buzbee1465db52009-09-23 17:17:35 -0700742 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700743 } else {
Bill Buzbee1465db52009-09-23 17:17:35 -0700744 RegLocation rlResult;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800745 dvmCompilerFlushAllRegs(cUnit); /* Send everything to home location */
Bill Buzbee1465db52009-09-23 17:17:35 -0700746 loadValueDirectFixed(cUnit, rlSrc2, r1);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700747 loadConstant(cUnit, r2, (int) callTgt);
Bill Buzbee1465db52009-09-23 17:17:35 -0700748 loadValueDirectFixed(cUnit, rlSrc1, r0);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700749 if (checkZero) {
Bill Buzbee1465db52009-09-23 17:17:35 -0700750 genNullCheck(cUnit, rlSrc2.sRegLow, r1, mir->offset, NULL);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700751 }
Bill Buzbee1465db52009-09-23 17:17:35 -0700752 opReg(cUnit, kOpBlx, r2);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800753 dvmCompilerColbberCallRegs(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700754 if (retReg == r0)
Bill Buzbeec6f10662010-02-09 11:16:15 -0800755 rlResult = dvmCompilerGetReturn(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700756 else
Bill Buzbeec6f10662010-02-09 11:16:15 -0800757 rlResult = dvmCompilerGetReturnAlt(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700758 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700759 }
760 return false;
761}
762
Ben Cheng5d90c202009-11-22 23:31:11 -0800763static bool genArithOp(CompilationUnit *cUnit, MIR *mir)
Ben Chengba4fc8b2009-06-01 13:00:29 -0700764{
765 OpCode opCode = mir->dalvikInsn.opCode;
Bill Buzbee1465db52009-09-23 17:17:35 -0700766 RegLocation rlDest;
767 RegLocation rlSrc1;
768 RegLocation rlSrc2;
769 /* Deduce sizes of operands */
770 if (mir->ssaRep->numUses == 2) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800771 rlSrc1 = dvmCompilerGetSrc(cUnit, mir, 0);
772 rlSrc2 = dvmCompilerGetSrc(cUnit, mir, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -0700773 } else if (mir->ssaRep->numUses == 3) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800774 rlSrc1 = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
775 rlSrc2 = dvmCompilerGetSrc(cUnit, mir, 2);
Bill Buzbee1465db52009-09-23 17:17:35 -0700776 } else {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800777 rlSrc1 = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
778 rlSrc2 = dvmCompilerGetSrcWide(cUnit, mir, 2, 3);
Bill Buzbee1465db52009-09-23 17:17:35 -0700779 assert(mir->ssaRep->numUses == 4);
780 }
781 if (mir->ssaRep->numDefs == 1) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800782 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -0700783 } else {
784 assert(mir->ssaRep->numDefs == 2);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800785 rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -0700786 }
Ben Chengba4fc8b2009-06-01 13:00:29 -0700787
788 if ((opCode >= OP_ADD_LONG_2ADDR) && (opCode <= OP_XOR_LONG_2ADDR)) {
Ben Cheng5d90c202009-11-22 23:31:11 -0800789 return genArithOpLong(cUnit,mir, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700790 }
791 if ((opCode >= OP_ADD_LONG) && (opCode <= OP_XOR_LONG)) {
Ben Cheng5d90c202009-11-22 23:31:11 -0800792 return genArithOpLong(cUnit,mir, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700793 }
794 if ((opCode >= OP_SHL_LONG_2ADDR) && (opCode <= OP_USHR_LONG_2ADDR)) {
Ben Cheng5d90c202009-11-22 23:31:11 -0800795 return genShiftOpLong(cUnit,mir, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700796 }
797 if ((opCode >= OP_SHL_LONG) && (opCode <= OP_USHR_LONG)) {
Ben Cheng5d90c202009-11-22 23:31:11 -0800798 return genShiftOpLong(cUnit,mir, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700799 }
800 if ((opCode >= OP_ADD_INT_2ADDR) && (opCode <= OP_USHR_INT_2ADDR)) {
Ben Cheng5d90c202009-11-22 23:31:11 -0800801 return genArithOpInt(cUnit,mir, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700802 }
803 if ((opCode >= OP_ADD_INT) && (opCode <= OP_USHR_INT)) {
Ben Cheng5d90c202009-11-22 23:31:11 -0800804 return genArithOpInt(cUnit,mir, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700805 }
806 if ((opCode >= OP_ADD_FLOAT_2ADDR) && (opCode <= OP_REM_FLOAT_2ADDR)) {
Ben Cheng5d90c202009-11-22 23:31:11 -0800807 return genArithOpFloat(cUnit,mir, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700808 }
809 if ((opCode >= OP_ADD_FLOAT) && (opCode <= OP_REM_FLOAT)) {
Ben Cheng5d90c202009-11-22 23:31:11 -0800810 return genArithOpFloat(cUnit, mir, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700811 }
812 if ((opCode >= OP_ADD_DOUBLE_2ADDR) && (opCode <= OP_REM_DOUBLE_2ADDR)) {
Ben Cheng5d90c202009-11-22 23:31:11 -0800813 return genArithOpDouble(cUnit,mir, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700814 }
815 if ((opCode >= OP_ADD_DOUBLE) && (opCode <= OP_REM_DOUBLE)) {
Ben Cheng5d90c202009-11-22 23:31:11 -0800816 return genArithOpDouble(cUnit,mir, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700817 }
818 return true;
819}
820
Bill Buzbee1465db52009-09-23 17:17:35 -0700821/* Generate conditional branch instructions */
822static ArmLIR *genConditionalBranch(CompilationUnit *cUnit,
823 ArmConditionCode cond,
824 ArmLIR *target)
825{
826 ArmLIR *branch = opCondBranch(cUnit, cond);
827 branch->generic.target = (LIR *) target;
828 return branch;
829}
830
831/* Generate unconditional branch instructions */
832static ArmLIR *genUnconditionalBranch(CompilationUnit *cUnit, ArmLIR *target)
833{
834 ArmLIR *branch = opNone(cUnit, kOpUncondBr);
835 branch->generic.target = (LIR *) target;
836 return branch;
837}
838
Bill Buzbee1465db52009-09-23 17:17:35 -0700839/* Perform the actual operation for OP_RETURN_* */
840static void genReturnCommon(CompilationUnit *cUnit, MIR *mir)
841{
842 genDispatchToHandler(cUnit, TEMPLATE_RETURN);
843#if defined(INVOKE_STATS)
844 gDvmJit.returnOp++;
845#endif
846 int dPC = (int) (cUnit->method->insns + mir->offset);
847 /* Insert branch, but defer setting of target */
848 ArmLIR *branch = genUnconditionalBranch(cUnit, NULL);
849 /* Set up the place holder to reconstruct this Dalvik PC */
850 ArmLIR *pcrLabel = dvmCompilerNew(sizeof(ArmLIR), true);
851 pcrLabel->opCode = ARM_PSEUDO_kPCReconstruction_CELL;
852 pcrLabel->operands[0] = dPC;
853 pcrLabel->operands[1] = mir->offset;
854 /* Insert the place holder to the growable list */
855 dvmInsertGrowableList(&cUnit->pcReconstructionList, pcrLabel);
856 /* Branch to the PC reconstruction code */
857 branch->generic.target = (LIR *) pcrLabel;
858}
859
Ben Chengba4fc8b2009-06-01 13:00:29 -0700860static void genProcessArgsNoRange(CompilationUnit *cUnit, MIR *mir,
861 DecodedInstruction *dInsn,
Bill Buzbee89efc3d2009-07-28 11:22:22 -0700862 ArmLIR **pcrLabel)
Ben Chengba4fc8b2009-06-01 13:00:29 -0700863{
864 unsigned int i;
865 unsigned int regMask = 0;
Bill Buzbee1465db52009-09-23 17:17:35 -0700866 RegLocation rlArg;
867 int numDone = 0;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700868
Bill Buzbee1465db52009-09-23 17:17:35 -0700869 /*
870 * Load arguments to r0..r4. Note that these registers may contain
871 * live values, so we clobber them immediately after loading to prevent
872 * them from being used as sources for subsequent loads.
873 */
Bill Buzbeec6f10662010-02-09 11:16:15 -0800874 dvmCompilerLockAllTemps(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700875 for (i = 0; i < dInsn->vA; i++) {
876 regMask |= 1 << i;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800877 rlArg = dvmCompilerGetSrc(cUnit, mir, numDone++);
Bill Buzbee1465db52009-09-23 17:17:35 -0700878 loadValueDirectFixed(cUnit, rlArg, i);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700879 }
880 if (regMask) {
881 /* Up to 5 args are pushed on top of FP - sizeofStackSaveArea */
Bill Buzbee1465db52009-09-23 17:17:35 -0700882 opRegRegImm(cUnit, kOpSub, r7, rFP,
883 sizeof(StackSaveArea) + (dInsn->vA << 2));
Ben Chengba4fc8b2009-06-01 13:00:29 -0700884 /* generate null check */
885 if (pcrLabel) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800886 *pcrLabel = genNullCheck(cUnit, dvmCompilerSSASrc(mir, 0), r0,
Bill Buzbee1465db52009-09-23 17:17:35 -0700887 mir->offset, NULL);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700888 }
Bill Buzbee270c1d62009-08-13 16:58:07 -0700889 storeMultiple(cUnit, r7, regMask);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700890 }
891}
892
893static void genProcessArgsRange(CompilationUnit *cUnit, MIR *mir,
894 DecodedInstruction *dInsn,
Bill Buzbee89efc3d2009-07-28 11:22:22 -0700895 ArmLIR **pcrLabel)
Ben Chengba4fc8b2009-06-01 13:00:29 -0700896{
897 int srcOffset = dInsn->vC << 2;
898 int numArgs = dInsn->vA;
899 int regMask;
Bill Buzbee1465db52009-09-23 17:17:35 -0700900
901 /*
902 * Note: here, all promoted registers will have been flushed
903 * back to the Dalvik base locations, so register usage restrictins
904 * are lifted. All parms loaded from original Dalvik register
905 * region - even though some might conceivably have valid copies
906 * cached in a preserved register.
907 */
Bill Buzbeec6f10662010-02-09 11:16:15 -0800908 dvmCompilerLockAllTemps(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700909
Ben Chengba4fc8b2009-06-01 13:00:29 -0700910 /*
911 * r4PC : &rFP[vC]
912 * r7: &newFP[0]
913 */
Bill Buzbee1465db52009-09-23 17:17:35 -0700914 opRegRegImm(cUnit, kOpAdd, r4PC, rFP, srcOffset);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700915 /* load [r0 .. min(numArgs,4)] */
916 regMask = (1 << ((numArgs < 4) ? numArgs : 4)) - 1;
Ben Chengd7d426a2009-09-22 11:23:36 -0700917 /*
918 * Protect the loadMultiple instruction from being reordered with other
919 * Dalvik stack accesses.
920 */
Bill Buzbee270c1d62009-08-13 16:58:07 -0700921 loadMultiple(cUnit, r4PC, regMask);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700922
Bill Buzbee1465db52009-09-23 17:17:35 -0700923 opRegRegImm(cUnit, kOpSub, r7, rFP,
924 sizeof(StackSaveArea) + (numArgs << 2));
Ben Chengba4fc8b2009-06-01 13:00:29 -0700925 /* generate null check */
926 if (pcrLabel) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800927 *pcrLabel = genNullCheck(cUnit, dvmCompilerSSASrc(mir, 0), r0,
Bill Buzbee1465db52009-09-23 17:17:35 -0700928 mir->offset, NULL);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700929 }
930
931 /*
932 * Handle remaining 4n arguments:
933 * store previously loaded 4 values and load the next 4 values
934 */
935 if (numArgs >= 8) {
Bill Buzbee89efc3d2009-07-28 11:22:22 -0700936 ArmLIR *loopLabel = NULL;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700937 /*
938 * r0 contains "this" and it will be used later, so push it to the stack
Bill Buzbee270c1d62009-08-13 16:58:07 -0700939 * first. Pushing r5 (rFP) is just for stack alignment purposes.
Ben Chengba4fc8b2009-06-01 13:00:29 -0700940 */
Bill Buzbee1465db52009-09-23 17:17:35 -0700941 opImm(cUnit, kOpPush, (1 << r0 | 1 << rFP));
Ben Chengba4fc8b2009-06-01 13:00:29 -0700942 /* No need to generate the loop structure if numArgs <= 11 */
943 if (numArgs > 11) {
944 loadConstant(cUnit, 5, ((numArgs - 4) >> 2) << 2);
Bill Buzbee1465db52009-09-23 17:17:35 -0700945 loopLabel = newLIR0(cUnit, kArmPseudoTargetLabel);
Ben Chengd7d426a2009-09-22 11:23:36 -0700946 loopLabel->defMask = ENCODE_ALL;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700947 }
Bill Buzbee270c1d62009-08-13 16:58:07 -0700948 storeMultiple(cUnit, r7, regMask);
Ben Chengd7d426a2009-09-22 11:23:36 -0700949 /*
950 * Protect the loadMultiple instruction from being reordered with other
951 * Dalvik stack accesses.
952 */
Bill Buzbee270c1d62009-08-13 16:58:07 -0700953 loadMultiple(cUnit, r4PC, regMask);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700954 /* No need to generate the loop structure if numArgs <= 11 */
955 if (numArgs > 11) {
Bill Buzbee1465db52009-09-23 17:17:35 -0700956 opRegImm(cUnit, kOpSub, rFP, 4);
957 genConditionalBranch(cUnit, kArmCondNe, loopLabel);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700958 }
959 }
960
961 /* Save the last batch of loaded values */
Bill Buzbee270c1d62009-08-13 16:58:07 -0700962 storeMultiple(cUnit, r7, regMask);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700963
964 /* Generate the loop epilogue - don't use r0 */
965 if ((numArgs > 4) && (numArgs % 4)) {
966 regMask = ((1 << (numArgs & 0x3)) - 1) << 1;
Ben Chengd7d426a2009-09-22 11:23:36 -0700967 /*
968 * Protect the loadMultiple instruction from being reordered with other
969 * Dalvik stack accesses.
970 */
Bill Buzbee270c1d62009-08-13 16:58:07 -0700971 loadMultiple(cUnit, r4PC, regMask);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700972 }
973 if (numArgs >= 8)
Bill Buzbee1465db52009-09-23 17:17:35 -0700974 opImm(cUnit, kOpPop, (1 << r0 | 1 << rFP));
Ben Chengba4fc8b2009-06-01 13:00:29 -0700975
976 /* Save the modulo 4 arguments */
977 if ((numArgs > 4) && (numArgs % 4)) {
Bill Buzbee270c1d62009-08-13 16:58:07 -0700978 storeMultiple(cUnit, r7, regMask);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700979 }
980}
981
Ben Cheng38329f52009-07-07 14:19:20 -0700982/*
983 * Generate code to setup the call stack then jump to the chaining cell if it
984 * is not a native method.
985 */
986static void genInvokeSingletonCommon(CompilationUnit *cUnit, MIR *mir,
Bill Buzbee89efc3d2009-07-28 11:22:22 -0700987 BasicBlock *bb, ArmLIR *labelList,
988 ArmLIR *pcrLabel,
Ben Cheng38329f52009-07-07 14:19:20 -0700989 const Method *calleeMethod)
Ben Chengba4fc8b2009-06-01 13:00:29 -0700990{
Bill Buzbee1465db52009-09-23 17:17:35 -0700991 /*
992 * Note: all Dalvik register state should be flushed to
993 * memory by the point, so register usage restrictions no
994 * longer apply. All temp & preserved registers may be used.
995 */
Bill Buzbeec6f10662010-02-09 11:16:15 -0800996 dvmCompilerLockAllTemps(cUnit);
Bill Buzbee89efc3d2009-07-28 11:22:22 -0700997 ArmLIR *retChainingCell = &labelList[bb->fallThrough->id];
Ben Chengba4fc8b2009-06-01 13:00:29 -0700998
999 /* r1 = &retChainingCell */
Bill Buzbeec6f10662010-02-09 11:16:15 -08001000 dvmCompilerLockTemp(cUnit, r1);
Bill Buzbee1465db52009-09-23 17:17:35 -07001001 ArmLIR *addrRetChain = opRegRegImm(cUnit, kOpAdd, r1, rpc, 0);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001002 /* r4PC = dalvikCallsite */
1003 loadConstant(cUnit, r4PC,
1004 (int) (cUnit->method->insns + mir->offset));
1005 addrRetChain->generic.target = (LIR *) retChainingCell;
1006 /*
Ben Cheng38329f52009-07-07 14:19:20 -07001007 * r0 = calleeMethod (loaded upon calling genInvokeSingletonCommon)
Ben Chengba4fc8b2009-06-01 13:00:29 -07001008 * r1 = &ChainingCell
1009 * r4PC = callsiteDPC
1010 */
1011 if (dvmIsNativeMethod(calleeMethod)) {
Ben Cheng38329f52009-07-07 14:19:20 -07001012 genDispatchToHandler(cUnit, TEMPLATE_INVOKE_METHOD_NATIVE);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001013#if defined(INVOKE_STATS)
Ben Cheng38329f52009-07-07 14:19:20 -07001014 gDvmJit.invokeNative++;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001015#endif
1016 } else {
1017 genDispatchToHandler(cUnit, TEMPLATE_INVOKE_METHOD_CHAIN);
1018#if defined(INVOKE_STATS)
1019 gDvmJit.invokeChain++;
1020#endif
Ben Cheng38329f52009-07-07 14:19:20 -07001021 /* Branch to the chaining cell */
Ben Chengba4fc8b2009-06-01 13:00:29 -07001022 genUnconditionalBranch(cUnit, &labelList[bb->taken->id]);
1023 }
1024 /* Handle exceptions using the interpreter */
1025 genTrap(cUnit, mir->offset, pcrLabel);
1026}
1027
Ben Cheng38329f52009-07-07 14:19:20 -07001028/*
1029 * Generate code to check the validity of a predicted chain and take actions
1030 * based on the result.
1031 *
1032 * 0x426a99aa : ldr r4, [pc, #72] --> r4 <- dalvikPC of this invoke
1033 * 0x426a99ac : add r1, pc, #32 --> r1 <- &retChainingCell
1034 * 0x426a99ae : add r2, pc, #40 --> r2 <- &predictedChainingCell
1035 * 0x426a99b0 : blx_1 0x426a918c --+ TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN
1036 * 0x426a99b2 : blx_2 see above --+
1037 * 0x426a99b4 : b 0x426a99d8 --> off to the predicted chain
1038 * 0x426a99b6 : b 0x426a99c8 --> punt to the interpreter
1039 * 0x426a99b8 : ldr r0, [r7, #44] --> r0 <- this->class->vtable[methodIdx]
1040 * 0x426a99ba : cmp r1, #0 --> compare r1 (rechain count) against 0
1041 * 0x426a99bc : bgt 0x426a99c2 --> >=0? don't rechain
1042 * 0x426a99be : ldr r7, [r6, #96] --+ dvmJitToPatchPredictedChain
1043 * 0x426a99c0 : blx r7 --+
1044 * 0x426a99c2 : add r1, pc, #12 --> r1 <- &retChainingCell
1045 * 0x426a99c4 : blx_1 0x426a9098 --+ TEMPLATE_INVOKE_METHOD_NO_OPT
1046 * 0x426a99c6 : blx_2 see above --+
1047 */
1048static void genInvokeVirtualCommon(CompilationUnit *cUnit, MIR *mir,
1049 int methodIndex,
Bill Buzbee89efc3d2009-07-28 11:22:22 -07001050 ArmLIR *retChainingCell,
1051 ArmLIR *predChainingCell,
1052 ArmLIR *pcrLabel)
Ben Cheng38329f52009-07-07 14:19:20 -07001053{
Bill Buzbee1465db52009-09-23 17:17:35 -07001054 /*
1055 * Note: all Dalvik register state should be flushed to
1056 * memory by the point, so register usage restrictions no
1057 * longer apply. Lock temps to prevent them from being
1058 * allocated by utility routines.
1059 */
Bill Buzbeec6f10662010-02-09 11:16:15 -08001060 dvmCompilerLockAllTemps(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07001061
Ben Cheng38329f52009-07-07 14:19:20 -07001062 /* "this" is already left in r0 by genProcessArgs* */
1063
1064 /* r4PC = dalvikCallsite */
1065 loadConstant(cUnit, r4PC,
1066 (int) (cUnit->method->insns + mir->offset));
1067
1068 /* r1 = &retChainingCell */
Bill Buzbee1465db52009-09-23 17:17:35 -07001069 ArmLIR *addrRetChain = opRegRegImm(cUnit, kOpAdd, r1, rpc, 0);
Ben Cheng38329f52009-07-07 14:19:20 -07001070 addrRetChain->generic.target = (LIR *) retChainingCell;
1071
1072 /* r2 = &predictedChainingCell */
Bill Buzbee1465db52009-09-23 17:17:35 -07001073 ArmLIR *predictedChainingCell = opRegRegImm(cUnit, kOpAdd, r2, rpc, 0);
Ben Cheng38329f52009-07-07 14:19:20 -07001074 predictedChainingCell->generic.target = (LIR *) predChainingCell;
1075
1076 genDispatchToHandler(cUnit, TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN);
1077
1078 /* return through lr - jump to the chaining cell */
1079 genUnconditionalBranch(cUnit, predChainingCell);
1080
1081 /*
1082 * null-check on "this" may have been eliminated, but we still need a PC-
1083 * reconstruction label for stack overflow bailout.
1084 */
1085 if (pcrLabel == NULL) {
1086 int dPC = (int) (cUnit->method->insns + mir->offset);
Bill Buzbee89efc3d2009-07-28 11:22:22 -07001087 pcrLabel = dvmCompilerNew(sizeof(ArmLIR), true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001088 pcrLabel->opCode = ARM_PSEUDO_kPCReconstruction_CELL;
Ben Cheng38329f52009-07-07 14:19:20 -07001089 pcrLabel->operands[0] = dPC;
1090 pcrLabel->operands[1] = mir->offset;
1091 /* Insert the place holder to the growable list */
1092 dvmInsertGrowableList(&cUnit->pcReconstructionList, pcrLabel);
1093 }
1094
1095 /* return through lr+2 - punt to the interpreter */
1096 genUnconditionalBranch(cUnit, pcrLabel);
1097
1098 /*
1099 * return through lr+4 - fully resolve the callee method.
1100 * r1 <- count
1101 * r2 <- &predictedChainCell
1102 * r3 <- this->class
1103 * r4 <- dPC
1104 * r7 <- this->class->vtable
1105 */
1106
1107 /* r0 <- calleeMethod */
Bill Buzbee270c1d62009-08-13 16:58:07 -07001108 loadWordDisp(cUnit, r7, methodIndex * 4, r0);
Ben Cheng38329f52009-07-07 14:19:20 -07001109
1110 /* Check if rechain limit is reached */
Bill Buzbee1465db52009-09-23 17:17:35 -07001111 opRegImm(cUnit, kOpCmp, r1, 0);
Ben Cheng38329f52009-07-07 14:19:20 -07001112
Bill Buzbee1465db52009-09-23 17:17:35 -07001113 ArmLIR *bypassRechaining = opCondBranch(cUnit, kArmCondGt);
Ben Cheng38329f52009-07-07 14:19:20 -07001114
Bill Buzbee270c1d62009-08-13 16:58:07 -07001115 loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
1116 jitToInterpEntries.dvmJitToPatchPredictedChain), r7);
Ben Cheng38329f52009-07-07 14:19:20 -07001117
1118 /*
1119 * r0 = calleeMethod
1120 * r2 = &predictedChainingCell
1121 * r3 = class
1122 *
1123 * &returnChainingCell has been loaded into r1 but is not needed
1124 * when patching the chaining cell and will be clobbered upon
1125 * returning so it will be reconstructed again.
1126 */
Bill Buzbee1465db52009-09-23 17:17:35 -07001127 opReg(cUnit, kOpBlx, r7);
Ben Cheng38329f52009-07-07 14:19:20 -07001128
1129 /* r1 = &retChainingCell */
Bill Buzbee1465db52009-09-23 17:17:35 -07001130 addrRetChain = opRegRegImm(cUnit, kOpAdd, r1, rpc, 0);
Ben Cheng38329f52009-07-07 14:19:20 -07001131 addrRetChain->generic.target = (LIR *) retChainingCell;
1132
1133 bypassRechaining->generic.target = (LIR *) addrRetChain;
1134 /*
1135 * r0 = calleeMethod,
1136 * r1 = &ChainingCell,
1137 * r4PC = callsiteDPC,
1138 */
1139 genDispatchToHandler(cUnit, TEMPLATE_INVOKE_METHOD_NO_OPT);
1140#if defined(INVOKE_STATS)
1141 gDvmJit.invokePredictedChain++;
1142#endif
1143 /* Handle exceptions using the interpreter */
1144 genTrap(cUnit, mir->offset, pcrLabel);
1145}
1146
1147/*
1148 * Up calling this function, "this" is stored in r0. The actual class will be
1149 * chased down off r0 and the predicted one will be retrieved through
1150 * predictedChainingCell then a comparison is performed to see whether the
1151 * previously established chaining is still valid.
1152 *
1153 * The return LIR is a branch based on the comparison result. The actual branch
1154 * target will be setup in the caller.
1155 */
Bill Buzbee89efc3d2009-07-28 11:22:22 -07001156static ArmLIR *genCheckPredictedChain(CompilationUnit *cUnit,
1157 ArmLIR *predChainingCell,
1158 ArmLIR *retChainingCell,
Ben Cheng38329f52009-07-07 14:19:20 -07001159 MIR *mir)
1160{
Bill Buzbee1465db52009-09-23 17:17:35 -07001161 /*
1162 * Note: all Dalvik register state should be flushed to
1163 * memory by the point, so register usage restrictions no
1164 * longer apply. All temp & preserved registers may be used.
1165 */
Bill Buzbeec6f10662010-02-09 11:16:15 -08001166 dvmCompilerLockAllTemps(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07001167
Ben Cheng38329f52009-07-07 14:19:20 -07001168 /* r3 now contains this->clazz */
Bill Buzbee270c1d62009-08-13 16:58:07 -07001169 loadWordDisp(cUnit, r0, offsetof(Object, clazz), r3);
Ben Cheng38329f52009-07-07 14:19:20 -07001170
1171 /*
1172 * r2 now contains predicted class. The starting offset of the
1173 * cached value is 4 bytes into the chaining cell.
1174 */
Bill Buzbee89efc3d2009-07-28 11:22:22 -07001175 ArmLIR *getPredictedClass =
Bill Buzbee270c1d62009-08-13 16:58:07 -07001176 loadWordDisp(cUnit, rpc, offsetof(PredictedChainingCell, clazz), r2);
Ben Cheng38329f52009-07-07 14:19:20 -07001177 getPredictedClass->generic.target = (LIR *) predChainingCell;
1178
1179 /*
1180 * r0 now contains predicted method. The starting offset of the
1181 * cached value is 8 bytes into the chaining cell.
1182 */
Bill Buzbee89efc3d2009-07-28 11:22:22 -07001183 ArmLIR *getPredictedMethod =
Bill Buzbee270c1d62009-08-13 16:58:07 -07001184 loadWordDisp(cUnit, rpc, offsetof(PredictedChainingCell, method), r0);
Ben Cheng38329f52009-07-07 14:19:20 -07001185 getPredictedMethod->generic.target = (LIR *) predChainingCell;
1186
1187 /* Load the stats counter to see if it is time to unchain and refresh */
Bill Buzbee89efc3d2009-07-28 11:22:22 -07001188 ArmLIR *getRechainingRequestCount =
Bill Buzbee270c1d62009-08-13 16:58:07 -07001189 loadWordDisp(cUnit, rpc, offsetof(PredictedChainingCell, counter), r7);
Ben Cheng38329f52009-07-07 14:19:20 -07001190 getRechainingRequestCount->generic.target =
1191 (LIR *) predChainingCell;
1192
1193 /* r4PC = dalvikCallsite */
1194 loadConstant(cUnit, r4PC,
1195 (int) (cUnit->method->insns + mir->offset));
1196
1197 /* r1 = &retChainingCell */
Bill Buzbee1465db52009-09-23 17:17:35 -07001198 ArmLIR *addrRetChain = opRegRegImm(cUnit, kOpAdd, r1, rpc, 0);
Ben Cheng38329f52009-07-07 14:19:20 -07001199 addrRetChain->generic.target = (LIR *) retChainingCell;
1200
1201 /* Check if r2 (predicted class) == r3 (actual class) */
Bill Buzbee1465db52009-09-23 17:17:35 -07001202 opRegReg(cUnit, kOpCmp, r2, r3);
Ben Cheng38329f52009-07-07 14:19:20 -07001203
Bill Buzbee1465db52009-09-23 17:17:35 -07001204 return opCondBranch(cUnit, kArmCondEq);
Ben Cheng38329f52009-07-07 14:19:20 -07001205}
1206
Ben Chengba4fc8b2009-06-01 13:00:29 -07001207/* Geneate a branch to go back to the interpreter */
1208static void genPuntToInterp(CompilationUnit *cUnit, unsigned int offset)
1209{
1210 /* r0 = dalvik pc */
Bill Buzbeec6f10662010-02-09 11:16:15 -08001211 dvmCompilerFlushAllRegs(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001212 loadConstant(cUnit, r0, (int) (cUnit->method->insns + offset));
Bill Buzbee270c1d62009-08-13 16:58:07 -07001213 loadWordDisp(cUnit, r0, offsetof(Object, clazz), r3);
1214 loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
1215 jitToInterpEntries.dvmJitToInterpPunt), r1);
Bill Buzbee1465db52009-09-23 17:17:35 -07001216 opReg(cUnit, kOpBlx, r1);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001217}
1218
1219/*
1220 * Attempt to single step one instruction using the interpreter and return
1221 * to the compiled code for the next Dalvik instruction
1222 */
1223static void genInterpSingleStep(CompilationUnit *cUnit, MIR *mir)
1224{
1225 int flags = dexGetInstrFlags(gDvm.instrFlags, mir->dalvikInsn.opCode);
1226 int flagsToCheck = kInstrCanBranch | kInstrCanSwitch | kInstrCanReturn |
1227 kInstrCanThrow;
Bill Buzbee1465db52009-09-23 17:17:35 -07001228
1229 //Ugly, but necessary. Flush all Dalvik regs so Interp can find them
Bill Buzbeec6f10662010-02-09 11:16:15 -08001230 dvmCompilerFlushAllRegs(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07001231
Ben Chengba4fc8b2009-06-01 13:00:29 -07001232 if ((mir->next == NULL) || (flags & flagsToCheck)) {
1233 genPuntToInterp(cUnit, mir->offset);
1234 return;
1235 }
1236 int entryAddr = offsetof(InterpState,
1237 jitToInterpEntries.dvmJitToInterpSingleStep);
Bill Buzbee270c1d62009-08-13 16:58:07 -07001238 loadWordDisp(cUnit, rGLUE, entryAddr, r2);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001239 /* r0 = dalvik pc */
1240 loadConstant(cUnit, r0, (int) (cUnit->method->insns + mir->offset));
1241 /* r1 = dalvik pc of following instruction */
1242 loadConstant(cUnit, r1, (int) (cUnit->method->insns + mir->next->offset));
Bill Buzbee1465db52009-09-23 17:17:35 -07001243 opReg(cUnit, kOpBlx, r2);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001244}
1245
Bill Buzbeec1d9ed42010-02-02 11:04:33 -08001246/*
1247 * To prevent a thread in a monitor wait from blocking the Jit from
1248 * resetting the code cache, heavyweight monitor lock will not
1249 * be allowed to return to an existing translation. Instead, we will
1250 * handle them by branching to a handler, which will in turn call the
1251 * runtime lock routine and then branch directly back to the
1252 * interpreter main loop. Given the high cost of the heavyweight
1253 * lock operation, this additional cost should be slight (especially when
1254 * considering that we expect the vast majority of lock operations to
1255 * use the fast-path thin lock bypass).
1256 */
Ben Cheng5d90c202009-11-22 23:31:11 -08001257static void genMonitorPortable(CompilationUnit *cUnit, MIR *mir)
Bill Buzbee270c1d62009-08-13 16:58:07 -07001258{
Bill Buzbeeefbd3c52009-11-04 22:18:40 -08001259 bool isEnter = (mir->dalvikInsn.opCode == OP_MONITOR_ENTER);
Bill Buzbee1465db52009-09-23 17:17:35 -07001260 genExportPC(cUnit, mir);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001261 dvmCompilerFlushAllRegs(cUnit); /* Send everything to home location */
1262 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001263 loadValueDirectFixed(cUnit, rlSrc, r1);
1264 loadWordDisp(cUnit, rGLUE, offsetof(InterpState, self), r0);
Bill Buzbeec1d9ed42010-02-02 11:04:33 -08001265 genNullCheck(cUnit, rlSrc.sRegLow, r1, mir->offset, NULL);
Bill Buzbeeefbd3c52009-11-04 22:18:40 -08001266 if (isEnter) {
Bill Buzbeec1d9ed42010-02-02 11:04:33 -08001267 /* Get dPC of next insn */
1268 loadConstant(cUnit, r4PC, (int)(cUnit->method->insns + mir->offset +
1269 dexGetInstrWidthAbs(gDvm.instrWidth, OP_MONITOR_ENTER)));
1270#if defined(WITH_DEADLOCK_PREDICTION)
1271 genDispatchToHandler(cUnit, TEMPLATE_MONITOR_ENTER_DEBUG);
1272#else
1273 genDispatchToHandler(cUnit, TEMPLATE_MONITOR_ENTER);
1274#endif
Bill Buzbee1465db52009-09-23 17:17:35 -07001275 } else {
1276 loadConstant(cUnit, r2, (int)dvmUnlockObject);
Bill Buzbeec1d9ed42010-02-02 11:04:33 -08001277 /* Do the call */
1278 opReg(cUnit, kOpBlx, r2);
Bill Buzbee6bbdd6b2010-02-16 14:40:01 -08001279 opRegImm(cUnit, kOpCmp, r0, 0); /* Did we throw? */
1280 ArmLIR *branchOver = opCondBranch(cUnit, kArmCondNe);
1281 loadConstant(cUnit, r0,
1282 (int) (cUnit->method->insns + mir->offset +
1283 dexGetInstrWidthAbs(gDvm.instrWidth, OP_MONITOR_EXIT)));
1284 genDispatchToHandler(cUnit, TEMPLATE_THROW_EXCEPTION_COMMON);
1285 ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel);
1286 target->defMask = ENCODE_ALL;
1287 branchOver->generic.target = (LIR *) target;
Bill Buzbeec6f10662010-02-09 11:16:15 -08001288 dvmCompilerColbberCallRegs(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07001289 }
Bill Buzbee270c1d62009-08-13 16:58:07 -07001290}
1291
Ben Chengba4fc8b2009-06-01 13:00:29 -07001292/*
1293 * The following are the first-level codegen routines that analyze the format
1294 * of each bytecode then either dispatch special purpose codegen routines
1295 * or produce corresponding Thumb instructions directly.
1296 */
1297
1298static bool handleFmt10t_Fmt20t_Fmt30t(CompilationUnit *cUnit, MIR *mir,
Bill Buzbee89efc3d2009-07-28 11:22:22 -07001299 BasicBlock *bb, ArmLIR *labelList)
Ben Chengba4fc8b2009-06-01 13:00:29 -07001300{
1301 /* For OP_GOTO, OP_GOTO_16, and OP_GOTO_32 */
1302 genUnconditionalBranch(cUnit, &labelList[bb->taken->id]);
1303 return false;
1304}
1305
1306static bool handleFmt10x(CompilationUnit *cUnit, MIR *mir)
1307{
1308 OpCode dalvikOpCode = mir->dalvikInsn.opCode;
1309 if (((dalvikOpCode >= OP_UNUSED_3E) && (dalvikOpCode <= OP_UNUSED_43)) ||
Andy McFadden96516932009-10-28 17:39:02 -07001310 ((dalvikOpCode >= OP_UNUSED_E3) && (dalvikOpCode <= OP_UNUSED_EB))) {
Ben Chengba4fc8b2009-06-01 13:00:29 -07001311 LOGE("Codegen: got unused opcode 0x%x\n",dalvikOpCode);
1312 return true;
1313 }
1314 switch (dalvikOpCode) {
1315 case OP_RETURN_VOID:
1316 genReturnCommon(cUnit,mir);
1317 break;
1318 case OP_UNUSED_73:
1319 case OP_UNUSED_79:
1320 case OP_UNUSED_7A:
1321 LOGE("Codegen: got unused opcode 0x%x\n",dalvikOpCode);
1322 return true;
1323 case OP_NOP:
1324 break;
1325 default:
1326 return true;
1327 }
1328 return false;
1329}
1330
1331static bool handleFmt11n_Fmt31i(CompilationUnit *cUnit, MIR *mir)
1332{
Bill Buzbee1465db52009-09-23 17:17:35 -07001333 RegLocation rlDest;
1334 RegLocation rlResult;
1335 if (mir->ssaRep->numDefs == 2) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001336 rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -07001337 } else {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001338 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001339 }
Ben Chenge9695e52009-06-16 16:11:47 -07001340
Ben Chengba4fc8b2009-06-01 13:00:29 -07001341 switch (mir->dalvikInsn.opCode) {
1342 case OP_CONST:
Ben Chenge9695e52009-06-16 16:11:47 -07001343 case OP_CONST_4: {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001344 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001345 loadConstantValue(cUnit, rlResult.lowReg, mir->dalvikInsn.vB);
1346 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001347 break;
Ben Chenge9695e52009-06-16 16:11:47 -07001348 }
1349 case OP_CONST_WIDE_32: {
Bill Buzbee1465db52009-09-23 17:17:35 -07001350 //TUNING: single routine to load constant pair for support doubles
Bill Buzbee964a7b02010-01-28 12:54:19 -08001351 //TUNING: load 0/-1 separately to avoid load dependency
Bill Buzbeec6f10662010-02-09 11:16:15 -08001352 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001353 loadConstantValue(cUnit, rlResult.lowReg, mir->dalvikInsn.vB);
1354 opRegRegImm(cUnit, kOpAsr, rlResult.highReg,
1355 rlResult.lowReg, 31);
1356 storeValueWide(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001357 break;
Ben Chenge9695e52009-06-16 16:11:47 -07001358 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07001359 default:
1360 return true;
1361 }
1362 return false;
1363}
1364
1365static bool handleFmt21h(CompilationUnit *cUnit, MIR *mir)
1366{
Bill Buzbee1465db52009-09-23 17:17:35 -07001367 RegLocation rlDest;
1368 RegLocation rlResult;
1369 if (mir->ssaRep->numDefs == 2) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001370 rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -07001371 } else {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001372 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001373 }
Bill Buzbeec6f10662010-02-09 11:16:15 -08001374 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
Ben Chenge9695e52009-06-16 16:11:47 -07001375
Ben Chengba4fc8b2009-06-01 13:00:29 -07001376 switch (mir->dalvikInsn.opCode) {
Ben Chenge9695e52009-06-16 16:11:47 -07001377 case OP_CONST_HIGH16: {
Bill Buzbee1465db52009-09-23 17:17:35 -07001378 loadConstantValue(cUnit, rlResult.lowReg, mir->dalvikInsn.vB << 16);
1379 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001380 break;
Ben Chenge9695e52009-06-16 16:11:47 -07001381 }
1382 case OP_CONST_WIDE_HIGH16: {
Bill Buzbee1465db52009-09-23 17:17:35 -07001383 loadConstantValueWide(cUnit, rlResult.lowReg, rlResult.highReg,
1384 0, mir->dalvikInsn.vB << 16);
1385 storeValueWide(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001386 break;
Ben Chenge9695e52009-06-16 16:11:47 -07001387 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07001388 default:
1389 return true;
1390 }
1391 return false;
1392}
1393
1394static bool handleFmt20bc(CompilationUnit *cUnit, MIR *mir)
1395{
1396 /* For OP_THROW_VERIFICATION_ERROR */
1397 genInterpSingleStep(cUnit, mir);
1398 return false;
1399}
1400
1401static bool handleFmt21c_Fmt31c(CompilationUnit *cUnit, MIR *mir)
1402{
Bill Buzbee1465db52009-09-23 17:17:35 -07001403 RegLocation rlResult;
1404 RegLocation rlDest;
1405 RegLocation rlSrc;
Ben Chenge9695e52009-06-16 16:11:47 -07001406
Ben Chengba4fc8b2009-06-01 13:00:29 -07001407 switch (mir->dalvikInsn.opCode) {
Ben Chengba4fc8b2009-06-01 13:00:29 -07001408 case OP_CONST_STRING_JUMBO:
1409 case OP_CONST_STRING: {
1410 void *strPtr = (void*)
1411 (cUnit->method->clazz->pDvmDex->pResStrings[mir->dalvikInsn.vB]);
1412 assert(strPtr != NULL);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001413 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
1414 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001415 loadConstantValue(cUnit, rlResult.lowReg, (int) strPtr );
1416 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001417 break;
1418 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07001419 case OP_CONST_CLASS: {
1420 void *classPtr = (void*)
1421 (cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vB]);
1422 assert(classPtr != NULL);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001423 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
1424 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001425 loadConstantValue(cUnit, rlResult.lowReg, (int) classPtr );
1426 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001427 break;
1428 }
1429 case OP_SGET_OBJECT:
1430 case OP_SGET_BOOLEAN:
1431 case OP_SGET_CHAR:
1432 case OP_SGET_BYTE:
1433 case OP_SGET_SHORT:
1434 case OP_SGET: {
Bill Buzbee50a6bf22009-07-08 13:08:04 -07001435 int valOffset = offsetof(StaticField, value);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001436 int tReg = dvmCompilerAllocTemp(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001437 void *fieldPtr = (void*)
1438 (cUnit->method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vB]);
1439 assert(fieldPtr != NULL);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001440 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
1441 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001442 loadConstant(cUnit, tReg, (int) fieldPtr + valOffset);
jeffhao9e45c0b2010-02-03 10:24:05 -08001443#if defined(WITH_SELF_VERIFICATION)
1444 cUnit->heapMemOp = true;
1445#endif
Bill Buzbee1465db52009-09-23 17:17:35 -07001446 loadWordDisp(cUnit, tReg, 0, rlResult.lowReg);
jeffhao9e45c0b2010-02-03 10:24:05 -08001447#if defined(WITH_SELF_VERIFICATION)
1448 cUnit->heapMemOp = false;
Jeff Hao97319a82009-08-12 16:57:15 -07001449#endif
Bill Buzbee1465db52009-09-23 17:17:35 -07001450 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001451 break;
1452 }
1453 case OP_SGET_WIDE: {
Bill Buzbee50a6bf22009-07-08 13:08:04 -07001454 int valOffset = offsetof(StaticField, value);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001455 void *fieldPtr = (void*)
1456 (cUnit->method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vB]);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001457 int tReg = dvmCompilerAllocTemp(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001458 assert(fieldPtr != NULL);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001459 rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
1460 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001461 loadConstant(cUnit, tReg, (int) fieldPtr + valOffset);
jeffhao9e45c0b2010-02-03 10:24:05 -08001462#if defined(WITH_SELF_VERIFICATION)
1463 cUnit->heapMemOp = true;
1464#endif
Bill Buzbee1465db52009-09-23 17:17:35 -07001465 loadPair(cUnit, tReg, rlResult.lowReg, rlResult.highReg);
jeffhao9e45c0b2010-02-03 10:24:05 -08001466#if defined(WITH_SELF_VERIFICATION)
1467 cUnit->heapMemOp = false;
Jeff Hao97319a82009-08-12 16:57:15 -07001468#endif
Bill Buzbee1465db52009-09-23 17:17:35 -07001469 storeValueWide(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001470 break;
1471 }
1472 case OP_SPUT_OBJECT:
1473 case OP_SPUT_BOOLEAN:
1474 case OP_SPUT_CHAR:
1475 case OP_SPUT_BYTE:
1476 case OP_SPUT_SHORT:
1477 case OP_SPUT: {
Bill Buzbee50a6bf22009-07-08 13:08:04 -07001478 int valOffset = offsetof(StaticField, value);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001479 int tReg = dvmCompilerAllocTemp(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001480 void *fieldPtr = (void*)
1481 (cUnit->method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vB]);
Ben Chenge9695e52009-06-16 16:11:47 -07001482
Ben Chengba4fc8b2009-06-01 13:00:29 -07001483 assert(fieldPtr != NULL);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001484 rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001485 rlSrc = loadValue(cUnit, rlSrc, kAnyReg);
1486 loadConstant(cUnit, tReg, (int) fieldPtr + valOffset);
jeffhao9e45c0b2010-02-03 10:24:05 -08001487#if defined(WITH_SELF_VERIFICATION)
1488 cUnit->heapMemOp = true;
1489#endif
Bill Buzbee1465db52009-09-23 17:17:35 -07001490 storeWordDisp(cUnit, tReg, 0 ,rlSrc.lowReg);
jeffhao9e45c0b2010-02-03 10:24:05 -08001491#if defined(WITH_SELF_VERIFICATION)
1492 cUnit->heapMemOp = false;
Jeff Hao97319a82009-08-12 16:57:15 -07001493#endif
Ben Chengba4fc8b2009-06-01 13:00:29 -07001494 break;
1495 }
1496 case OP_SPUT_WIDE: {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001497 int tReg = dvmCompilerAllocTemp(cUnit);
Bill Buzbee50a6bf22009-07-08 13:08:04 -07001498 int valOffset = offsetof(StaticField, value);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001499 void *fieldPtr = (void*)
1500 (cUnit->method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vB]);
Ben Chenge9695e52009-06-16 16:11:47 -07001501
Ben Chengba4fc8b2009-06-01 13:00:29 -07001502 assert(fieldPtr != NULL);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001503 rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -07001504 rlSrc = loadValueWide(cUnit, rlSrc, kAnyReg);
1505 loadConstant(cUnit, tReg, (int) fieldPtr + valOffset);
jeffhao9e45c0b2010-02-03 10:24:05 -08001506#if defined(WITH_SELF_VERIFICATION)
1507 cUnit->heapMemOp = true;
1508#endif
Bill Buzbee1465db52009-09-23 17:17:35 -07001509 storePair(cUnit, tReg, rlSrc.lowReg, rlSrc.highReg);
jeffhao9e45c0b2010-02-03 10:24:05 -08001510#if defined(WITH_SELF_VERIFICATION)
1511 cUnit->heapMemOp = false;
Jeff Hao97319a82009-08-12 16:57:15 -07001512#endif
Ben Chengba4fc8b2009-06-01 13:00:29 -07001513 break;
1514 }
1515 case OP_NEW_INSTANCE: {
Ben Chenge9695e52009-06-16 16:11:47 -07001516 /*
1517 * Obey the calling convention and don't mess with the register
1518 * usage.
1519 */
Ben Chengba4fc8b2009-06-01 13:00:29 -07001520 ClassObject *classPtr = (void*)
1521 (cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vB]);
1522 assert(classPtr != NULL);
1523 assert(classPtr->status & CLASS_INITIALIZED);
Ben Cheng79d173c2009-09-29 16:12:51 -07001524 /*
1525 * If it is going to throw, it should not make to the trace to begin
Bill Buzbee1465db52009-09-23 17:17:35 -07001526 * with. However, Alloc might throw, so we need to genExportPC()
Ben Cheng79d173c2009-09-29 16:12:51 -07001527 */
1528 assert((classPtr->accessFlags & (ACC_INTERFACE|ACC_ABSTRACT)) == 0);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001529 dvmCompilerFlushAllRegs(cUnit); /* Everything to home location */
Bill Buzbee1465db52009-09-23 17:17:35 -07001530 genExportPC(cUnit, mir);
1531 loadConstant(cUnit, r2, (int)dvmAllocObject);
Ben Chenge9695e52009-06-16 16:11:47 -07001532 loadConstant(cUnit, r0, (int) classPtr);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001533 loadConstant(cUnit, r1, ALLOC_DONT_TRACK);
Bill Buzbee1465db52009-09-23 17:17:35 -07001534 opReg(cUnit, kOpBlx, r2);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001535 dvmCompilerColbberCallRegs(cUnit);
Ben Cheng4f489172009-09-27 17:08:35 -07001536 /* generate a branch over if allocation is successful */
Bill Buzbee1465db52009-09-23 17:17:35 -07001537 opRegImm(cUnit, kOpCmp, r0, 0); /* NULL? */
1538 ArmLIR *branchOver = opCondBranch(cUnit, kArmCondNe);
Ben Cheng4f489172009-09-27 17:08:35 -07001539 /*
1540 * OOM exception needs to be thrown here and cannot re-execute
1541 */
1542 loadConstant(cUnit, r0,
1543 (int) (cUnit->method->insns + mir->offset));
1544 genDispatchToHandler(cUnit, TEMPLATE_THROW_EXCEPTION_COMMON);
1545 /* noreturn */
1546
Bill Buzbee1465db52009-09-23 17:17:35 -07001547 ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel);
Ben Cheng4f489172009-09-27 17:08:35 -07001548 target->defMask = ENCODE_ALL;
1549 branchOver->generic.target = (LIR *) target;
Bill Buzbeec6f10662010-02-09 11:16:15 -08001550 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
1551 rlResult = dvmCompilerGetReturn(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07001552 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001553 break;
1554 }
1555 case OP_CHECK_CAST: {
Ben Chenge9695e52009-06-16 16:11:47 -07001556 /*
1557 * Obey the calling convention and don't mess with the register
1558 * usage.
1559 */
Ben Chengba4fc8b2009-06-01 13:00:29 -07001560 ClassObject *classPtr =
1561 (cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vB]);
Bill Buzbee4df41a52009-11-12 17:07:16 -08001562 /*
1563 * Note: It is possible that classPtr is NULL at this point,
1564 * even though this instruction has been successfully interpreted.
1565 * If the previous interpretation had a null source, the
1566 * interpreter would not have bothered to resolve the clazz.
1567 * Bail out to the interpreter in this case, and log it
1568 * so that we can tell if it happens frequently.
1569 */
1570 if (classPtr == NULL) {
1571 LOGD("null clazz in OP_CHECK_CAST, single-stepping");
1572 genInterpSingleStep(cUnit, mir);
1573 return false;
1574 }
Bill Buzbeec6f10662010-02-09 11:16:15 -08001575 dvmCompilerFlushAllRegs(cUnit); /* Everything to home location */
Ben Chengba4fc8b2009-06-01 13:00:29 -07001576 loadConstant(cUnit, r1, (int) classPtr );
Bill Buzbeec6f10662010-02-09 11:16:15 -08001577 rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001578 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
1579 opRegImm(cUnit, kOpCmp, rlSrc.lowReg, 0); /* Null? */
1580 ArmLIR *branch1 = opCondBranch(cUnit, kArmCondEq);
1581 /*
1582 * rlSrc.lowReg now contains object->clazz. Note that
1583 * it could have been allocated r0, but we're okay so long
1584 * as we don't do anything desctructive until r0 is loaded
1585 * with clazz.
1586 */
Ben Chengba4fc8b2009-06-01 13:00:29 -07001587 /* r0 now contains object->clazz */
Bill Buzbee1465db52009-09-23 17:17:35 -07001588 loadWordDisp(cUnit, rlSrc.lowReg, offsetof(Object, clazz), r0);
1589 loadConstant(cUnit, r2, (int)dvmInstanceofNonTrivial);
1590 opRegReg(cUnit, kOpCmp, r0, r1);
1591 ArmLIR *branch2 = opCondBranch(cUnit, kArmCondEq);
1592 opReg(cUnit, kOpBlx, r2);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001593 dvmCompilerColbberCallRegs(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07001594 /*
1595 * If null, check cast failed - punt to the interpreter. Because
1596 * interpreter will be the one throwing, we don't need to
1597 * genExportPC() here.
1598 */
Bill Buzbee270c1d62009-08-13 16:58:07 -07001599 genZeroCheck(cUnit, r0, mir->offset, NULL);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001600 /* check cast passed - branch target here */
Bill Buzbee1465db52009-09-23 17:17:35 -07001601 ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel);
Ben Chengd7d426a2009-09-22 11:23:36 -07001602 target->defMask = ENCODE_ALL;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001603 branch1->generic.target = (LIR *)target;
1604 branch2->generic.target = (LIR *)target;
1605 break;
1606 }
1607 default:
1608 return true;
1609 }
1610 return false;
1611}
1612
1613static bool handleFmt11x(CompilationUnit *cUnit, MIR *mir)
1614{
1615 OpCode dalvikOpCode = mir->dalvikInsn.opCode;
Bill Buzbee1465db52009-09-23 17:17:35 -07001616 RegLocation rlResult;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001617 switch (dalvikOpCode) {
1618 case OP_MOVE_EXCEPTION: {
1619 int offset = offsetof(InterpState, self);
1620 int exOffset = offsetof(Thread, exception);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001621 int selfReg = dvmCompilerAllocTemp(cUnit);
1622 int resetReg = dvmCompilerAllocTemp(cUnit);
1623 RegLocation rlDest = dvmCompilerGetDest(cUnit, mir, 0);
1624 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001625 loadWordDisp(cUnit, rGLUE, offset, selfReg);
Bill Buzbeef9f33282009-11-22 12:45:30 -08001626 loadConstant(cUnit, resetReg, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001627 loadWordDisp(cUnit, selfReg, exOffset, rlResult.lowReg);
Bill Buzbeef9f33282009-11-22 12:45:30 -08001628 storeWordDisp(cUnit, selfReg, exOffset, resetReg);
Bill Buzbee1465db52009-09-23 17:17:35 -07001629 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001630 break;
1631 }
1632 case OP_MOVE_RESULT:
1633 case OP_MOVE_RESULT_OBJECT: {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001634 RegLocation rlDest = dvmCompilerGetDest(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001635 RegLocation rlSrc = LOC_DALVIK_RETURN_VAL;
1636 rlSrc.fp = rlDest.fp;
1637 storeValue(cUnit, rlDest, rlSrc);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001638 break;
1639 }
1640 case OP_MOVE_RESULT_WIDE: {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001641 RegLocation rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -07001642 RegLocation rlSrc = LOC_DALVIK_RETURN_VAL_WIDE;
1643 rlSrc.fp = rlDest.fp;
1644 storeValueWide(cUnit, rlDest, rlSrc);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001645 break;
1646 }
1647 case OP_RETURN_WIDE: {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001648 RegLocation rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -07001649 RegLocation rlDest = LOC_DALVIK_RETURN_VAL_WIDE;
1650 rlDest.fp = rlSrc.fp;
1651 storeValueWide(cUnit, rlDest, rlSrc);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001652 genReturnCommon(cUnit,mir);
1653 break;
1654 }
1655 case OP_RETURN:
1656 case OP_RETURN_OBJECT: {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001657 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001658 RegLocation rlDest = LOC_DALVIK_RETURN_VAL;
1659 rlDest.fp = rlSrc.fp;
1660 storeValue(cUnit, rlDest, rlSrc);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001661 genReturnCommon(cUnit,mir);
1662 break;
1663 }
Bill Buzbee1465db52009-09-23 17:17:35 -07001664 case OP_MONITOR_EXIT:
Ben Chengba4fc8b2009-06-01 13:00:29 -07001665 case OP_MONITOR_ENTER:
Bill Buzbeed0937ef2009-12-22 16:15:39 -08001666#if defined(WITH_DEADLOCK_PREDICTION) || defined(WITH_MONITOR_TRACKING)
Ben Cheng5d90c202009-11-22 23:31:11 -08001667 genMonitorPortable(cUnit, mir);
Bill Buzbee1465db52009-09-23 17:17:35 -07001668#else
Ben Cheng5d90c202009-11-22 23:31:11 -08001669 genMonitor(cUnit, mir);
Bill Buzbee1465db52009-09-23 17:17:35 -07001670#endif
Ben Chengba4fc8b2009-06-01 13:00:29 -07001671 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001672 case OP_THROW: {
1673 genInterpSingleStep(cUnit, mir);
1674 break;
1675 }
1676 default:
1677 return true;
1678 }
1679 return false;
1680}
1681
Bill Buzbeed45ba372009-06-15 17:00:57 -07001682static bool handleFmt12x(CompilationUnit *cUnit, MIR *mir)
1683{
1684 OpCode opCode = mir->dalvikInsn.opCode;
Bill Buzbee1465db52009-09-23 17:17:35 -07001685 RegLocation rlDest;
1686 RegLocation rlSrc;
1687 RegLocation rlResult;
Bill Buzbeed45ba372009-06-15 17:00:57 -07001688
Ben Chengba4fc8b2009-06-01 13:00:29 -07001689 if ( (opCode >= OP_ADD_INT_2ADDR) && (opCode <= OP_REM_DOUBLE_2ADDR)) {
Ben Cheng5d90c202009-11-22 23:31:11 -08001690 return genArithOp( cUnit, mir );
Ben Chengba4fc8b2009-06-01 13:00:29 -07001691 }
1692
Bill Buzbee1465db52009-09-23 17:17:35 -07001693 if (mir->ssaRep->numUses == 2)
Bill Buzbeec6f10662010-02-09 11:16:15 -08001694 rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -07001695 else
Bill Buzbeec6f10662010-02-09 11:16:15 -08001696 rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001697 if (mir->ssaRep->numDefs == 2)
Bill Buzbeec6f10662010-02-09 11:16:15 -08001698 rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -07001699 else
Bill Buzbeec6f10662010-02-09 11:16:15 -08001700 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
Ben Chenge9695e52009-06-16 16:11:47 -07001701
Ben Chengba4fc8b2009-06-01 13:00:29 -07001702 switch (opCode) {
Bill Buzbee1465db52009-09-23 17:17:35 -07001703 case OP_DOUBLE_TO_INT:
Ben Chengba4fc8b2009-06-01 13:00:29 -07001704 case OP_INT_TO_FLOAT:
Ben Chengba4fc8b2009-06-01 13:00:29 -07001705 case OP_FLOAT_TO_INT:
Ben Chengba4fc8b2009-06-01 13:00:29 -07001706 case OP_DOUBLE_TO_FLOAT:
Ben Chengba4fc8b2009-06-01 13:00:29 -07001707 case OP_FLOAT_TO_DOUBLE:
Ben Chengba4fc8b2009-06-01 13:00:29 -07001708 case OP_INT_TO_DOUBLE:
Ben Chengba4fc8b2009-06-01 13:00:29 -07001709 case OP_FLOAT_TO_LONG:
Ben Chengba4fc8b2009-06-01 13:00:29 -07001710 case OP_LONG_TO_FLOAT:
Ben Chengba4fc8b2009-06-01 13:00:29 -07001711 case OP_DOUBLE_TO_LONG:
Ben Chengba4fc8b2009-06-01 13:00:29 -07001712 case OP_LONG_TO_DOUBLE:
Ben Cheng5d90c202009-11-22 23:31:11 -08001713 return genConversion(cUnit, mir);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001714 case OP_NEG_INT:
1715 case OP_NOT_INT:
Ben Cheng5d90c202009-11-22 23:31:11 -08001716 return genArithOpInt(cUnit, mir, rlDest, rlSrc, rlSrc);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001717 case OP_NEG_LONG:
1718 case OP_NOT_LONG:
Ben Cheng5d90c202009-11-22 23:31:11 -08001719 return genArithOpLong(cUnit, mir, rlDest, rlSrc, rlSrc);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001720 case OP_NEG_FLOAT:
Ben Cheng5d90c202009-11-22 23:31:11 -08001721 return genArithOpFloat(cUnit, mir, rlDest, rlSrc, rlSrc);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001722 case OP_NEG_DOUBLE:
Ben Cheng5d90c202009-11-22 23:31:11 -08001723 return genArithOpDouble(cUnit, mir, rlDest, rlSrc, rlSrc);
Bill Buzbee1465db52009-09-23 17:17:35 -07001724 case OP_MOVE_WIDE:
1725 storeValueWide(cUnit, rlDest, rlSrc);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001726 break;
Bill Buzbee1465db52009-09-23 17:17:35 -07001727 case OP_INT_TO_LONG:
Bill Buzbeec6f10662010-02-09 11:16:15 -08001728 rlSrc = dvmCompilerUpdateLoc(cUnit, rlSrc);
1729 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee964a7b02010-01-28 12:54:19 -08001730 //TUNING: shouldn't loadValueDirect already check for phys reg?
Bill Buzbee1465db52009-09-23 17:17:35 -07001731 if (rlSrc.location == kLocPhysReg) {
1732 genRegCopy(cUnit, rlResult.lowReg, rlSrc.lowReg);
1733 } else {
1734 loadValueDirect(cUnit, rlSrc, rlResult.lowReg);
1735 }
1736 opRegRegImm(cUnit, kOpAsr, rlResult.highReg,
1737 rlResult.lowReg, 31);
1738 storeValueWide(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001739 break;
Bill Buzbee1465db52009-09-23 17:17:35 -07001740 case OP_LONG_TO_INT:
Bill Buzbeec6f10662010-02-09 11:16:15 -08001741 rlSrc = dvmCompilerUpdateLocWide(cUnit, rlSrc);
1742 rlSrc = dvmCompilerWideToNarrow(cUnit, rlSrc);
Bill Buzbee1465db52009-09-23 17:17:35 -07001743 // Intentional fallthrough
Ben Chengba4fc8b2009-06-01 13:00:29 -07001744 case OP_MOVE:
1745 case OP_MOVE_OBJECT:
Bill Buzbee1465db52009-09-23 17:17:35 -07001746 storeValue(cUnit, rlDest, rlSrc);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001747 break;
1748 case OP_INT_TO_BYTE:
Bill Buzbee1465db52009-09-23 17:17:35 -07001749 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001750 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001751 opRegReg(cUnit, kOp2Byte, rlResult.lowReg, rlSrc.lowReg);
1752 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001753 break;
1754 case OP_INT_TO_SHORT:
Bill Buzbee1465db52009-09-23 17:17:35 -07001755 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001756 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001757 opRegReg(cUnit, kOp2Short, rlResult.lowReg, rlSrc.lowReg);
1758 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001759 break;
1760 case OP_INT_TO_CHAR:
Bill Buzbee1465db52009-09-23 17:17:35 -07001761 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001762 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001763 opRegReg(cUnit, kOp2Char, rlResult.lowReg, rlSrc.lowReg);
1764 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001765 break;
1766 case OP_ARRAY_LENGTH: {
1767 int lenOffset = offsetof(ArrayObject, length);
Bill Buzbee1465db52009-09-23 17:17:35 -07001768 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
1769 genNullCheck(cUnit, rlSrc.sRegLow, rlSrc.lowReg,
1770 mir->offset, NULL);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001771 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001772 loadWordDisp(cUnit, rlSrc.lowReg, lenOffset,
1773 rlResult.lowReg);
1774 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001775 break;
1776 }
1777 default:
1778 return true;
1779 }
1780 return false;
1781}
1782
1783static bool handleFmt21s(CompilationUnit *cUnit, MIR *mir)
1784{
1785 OpCode dalvikOpCode = mir->dalvikInsn.opCode;
Bill Buzbee1465db52009-09-23 17:17:35 -07001786 RegLocation rlDest;
1787 RegLocation rlResult;
1788 int BBBB = mir->dalvikInsn.vB;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001789 if (dalvikOpCode == OP_CONST_WIDE_16) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001790 rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
1791 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001792 loadConstantValue(cUnit, rlResult.lowReg, BBBB);
Bill Buzbee964a7b02010-01-28 12:54:19 -08001793 //TUNING: do high separately to avoid load dependency
Bill Buzbee1465db52009-09-23 17:17:35 -07001794 opRegRegImm(cUnit, kOpAsr, rlResult.highReg, rlResult.lowReg, 31);
1795 storeValueWide(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001796 } else if (dalvikOpCode == OP_CONST_16) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001797 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
1798 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001799 loadConstantValue(cUnit, rlResult.lowReg, BBBB);
1800 storeValue(cUnit, rlDest, rlResult);
1801 } else
Ben Chengba4fc8b2009-06-01 13:00:29 -07001802 return true;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001803 return false;
1804}
1805
1806/* Compare agaist zero */
1807static bool handleFmt21t(CompilationUnit *cUnit, MIR *mir, BasicBlock *bb,
Bill Buzbee89efc3d2009-07-28 11:22:22 -07001808 ArmLIR *labelList)
Ben Chengba4fc8b2009-06-01 13:00:29 -07001809{
1810 OpCode dalvikOpCode = mir->dalvikInsn.opCode;
Bill Buzbee89efc3d2009-07-28 11:22:22 -07001811 ArmConditionCode cond;
Bill Buzbeec6f10662010-02-09 11:16:15 -08001812 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001813 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
1814 opRegImm(cUnit, kOpCmp, rlSrc.lowReg, 0);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001815
Bill Buzbee270c1d62009-08-13 16:58:07 -07001816//TUNING: break this out to allow use of Thumb2 CB[N]Z
Ben Chengba4fc8b2009-06-01 13:00:29 -07001817 switch (dalvikOpCode) {
1818 case OP_IF_EQZ:
Bill Buzbee1465db52009-09-23 17:17:35 -07001819 cond = kArmCondEq;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001820 break;
1821 case OP_IF_NEZ:
Bill Buzbee1465db52009-09-23 17:17:35 -07001822 cond = kArmCondNe;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001823 break;
1824 case OP_IF_LTZ:
Bill Buzbee1465db52009-09-23 17:17:35 -07001825 cond = kArmCondLt;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001826 break;
1827 case OP_IF_GEZ:
Bill Buzbee1465db52009-09-23 17:17:35 -07001828 cond = kArmCondGe;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001829 break;
1830 case OP_IF_GTZ:
Bill Buzbee1465db52009-09-23 17:17:35 -07001831 cond = kArmCondGt;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001832 break;
1833 case OP_IF_LEZ:
Bill Buzbee1465db52009-09-23 17:17:35 -07001834 cond = kArmCondLe;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001835 break;
1836 default:
1837 cond = 0;
1838 LOGE("Unexpected opcode (%d) for Fmt21t\n", dalvikOpCode);
1839 dvmAbort();
1840 }
1841 genConditionalBranch(cUnit, cond, &labelList[bb->taken->id]);
1842 /* This mostly likely will be optimized away in a later phase */
1843 genUnconditionalBranch(cUnit, &labelList[bb->fallThrough->id]);
1844 return false;
1845}
1846
Bill Buzbee78cb0e22010-02-11 14:04:53 -08001847/* Positive power of 2? Return shiftCount if so, -1 if not */
1848static int mulToShift(int val) {
1849 int shiftCount;
1850 if (val > 0 && ((val & (val - 1)) == 0)) {
1851 shiftCount = 0;
1852 val = ~val & (val - 1);
1853 while (val) {
1854 shiftCount++;
1855 val >>= 1;
1856 }
1857 } else {
1858 shiftCount = -1;
1859 }
1860 return shiftCount;
1861}
1862
Ben Chengba4fc8b2009-06-01 13:00:29 -07001863static bool handleFmt22b_Fmt22s(CompilationUnit *cUnit, MIR *mir)
1864{
1865 OpCode dalvikOpCode = mir->dalvikInsn.opCode;
Bill Buzbeec6f10662010-02-09 11:16:15 -08001866 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
1867 RegLocation rlDest = dvmCompilerGetDest(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001868 RegLocation rlResult;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001869 int lit = mir->dalvikInsn.vC;
Ben Cheng4f489172009-09-27 17:08:35 -07001870 OpKind op = 0; /* Make gcc happy */
Bill Buzbee1465db52009-09-23 17:17:35 -07001871 int shiftOp = false;
1872 bool isDiv = false;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001873
Ben Chengba4fc8b2009-06-01 13:00:29 -07001874 int __aeabi_idivmod(int op1, int op2);
1875 int __aeabi_idiv(int op1, int op2);
1876
1877 switch (dalvikOpCode) {
Bill Buzbee1465db52009-09-23 17:17:35 -07001878 case OP_RSUB_INT_LIT8:
1879 case OP_RSUB_INT: {
1880 int tReg;
1881 //TUNING: add support for use of Arm rsub op
1882 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001883 tReg = dvmCompilerAllocTemp(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07001884 loadConstant(cUnit, tReg, lit);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001885 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001886 opRegRegReg(cUnit, kOpSub, rlResult.lowReg,
1887 tReg, rlSrc.lowReg);
1888 storeValue(cUnit, rlDest, rlResult);
1889 return false;
1890 break;
1891 }
1892
Ben Chengba4fc8b2009-06-01 13:00:29 -07001893 case OP_ADD_INT_LIT8:
1894 case OP_ADD_INT_LIT16:
Bill Buzbee1465db52009-09-23 17:17:35 -07001895 op = kOpAdd;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001896 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001897 case OP_MUL_INT_LIT8:
Bill Buzbee78cb0e22010-02-11 14:04:53 -08001898 case OP_MUL_INT_LIT16: {
1899 // TUNING: General shift & add for small constants
1900 int shiftCount = mulToShift(lit);
1901 if (shiftCount >= 0) {
1902 op = kOpLsl;
1903 lit = shiftCount;
1904 shiftOp = true;
1905 } else {
1906 op = kOpMul;
1907 }
Bill Buzbee1465db52009-09-23 17:17:35 -07001908 break;
Bill Buzbee78cb0e22010-02-11 14:04:53 -08001909 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07001910 case OP_AND_INT_LIT8:
1911 case OP_AND_INT_LIT16:
Bill Buzbee1465db52009-09-23 17:17:35 -07001912 op = kOpAnd;
1913 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001914 case OP_OR_INT_LIT8:
1915 case OP_OR_INT_LIT16:
Bill Buzbee1465db52009-09-23 17:17:35 -07001916 op = kOpOr;
1917 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001918 case OP_XOR_INT_LIT8:
1919 case OP_XOR_INT_LIT16:
Bill Buzbee1465db52009-09-23 17:17:35 -07001920 op = kOpXor;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001921 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001922 case OP_SHL_INT_LIT8:
Bill Buzbee0e605272009-12-01 14:28:05 -08001923 lit &= 31;
Bill Buzbee1465db52009-09-23 17:17:35 -07001924 shiftOp = true;
1925 op = kOpLsl;
1926 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001927 case OP_SHR_INT_LIT8:
Bill Buzbee0e605272009-12-01 14:28:05 -08001928 lit &= 31;
Bill Buzbee1465db52009-09-23 17:17:35 -07001929 shiftOp = true;
1930 op = kOpAsr;
1931 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001932 case OP_USHR_INT_LIT8:
Bill Buzbee0e605272009-12-01 14:28:05 -08001933 lit &= 31;
Bill Buzbee1465db52009-09-23 17:17:35 -07001934 shiftOp = true;
1935 op = kOpLsr;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001936 break;
1937
1938 case OP_DIV_INT_LIT8:
1939 case OP_DIV_INT_LIT16:
Ben Chengba4fc8b2009-06-01 13:00:29 -07001940 case OP_REM_INT_LIT8:
1941 case OP_REM_INT_LIT16:
1942 if (lit == 0) {
1943 /* Let the interpreter deal with div by 0 */
1944 genInterpSingleStep(cUnit, mir);
1945 return false;
1946 }
Bill Buzbeec6f10662010-02-09 11:16:15 -08001947 dvmCompilerFlushAllRegs(cUnit); /* Everything to home location */
Bill Buzbee1465db52009-09-23 17:17:35 -07001948 loadValueDirectFixed(cUnit, rlSrc, r0);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001949 dvmCompilerClobber(cUnit, r0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001950 if ((dalvikOpCode == OP_DIV_INT_LIT8) ||
1951 (dalvikOpCode == OP_DIV_INT_LIT16)) {
1952 loadConstant(cUnit, r2, (int)__aeabi_idiv);
1953 isDiv = true;
1954 } else {
1955 loadConstant(cUnit, r2, (int)__aeabi_idivmod);
1956 isDiv = false;
1957 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07001958 loadConstant(cUnit, r1, lit);
Bill Buzbee1465db52009-09-23 17:17:35 -07001959 opReg(cUnit, kOpBlx, r2);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001960 dvmCompilerColbberCallRegs(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07001961 if (isDiv)
Bill Buzbeec6f10662010-02-09 11:16:15 -08001962 rlResult = dvmCompilerGetReturn(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07001963 else
Bill Buzbeec6f10662010-02-09 11:16:15 -08001964 rlResult = dvmCompilerGetReturnAlt(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07001965 storeValue(cUnit, rlDest, rlResult);
1966 return false;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001967 break;
1968 default:
1969 return true;
1970 }
Bill Buzbee1465db52009-09-23 17:17:35 -07001971 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001972 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001973 // Avoid shifts by literal 0 - no support in Thumb. Change to copy
1974 if (shiftOp && (lit == 0)) {
1975 genRegCopy(cUnit, rlResult.lowReg, rlSrc.lowReg);
1976 } else {
1977 opRegRegImm(cUnit, op, rlResult.lowReg, rlSrc.lowReg, lit);
1978 }
1979 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001980 return false;
1981}
1982
1983static bool handleFmt22c(CompilationUnit *cUnit, MIR *mir)
1984{
1985 OpCode dalvikOpCode = mir->dalvikInsn.opCode;
1986 int fieldOffset;
1987
1988 if (dalvikOpCode >= OP_IGET && dalvikOpCode <= OP_IPUT_SHORT) {
1989 InstField *pInstField = (InstField *)
1990 cUnit->method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vC];
Ben Chengba4fc8b2009-06-01 13:00:29 -07001991
1992 assert(pInstField != NULL);
1993 fieldOffset = pInstField->byteOffset;
1994 } else {
Ben Chenga0e7b602009-10-13 23:09:01 -07001995 /* Deliberately break the code while make the compiler happy */
1996 fieldOffset = -1;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001997 }
1998 switch (dalvikOpCode) {
Ben Chengba4fc8b2009-06-01 13:00:29 -07001999 case OP_NEW_ARRAY: {
Bill Buzbee1465db52009-09-23 17:17:35 -07002000 // Generates a call - use explicit registers
Bill Buzbeec6f10662010-02-09 11:16:15 -08002001 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
2002 RegLocation rlDest = dvmCompilerGetDest(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07002003 RegLocation rlResult;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002004 void *classPtr = (void*)
2005 (cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vC]);
2006 assert(classPtr != NULL);
Bill Buzbeec6f10662010-02-09 11:16:15 -08002007 dvmCompilerFlushAllRegs(cUnit); /* Everything to home location */
Bill Buzbee1465db52009-09-23 17:17:35 -07002008 genExportPC(cUnit, mir);
2009 loadValueDirectFixed(cUnit, rlSrc, r1); /* Len */
Ben Chengba4fc8b2009-06-01 13:00:29 -07002010 loadConstant(cUnit, r0, (int) classPtr );
Bill Buzbee1465db52009-09-23 17:17:35 -07002011 loadConstant(cUnit, r3, (int)dvmAllocArrayByClass);
Ben Cheng4f489172009-09-27 17:08:35 -07002012 /*
2013 * "len < 0": bail to the interpreter to re-execute the
2014 * instruction
2015 */
Bill Buzbee89efc3d2009-07-28 11:22:22 -07002016 ArmLIR *pcrLabel =
Bill Buzbee1465db52009-09-23 17:17:35 -07002017 genRegImmCheck(cUnit, kArmCondMi, r1, 0, mir->offset, NULL);
Bill Buzbee270c1d62009-08-13 16:58:07 -07002018 loadConstant(cUnit, r2, ALLOC_DONT_TRACK);
Bill Buzbee1465db52009-09-23 17:17:35 -07002019 opReg(cUnit, kOpBlx, r3);
Bill Buzbeec6f10662010-02-09 11:16:15 -08002020 dvmCompilerColbberCallRegs(cUnit);
Ben Cheng4f489172009-09-27 17:08:35 -07002021 /* generate a branch over if allocation is successful */
Bill Buzbee1465db52009-09-23 17:17:35 -07002022 opRegImm(cUnit, kOpCmp, r0, 0); /* NULL? */
2023 ArmLIR *branchOver = opCondBranch(cUnit, kArmCondNe);
Ben Cheng4f489172009-09-27 17:08:35 -07002024 /*
2025 * OOM exception needs to be thrown here and cannot re-execute
2026 */
2027 loadConstant(cUnit, r0,
2028 (int) (cUnit->method->insns + mir->offset));
2029 genDispatchToHandler(cUnit, TEMPLATE_THROW_EXCEPTION_COMMON);
2030 /* noreturn */
2031
Bill Buzbee1465db52009-09-23 17:17:35 -07002032 ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel);
Ben Cheng4f489172009-09-27 17:08:35 -07002033 target->defMask = ENCODE_ALL;
2034 branchOver->generic.target = (LIR *) target;
Bill Buzbeec6f10662010-02-09 11:16:15 -08002035 rlResult = dvmCompilerGetReturn(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07002036 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002037 break;
2038 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07002039 case OP_INSTANCE_OF: {
Bill Buzbee1465db52009-09-23 17:17:35 -07002040 // May generate a call - use explicit registers
Bill Buzbeec6f10662010-02-09 11:16:15 -08002041 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
2042 RegLocation rlDest = dvmCompilerGetDest(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07002043 RegLocation rlResult;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002044 ClassObject *classPtr =
2045 (cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vC]);
Bill Buzbee480e6782010-01-27 15:43:08 -08002046 /*
2047 * Note: It is possible that classPtr is NULL at this point,
2048 * even though this instruction has been successfully interpreted.
2049 * If the previous interpretation had a null source, the
2050 * interpreter would not have bothered to resolve the clazz.
2051 * Bail out to the interpreter in this case, and log it
2052 * so that we can tell if it happens frequently.
2053 */
2054 if (classPtr == NULL) {
2055 LOGD("null clazz in OP_INSTANCE_OF, single-stepping");
2056 genInterpSingleStep(cUnit, mir);
2057 break;
2058 }
Bill Buzbeec6f10662010-02-09 11:16:15 -08002059 dvmCompilerFlushAllRegs(cUnit); /* Everything to home location */
Bill Buzbee1465db52009-09-23 17:17:35 -07002060 loadValueDirectFixed(cUnit, rlSrc, r0); /* Ref */
Ben Chengba4fc8b2009-06-01 13:00:29 -07002061 loadConstant(cUnit, r2, (int) classPtr );
Bill Buzbee270c1d62009-08-13 16:58:07 -07002062//TUNING: compare to 0 primative to allow use of CB[N]Z
Bill Buzbee1465db52009-09-23 17:17:35 -07002063 opRegImm(cUnit, kOpCmp, r0, 0); /* NULL? */
Ben Cheng752c7942009-06-22 10:50:07 -07002064 /* When taken r0 has NULL which can be used for store directly */
Bill Buzbee1465db52009-09-23 17:17:35 -07002065 ArmLIR *branch1 = opCondBranch(cUnit, kArmCondEq);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002066 /* r1 now contains object->clazz */
Bill Buzbee270c1d62009-08-13 16:58:07 -07002067 loadWordDisp(cUnit, r0, offsetof(Object, clazz), r1);
Bill Buzbee1465db52009-09-23 17:17:35 -07002068 /* r1 now contains object->clazz */
2069 loadConstant(cUnit, r3, (int)dvmInstanceofNonTrivial);
Ben Cheng752c7942009-06-22 10:50:07 -07002070 loadConstant(cUnit, r0, 1); /* Assume true */
Bill Buzbee1465db52009-09-23 17:17:35 -07002071 opRegReg(cUnit, kOpCmp, r1, r2);
2072 ArmLIR *branch2 = opCondBranch(cUnit, kArmCondEq);
2073 genRegCopy(cUnit, r0, r1);
2074 genRegCopy(cUnit, r1, r2);
2075 opReg(cUnit, kOpBlx, r3);
Bill Buzbeec6f10662010-02-09 11:16:15 -08002076 dvmCompilerColbberCallRegs(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002077 /* branch target here */
Bill Buzbee1465db52009-09-23 17:17:35 -07002078 ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel);
Ben Chengd7d426a2009-09-22 11:23:36 -07002079 target->defMask = ENCODE_ALL;
Bill Buzbeec6f10662010-02-09 11:16:15 -08002080 rlResult = dvmCompilerGetReturn(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07002081 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002082 branch1->generic.target = (LIR *)target;
2083 branch2->generic.target = (LIR *)target;
2084 break;
2085 }
2086 case OP_IGET_WIDE:
2087 genIGetWide(cUnit, mir, fieldOffset);
2088 break;
2089 case OP_IGET:
2090 case OP_IGET_OBJECT:
Bill Buzbee1465db52009-09-23 17:17:35 -07002091 genIGet(cUnit, mir, kWord, fieldOffset);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002092 break;
2093 case OP_IGET_BOOLEAN:
Bill Buzbee1465db52009-09-23 17:17:35 -07002094 genIGet(cUnit, mir, kUnsignedByte, fieldOffset);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002095 break;
2096 case OP_IGET_BYTE:
Bill Buzbee1465db52009-09-23 17:17:35 -07002097 genIGet(cUnit, mir, kSignedByte, fieldOffset);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002098 break;
2099 case OP_IGET_CHAR:
Bill Buzbee1465db52009-09-23 17:17:35 -07002100 genIGet(cUnit, mir, kUnsignedHalf, fieldOffset);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002101 break;
2102 case OP_IGET_SHORT:
Bill Buzbee1465db52009-09-23 17:17:35 -07002103 genIGet(cUnit, mir, kSignedHalf, fieldOffset);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002104 break;
2105 case OP_IPUT_WIDE:
2106 genIPutWide(cUnit, mir, fieldOffset);
2107 break;
2108 case OP_IPUT:
2109 case OP_IPUT_OBJECT:
Bill Buzbee1465db52009-09-23 17:17:35 -07002110 genIPut(cUnit, mir, kWord, fieldOffset);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002111 break;
2112 case OP_IPUT_SHORT:
2113 case OP_IPUT_CHAR:
Bill Buzbee1465db52009-09-23 17:17:35 -07002114 genIPut(cUnit, mir, kUnsignedHalf, fieldOffset);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002115 break;
2116 case OP_IPUT_BYTE:
2117 case OP_IPUT_BOOLEAN:
Bill Buzbee1465db52009-09-23 17:17:35 -07002118 genIPut(cUnit, mir, kUnsignedByte, fieldOffset);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002119 break;
2120 default:
2121 return true;
2122 }
2123 return false;
2124}
2125
2126static bool handleFmt22cs(CompilationUnit *cUnit, MIR *mir)
2127{
2128 OpCode dalvikOpCode = mir->dalvikInsn.opCode;
2129 int fieldOffset = mir->dalvikInsn.vC;
2130 switch (dalvikOpCode) {
2131 case OP_IGET_QUICK:
2132 case OP_IGET_OBJECT_QUICK:
Bill Buzbee1465db52009-09-23 17:17:35 -07002133 genIGet(cUnit, mir, kWord, fieldOffset);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002134 break;
2135 case OP_IPUT_QUICK:
2136 case OP_IPUT_OBJECT_QUICK:
Bill Buzbee1465db52009-09-23 17:17:35 -07002137 genIPut(cUnit, mir, kWord, fieldOffset);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002138 break;
2139 case OP_IGET_WIDE_QUICK:
2140 genIGetWide(cUnit, mir, fieldOffset);
2141 break;
2142 case OP_IPUT_WIDE_QUICK:
2143 genIPutWide(cUnit, mir, fieldOffset);
2144 break;
2145 default:
2146 return true;
2147 }
2148 return false;
2149
2150}
2151
2152/* Compare agaist zero */
2153static bool handleFmt22t(CompilationUnit *cUnit, MIR *mir, BasicBlock *bb,
Bill Buzbee89efc3d2009-07-28 11:22:22 -07002154 ArmLIR *labelList)
Ben Chengba4fc8b2009-06-01 13:00:29 -07002155{
2156 OpCode dalvikOpCode = mir->dalvikInsn.opCode;
Bill Buzbee89efc3d2009-07-28 11:22:22 -07002157 ArmConditionCode cond;
Bill Buzbeec6f10662010-02-09 11:16:15 -08002158 RegLocation rlSrc1 = dvmCompilerGetSrc(cUnit, mir, 0);
2159 RegLocation rlSrc2 = dvmCompilerGetSrc(cUnit, mir, 1);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002160
Bill Buzbee1465db52009-09-23 17:17:35 -07002161 rlSrc1 = loadValue(cUnit, rlSrc1, kCoreReg);
2162 rlSrc2 = loadValue(cUnit, rlSrc2, kCoreReg);
2163 opRegReg(cUnit, kOpCmp, rlSrc1.lowReg, rlSrc2.lowReg);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002164
2165 switch (dalvikOpCode) {
2166 case OP_IF_EQ:
Bill Buzbee1465db52009-09-23 17:17:35 -07002167 cond = kArmCondEq;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002168 break;
2169 case OP_IF_NE:
Bill Buzbee1465db52009-09-23 17:17:35 -07002170 cond = kArmCondNe;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002171 break;
2172 case OP_IF_LT:
Bill Buzbee1465db52009-09-23 17:17:35 -07002173 cond = kArmCondLt;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002174 break;
2175 case OP_IF_GE:
Bill Buzbee1465db52009-09-23 17:17:35 -07002176 cond = kArmCondGe;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002177 break;
2178 case OP_IF_GT:
Bill Buzbee1465db52009-09-23 17:17:35 -07002179 cond = kArmCondGt;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002180 break;
2181 case OP_IF_LE:
Bill Buzbee1465db52009-09-23 17:17:35 -07002182 cond = kArmCondLe;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002183 break;
2184 default:
2185 cond = 0;
2186 LOGE("Unexpected opcode (%d) for Fmt22t\n", dalvikOpCode);
2187 dvmAbort();
2188 }
2189 genConditionalBranch(cUnit, cond, &labelList[bb->taken->id]);
2190 /* This mostly likely will be optimized away in a later phase */
2191 genUnconditionalBranch(cUnit, &labelList[bb->fallThrough->id]);
2192 return false;
2193}
2194
2195static bool handleFmt22x_Fmt32x(CompilationUnit *cUnit, MIR *mir)
2196{
2197 OpCode opCode = mir->dalvikInsn.opCode;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002198
2199 switch (opCode) {
2200 case OP_MOVE_16:
2201 case OP_MOVE_OBJECT_16:
2202 case OP_MOVE_FROM16:
Ben Chenge9695e52009-06-16 16:11:47 -07002203 case OP_MOVE_OBJECT_FROM16: {
Bill Buzbeec6f10662010-02-09 11:16:15 -08002204 storeValue(cUnit, dvmCompilerGetDest(cUnit, mir, 0),
2205 dvmCompilerGetSrc(cUnit, mir, 0));
Ben Chengba4fc8b2009-06-01 13:00:29 -07002206 break;
Ben Chenge9695e52009-06-16 16:11:47 -07002207 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07002208 case OP_MOVE_WIDE_16:
Ben Chenge9695e52009-06-16 16:11:47 -07002209 case OP_MOVE_WIDE_FROM16: {
Bill Buzbeec6f10662010-02-09 11:16:15 -08002210 storeValueWide(cUnit, dvmCompilerGetDestWide(cUnit, mir, 0, 1),
2211 dvmCompilerGetSrcWide(cUnit, mir, 0, 1));
Ben Chengba4fc8b2009-06-01 13:00:29 -07002212 break;
Ben Chenge9695e52009-06-16 16:11:47 -07002213 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07002214 default:
2215 return true;
2216 }
2217 return false;
2218}
2219
2220static bool handleFmt23x(CompilationUnit *cUnit, MIR *mir)
2221{
2222 OpCode opCode = mir->dalvikInsn.opCode;
Bill Buzbee1465db52009-09-23 17:17:35 -07002223 RegLocation rlSrc1;
2224 RegLocation rlSrc2;
2225 RegLocation rlDest;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002226
2227 if ( (opCode >= OP_ADD_INT) && (opCode <= OP_REM_DOUBLE)) {
Ben Cheng5d90c202009-11-22 23:31:11 -08002228 return genArithOp( cUnit, mir );
Ben Chengba4fc8b2009-06-01 13:00:29 -07002229 }
2230
Bill Buzbee1465db52009-09-23 17:17:35 -07002231 /* APUTs have 3 sources and no targets */
2232 if (mir->ssaRep->numDefs == 0) {
2233 if (mir->ssaRep->numUses == 3) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08002234 rlDest = dvmCompilerGetSrc(cUnit, mir, 0);
2235 rlSrc1 = dvmCompilerGetSrc(cUnit, mir, 1);
2236 rlSrc2 = dvmCompilerGetSrc(cUnit, mir, 2);
Bill Buzbee1465db52009-09-23 17:17:35 -07002237 } else {
2238 assert(mir->ssaRep->numUses == 4);
Bill Buzbeec6f10662010-02-09 11:16:15 -08002239 rlDest = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
2240 rlSrc1 = dvmCompilerGetSrc(cUnit, mir, 2);
2241 rlSrc2 = dvmCompilerGetSrc(cUnit, mir, 3);
Bill Buzbee1465db52009-09-23 17:17:35 -07002242 }
2243 } else {
2244 /* Two sources and 1 dest. Deduce the operand sizes */
2245 if (mir->ssaRep->numUses == 4) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08002246 rlSrc1 = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
2247 rlSrc2 = dvmCompilerGetSrcWide(cUnit, mir, 2, 3);
Bill Buzbee1465db52009-09-23 17:17:35 -07002248 } else {
2249 assert(mir->ssaRep->numUses == 2);
Bill Buzbeec6f10662010-02-09 11:16:15 -08002250 rlSrc1 = dvmCompilerGetSrc(cUnit, mir, 0);
2251 rlSrc2 = dvmCompilerGetSrc(cUnit, mir, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -07002252 }
2253 if (mir->ssaRep->numDefs == 2) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08002254 rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -07002255 } else {
2256 assert(mir->ssaRep->numDefs == 1);
Bill Buzbeec6f10662010-02-09 11:16:15 -08002257 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07002258 }
2259 }
2260
2261
Ben Chengba4fc8b2009-06-01 13:00:29 -07002262 switch (opCode) {
Bill Buzbeed45ba372009-06-15 17:00:57 -07002263 case OP_CMPL_FLOAT:
2264 case OP_CMPG_FLOAT:
2265 case OP_CMPL_DOUBLE:
2266 case OP_CMPG_DOUBLE:
Ben Cheng5d90c202009-11-22 23:31:11 -08002267 return genCmpFP(cUnit, mir, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002268 case OP_CMP_LONG:
Bill Buzbee1465db52009-09-23 17:17:35 -07002269 genCmpLong(cUnit, mir, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002270 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002271 case OP_AGET_WIDE:
Bill Buzbee1465db52009-09-23 17:17:35 -07002272 genArrayGet(cUnit, mir, kLong, rlSrc1, rlSrc2, rlDest, 3);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002273 break;
2274 case OP_AGET:
2275 case OP_AGET_OBJECT:
Bill Buzbee1465db52009-09-23 17:17:35 -07002276 genArrayGet(cUnit, mir, kWord, rlSrc1, rlSrc2, rlDest, 2);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002277 break;
2278 case OP_AGET_BOOLEAN:
Bill Buzbee1465db52009-09-23 17:17:35 -07002279 genArrayGet(cUnit, mir, kUnsignedByte, rlSrc1, rlSrc2, rlDest, 0);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002280 break;
2281 case OP_AGET_BYTE:
Bill Buzbee1465db52009-09-23 17:17:35 -07002282 genArrayGet(cUnit, mir, kSignedByte, rlSrc1, rlSrc2, rlDest, 0);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002283 break;
2284 case OP_AGET_CHAR:
Bill Buzbee1465db52009-09-23 17:17:35 -07002285 genArrayGet(cUnit, mir, kUnsignedHalf, rlSrc1, rlSrc2, rlDest, 1);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002286 break;
2287 case OP_AGET_SHORT:
Bill Buzbee1465db52009-09-23 17:17:35 -07002288 genArrayGet(cUnit, mir, kSignedHalf, rlSrc1, rlSrc2, rlDest, 1);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002289 break;
2290 case OP_APUT_WIDE:
Bill Buzbee1465db52009-09-23 17:17:35 -07002291 genArrayPut(cUnit, mir, kLong, rlSrc1, rlSrc2, rlDest, 3);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002292 break;
2293 case OP_APUT:
2294 case OP_APUT_OBJECT:
Bill Buzbee1465db52009-09-23 17:17:35 -07002295 genArrayPut(cUnit, mir, kWord, rlSrc1, rlSrc2, rlDest, 2);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002296 break;
2297 case OP_APUT_SHORT:
2298 case OP_APUT_CHAR:
Bill Buzbee1465db52009-09-23 17:17:35 -07002299 genArrayPut(cUnit, mir, kUnsignedHalf, rlSrc1, rlSrc2, rlDest, 1);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002300 break;
2301 case OP_APUT_BYTE:
2302 case OP_APUT_BOOLEAN:
Bill Buzbee1465db52009-09-23 17:17:35 -07002303 genArrayPut(cUnit, mir, kUnsignedByte, rlSrc1, rlSrc2, rlDest, 0);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002304 break;
2305 default:
2306 return true;
2307 }
2308 return false;
2309}
2310
Ben Cheng6c10a972009-10-29 14:39:18 -07002311/*
2312 * Find the matching case.
2313 *
2314 * return values:
2315 * r0 (low 32-bit): pc of the chaining cell corresponding to the resolved case,
2316 * including default which is placed at MIN(size, MAX_CHAINED_SWITCH_CASES).
2317 * r1 (high 32-bit): the branch offset of the matching case (only for indexes
2318 * above MAX_CHAINED_SWITCH_CASES).
2319 *
2320 * Instructions around the call are:
2321 *
2322 * mov r2, pc
2323 * blx &findPackedSwitchIndex
2324 * mov pc, r0
2325 * .align4
2326 * chaining cell for case 0 [8 bytes]
2327 * chaining cell for case 1 [8 bytes]
2328 * :
2329 * chaining cell for case MIN(size, MAX_CHAINED_SWITCH_CASES)-1 [8 bytes]
2330 * chaining cell for case default [8 bytes]
2331 * noChain exit
2332 */
2333s8 findPackedSwitchIndex(const u2* switchData, int testVal, int pc)
2334{
2335 int size;
2336 int firstKey;
2337 const int *entries;
2338 int index;
2339 int jumpIndex;
2340 int caseDPCOffset = 0;
2341 /* In Thumb mode pc is 4 ahead of the "mov r2, pc" instruction */
2342 int chainingPC = (pc + 4) & ~3;
2343
2344 /*
2345 * Packed switch data format:
2346 * ushort ident = 0x0100 magic value
2347 * ushort size number of entries in the table
2348 * int first_key first (and lowest) switch case value
2349 * int targets[size] branch targets, relative to switch opcode
2350 *
2351 * Total size is (4+size*2) 16-bit code units.
2352 */
2353 size = switchData[1];
2354 assert(size > 0);
2355
2356 firstKey = switchData[2];
2357 firstKey |= switchData[3] << 16;
2358
2359
2360 /* The entries are guaranteed to be aligned on a 32-bit boundary;
2361 * we can treat them as a native int array.
2362 */
2363 entries = (const int*) &switchData[4];
2364 assert(((u4)entries & 0x3) == 0);
2365
2366 index = testVal - firstKey;
2367
2368 /* Jump to the default cell */
2369 if (index < 0 || index >= size) {
2370 jumpIndex = MIN(size, MAX_CHAINED_SWITCH_CASES);
2371 /* Jump to the non-chaining exit point */
2372 } else if (index >= MAX_CHAINED_SWITCH_CASES) {
2373 jumpIndex = MAX_CHAINED_SWITCH_CASES + 1;
2374 caseDPCOffset = entries[index];
2375 /* Jump to the inline chaining cell */
2376 } else {
2377 jumpIndex = index;
2378 }
2379
2380 chainingPC += jumpIndex * 8;
2381 return (((s8) caseDPCOffset) << 32) | (u8) chainingPC;
2382}
2383
2384/* See comments for findPackedSwitchIndex */
2385s8 findSparseSwitchIndex(const u2* switchData, int testVal, int pc)
2386{
2387 int size;
2388 const int *keys;
2389 const int *entries;
2390 int chainingPC = (pc + 4) & ~3;
2391 int i;
2392
2393 /*
2394 * Sparse switch data format:
2395 * ushort ident = 0x0200 magic value
2396 * ushort size number of entries in the table; > 0
2397 * int keys[size] keys, sorted low-to-high; 32-bit aligned
2398 * int targets[size] branch targets, relative to switch opcode
2399 *
2400 * Total size is (2+size*4) 16-bit code units.
2401 */
2402
2403 size = switchData[1];
2404 assert(size > 0);
2405
2406 /* The keys are guaranteed to be aligned on a 32-bit boundary;
2407 * we can treat them as a native int array.
2408 */
2409 keys = (const int*) &switchData[2];
2410 assert(((u4)keys & 0x3) == 0);
2411
2412 /* The entries are guaranteed to be aligned on a 32-bit boundary;
2413 * we can treat them as a native int array.
2414 */
2415 entries = keys + size;
2416 assert(((u4)entries & 0x3) == 0);
2417
2418 /*
2419 * Run through the list of keys, which are guaranteed to
2420 * be sorted low-to-high.
2421 *
2422 * Most tables have 3-4 entries. Few have more than 10. A binary
2423 * search here is probably not useful.
2424 */
2425 for (i = 0; i < size; i++) {
2426 int k = keys[i];
2427 if (k == testVal) {
2428 /* MAX_CHAINED_SWITCH_CASES + 1 is the start of the overflow case */
2429 int jumpIndex = (i < MAX_CHAINED_SWITCH_CASES) ?
2430 i : MAX_CHAINED_SWITCH_CASES + 1;
2431 chainingPC += jumpIndex * 8;
2432 return (((s8) entries[i]) << 32) | (u8) chainingPC;
2433 } else if (k > testVal) {
2434 break;
2435 }
2436 }
2437 return chainingPC + MIN(size, MAX_CHAINED_SWITCH_CASES) * 8;
2438}
2439
Ben Chengba4fc8b2009-06-01 13:00:29 -07002440static bool handleFmt31t(CompilationUnit *cUnit, MIR *mir)
2441{
2442 OpCode dalvikOpCode = mir->dalvikInsn.opCode;
2443 switch (dalvikOpCode) {
2444 case OP_FILL_ARRAY_DATA: {
Bill Buzbeec6f10662010-02-09 11:16:15 -08002445 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07002446 // Making a call - use explicit registers
Bill Buzbeec6f10662010-02-09 11:16:15 -08002447 dvmCompilerFlushAllRegs(cUnit); /* Everything to home location */
Bill Buzbee1465db52009-09-23 17:17:35 -07002448 genExportPC(cUnit, mir);
2449 loadValueDirectFixed(cUnit, rlSrc, r0);
Bill Buzbeefd023aa2009-11-02 09:23:49 -08002450 loadConstant(cUnit, r2, (int)dvmInterpHandleFillArrayData);
Ben Cheng6c10a972009-10-29 14:39:18 -07002451 loadConstant(cUnit, r1,
2452 (int) (cUnit->method->insns + mir->offset + mir->dalvikInsn.vB));
Bill Buzbee1465db52009-09-23 17:17:35 -07002453 opReg(cUnit, kOpBlx, r2);
Bill Buzbeec6f10662010-02-09 11:16:15 -08002454 dvmCompilerColbberCallRegs(cUnit);
Bill Buzbeefd023aa2009-11-02 09:23:49 -08002455 /* generate a branch over if successful */
2456 opRegImm(cUnit, kOpCmp, r0, 0); /* NULL? */
2457 ArmLIR *branchOver = opCondBranch(cUnit, kArmCondNe);
2458 loadConstant(cUnit, r0,
2459 (int) (cUnit->method->insns + mir->offset));
2460 genDispatchToHandler(cUnit, TEMPLATE_THROW_EXCEPTION_COMMON);
2461 ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel);
2462 target->defMask = ENCODE_ALL;
2463 branchOver->generic.target = (LIR *) target;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002464 break;
2465 }
2466 /*
Ben Cheng6c10a972009-10-29 14:39:18 -07002467 * Compute the goto target of up to
2468 * MIN(switchSize, MAX_CHAINED_SWITCH_CASES) + 1 chaining cells.
2469 * See the comment before findPackedSwitchIndex for the code layout.
Ben Chengba4fc8b2009-06-01 13:00:29 -07002470 */
2471 case OP_PACKED_SWITCH:
2472 case OP_SPARSE_SWITCH: {
Bill Buzbeec6f10662010-02-09 11:16:15 -08002473 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
2474 dvmCompilerFlushAllRegs(cUnit); /* Everything to home location */
Bill Buzbee1465db52009-09-23 17:17:35 -07002475 loadValueDirectFixed(cUnit, rlSrc, r1);
Bill Buzbeec6f10662010-02-09 11:16:15 -08002476 dvmCompilerLockAllTemps(cUnit);
Ben Cheng6c10a972009-10-29 14:39:18 -07002477 const u2 *switchData =
2478 cUnit->method->insns + mir->offset + mir->dalvikInsn.vB;
2479 u2 size = switchData[1];
2480
Ben Chengba4fc8b2009-06-01 13:00:29 -07002481 if (dalvikOpCode == OP_PACKED_SWITCH) {
Ben Cheng6c10a972009-10-29 14:39:18 -07002482 loadConstant(cUnit, r4PC, (int)findPackedSwitchIndex);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002483 } else {
Ben Cheng6c10a972009-10-29 14:39:18 -07002484 loadConstant(cUnit, r4PC, (int)findSparseSwitchIndex);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002485 }
Ben Cheng6c10a972009-10-29 14:39:18 -07002486 /* r0 <- Addr of the switch data */
2487 loadConstant(cUnit, r0,
2488 (int) (cUnit->method->insns + mir->offset + mir->dalvikInsn.vB));
2489 /* r2 <- pc of the instruction following the blx */
2490 opRegReg(cUnit, kOpMov, r2, rpc);
Bill Buzbee1465db52009-09-23 17:17:35 -07002491 opReg(cUnit, kOpBlx, r4PC);
Bill Buzbeec6f10662010-02-09 11:16:15 -08002492 dvmCompilerColbberCallRegs(cUnit);
Ben Cheng6c10a972009-10-29 14:39:18 -07002493 /* pc <- computed goto target */
2494 opRegReg(cUnit, kOpMov, rpc, r0);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002495 break;
2496 }
2497 default:
2498 return true;
2499 }
2500 return false;
2501}
2502
2503static bool handleFmt35c_3rc(CompilationUnit *cUnit, MIR *mir, BasicBlock *bb,
Bill Buzbee89efc3d2009-07-28 11:22:22 -07002504 ArmLIR *labelList)
Ben Chengba4fc8b2009-06-01 13:00:29 -07002505{
Bill Buzbee9bc3df32009-07-30 10:52:29 -07002506 ArmLIR *retChainingCell = NULL;
Bill Buzbee89efc3d2009-07-28 11:22:22 -07002507 ArmLIR *pcrLabel = NULL;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002508
Bill Buzbeef4ce16f2009-07-28 13:28:25 -07002509 if (bb->fallThrough != NULL)
2510 retChainingCell = &labelList[bb->fallThrough->id];
2511
Ben Chengba4fc8b2009-06-01 13:00:29 -07002512 DecodedInstruction *dInsn = &mir->dalvikInsn;
2513 switch (mir->dalvikInsn.opCode) {
2514 /*
2515 * calleeMethod = this->clazz->vtable[
2516 * method->clazz->pDvmDex->pResMethods[BBBB]->methodIndex
2517 * ]
2518 */
2519 case OP_INVOKE_VIRTUAL:
2520 case OP_INVOKE_VIRTUAL_RANGE: {
Bill Buzbee89efc3d2009-07-28 11:22:22 -07002521 ArmLIR *predChainingCell = &labelList[bb->taken->id];
Ben Chengba4fc8b2009-06-01 13:00:29 -07002522 int methodIndex =
2523 cUnit->method->clazz->pDvmDex->pResMethods[dInsn->vB]->
2524 methodIndex;
2525
2526 if (mir->dalvikInsn.opCode == OP_INVOKE_VIRTUAL)
2527 genProcessArgsNoRange(cUnit, mir, dInsn, &pcrLabel);
2528 else
2529 genProcessArgsRange(cUnit, mir, dInsn, &pcrLabel);
2530
Ben Cheng38329f52009-07-07 14:19:20 -07002531 genInvokeVirtualCommon(cUnit, mir, methodIndex,
2532 retChainingCell,
2533 predChainingCell,
2534 pcrLabel);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002535 break;
2536 }
2537 /*
2538 * calleeMethod = method->clazz->super->vtable[method->clazz->pDvmDex
2539 * ->pResMethods[BBBB]->methodIndex]
2540 */
2541 /* TODO - not excersized in RunPerf.jar */
2542 case OP_INVOKE_SUPER:
2543 case OP_INVOKE_SUPER_RANGE: {
2544 int mIndex = cUnit->method->clazz->pDvmDex->
2545 pResMethods[dInsn->vB]->methodIndex;
2546 const Method *calleeMethod =
2547 cUnit->method->clazz->super->vtable[mIndex];
2548
2549 if (mir->dalvikInsn.opCode == OP_INVOKE_SUPER)
2550 genProcessArgsNoRange(cUnit, mir, dInsn, &pcrLabel);
2551 else
2552 genProcessArgsRange(cUnit, mir, dInsn, &pcrLabel);
2553
2554 /* r0 = calleeMethod */
2555 loadConstant(cUnit, r0, (int) calleeMethod);
2556
Ben Cheng38329f52009-07-07 14:19:20 -07002557 genInvokeSingletonCommon(cUnit, mir, bb, labelList, pcrLabel,
2558 calleeMethod);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002559 break;
2560 }
2561 /* calleeMethod = method->clazz->pDvmDex->pResMethods[BBBB] */
2562 case OP_INVOKE_DIRECT:
2563 case OP_INVOKE_DIRECT_RANGE: {
2564 const Method *calleeMethod =
2565 cUnit->method->clazz->pDvmDex->pResMethods[dInsn->vB];
2566
2567 if (mir->dalvikInsn.opCode == OP_INVOKE_DIRECT)
2568 genProcessArgsNoRange(cUnit, mir, dInsn, &pcrLabel);
2569 else
2570 genProcessArgsRange(cUnit, mir, dInsn, &pcrLabel);
2571
2572 /* r0 = calleeMethod */
2573 loadConstant(cUnit, r0, (int) calleeMethod);
2574
Ben Cheng38329f52009-07-07 14:19:20 -07002575 genInvokeSingletonCommon(cUnit, mir, bb, labelList, pcrLabel,
2576 calleeMethod);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002577 break;
2578 }
2579 /* calleeMethod = method->clazz->pDvmDex->pResMethods[BBBB] */
2580 case OP_INVOKE_STATIC:
2581 case OP_INVOKE_STATIC_RANGE: {
2582 const Method *calleeMethod =
2583 cUnit->method->clazz->pDvmDex->pResMethods[dInsn->vB];
2584
2585 if (mir->dalvikInsn.opCode == OP_INVOKE_STATIC)
2586 genProcessArgsNoRange(cUnit, mir, dInsn,
2587 NULL /* no null check */);
2588 else
2589 genProcessArgsRange(cUnit, mir, dInsn,
2590 NULL /* no null check */);
2591
2592 /* r0 = calleeMethod */
2593 loadConstant(cUnit, r0, (int) calleeMethod);
2594
Ben Cheng38329f52009-07-07 14:19:20 -07002595 genInvokeSingletonCommon(cUnit, mir, bb, labelList, pcrLabel,
2596 calleeMethod);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002597 break;
2598 }
Bill Buzbee1465db52009-09-23 17:17:35 -07002599 /*
Ben Chengba4fc8b2009-06-01 13:00:29 -07002600 * calleeMethod = dvmFindInterfaceMethodInCache(this->clazz,
2601 * BBBB, method, method->clazz->pDvmDex)
Ben Cheng38329f52009-07-07 14:19:20 -07002602 *
2603 * Given "invoke-interface {v0}", the following is the generated code:
2604 *
2605 * 0x426a9abe : ldr r0, [r5, #0] --+
2606 * 0x426a9ac0 : mov r7, r5 |
2607 * 0x426a9ac2 : sub r7, #24 |
2608 * 0x426a9ac4 : cmp r0, #0 | genProcessArgsNoRange
2609 * 0x426a9ac6 : beq 0x426a9afe |
2610 * 0x426a9ac8 : stmia r7, <r0> --+
2611 * 0x426a9aca : ldr r4, [pc, #104] --> r4 <- dalvikPC of this invoke
2612 * 0x426a9acc : add r1, pc, #52 --> r1 <- &retChainingCell
2613 * 0x426a9ace : add r2, pc, #60 --> r2 <- &predictedChainingCell
2614 * 0x426a9ad0 : blx_1 0x426a918c --+ TEMPLATE_INVOKE_METHOD_
2615 * 0x426a9ad2 : blx_2 see above --+ PREDICTED_CHAIN
2616 * 0x426a9ad4 : b 0x426a9b0c --> off to the predicted chain
2617 * 0x426a9ad6 : b 0x426a9afe --> punt to the interpreter
Ben Chenga8e64a72009-10-20 13:01:36 -07002618 * 0x426a9ad8 : mov r8, r1 --+
2619 * 0x426a9ada : mov r9, r2 |
2620 * 0x426a9adc : mov r10, r3 |
Ben Cheng38329f52009-07-07 14:19:20 -07002621 * 0x426a9ade : mov r0, r3 |
2622 * 0x426a9ae0 : mov r1, #74 | dvmFindInterfaceMethodInCache
2623 * 0x426a9ae2 : ldr r2, [pc, #76] |
2624 * 0x426a9ae4 : ldr r3, [pc, #68] |
2625 * 0x426a9ae6 : ldr r7, [pc, #64] |
2626 * 0x426a9ae8 : blx r7 --+
Ben Chenga8e64a72009-10-20 13:01:36 -07002627 * 0x426a9aea : mov r1, r8 --> r1 <- rechain count
Ben Cheng38329f52009-07-07 14:19:20 -07002628 * 0x426a9aec : cmp r1, #0 --> compare against 0
2629 * 0x426a9aee : bgt 0x426a9af8 --> >=0? don't rechain
2630 * 0x426a9af0 : ldr r7, [r6, #96] --+
Ben Chenga8e64a72009-10-20 13:01:36 -07002631 * 0x426a9af2 : mov r2, r9 | dvmJitToPatchPredictedChain
2632 * 0x426a9af4 : mov r3, r10 |
Ben Cheng38329f52009-07-07 14:19:20 -07002633 * 0x426a9af6 : blx r7 --+
2634 * 0x426a9af8 : add r1, pc, #8 --> r1 <- &retChainingCell
2635 * 0x426a9afa : blx_1 0x426a9098 --+ TEMPLATE_INVOKE_METHOD_NO_OPT
2636 * 0x426a9afc : blx_2 see above --+
2637 * -------- reconstruct dalvik PC : 0x428b786c @ +0x001e
2638 * 0x426a9afe (0042): ldr r0, [pc, #52]
2639 * Exception_Handling:
2640 * 0x426a9b00 (0044): ldr r1, [r6, #84]
2641 * 0x426a9b02 (0046): blx r1
2642 * 0x426a9b04 (0048): .align4
2643 * -------- chaining cell (hot): 0x0021
2644 * 0x426a9b04 (0048): ldr r0, [r6, #92]
2645 * 0x426a9b06 (004a): blx r0
2646 * 0x426a9b08 (004c): data 0x7872(30834)
2647 * 0x426a9b0a (004e): data 0x428b(17035)
2648 * 0x426a9b0c (0050): .align4
2649 * -------- chaining cell (predicted)
2650 * 0x426a9b0c (0050): data 0x0000(0) --> will be patched into bx
2651 * 0x426a9b0e (0052): data 0x0000(0)
2652 * 0x426a9b10 (0054): data 0x0000(0) --> class
2653 * 0x426a9b12 (0056): data 0x0000(0)
2654 * 0x426a9b14 (0058): data 0x0000(0) --> method
2655 * 0x426a9b16 (005a): data 0x0000(0)
2656 * 0x426a9b18 (005c): data 0x0000(0) --> reset count
2657 * 0x426a9b1a (005e): data 0x0000(0)
2658 * 0x426a9b28 (006c): .word (0xad0392a5)
2659 * 0x426a9b2c (0070): .word (0x6e750)
2660 * 0x426a9b30 (0074): .word (0x4109a618)
2661 * 0x426a9b34 (0078): .word (0x428b786c)
Ben Chengba4fc8b2009-06-01 13:00:29 -07002662 */
2663 case OP_INVOKE_INTERFACE:
2664 case OP_INVOKE_INTERFACE_RANGE: {
Bill Buzbee89efc3d2009-07-28 11:22:22 -07002665 ArmLIR *predChainingCell = &labelList[bb->taken->id];
Ben Chengba4fc8b2009-06-01 13:00:29 -07002666 int methodIndex = dInsn->vB;
2667
Bill Buzbee1465db52009-09-23 17:17:35 -07002668 /* Ensure that nothing is both live and dirty */
Bill Buzbeec6f10662010-02-09 11:16:15 -08002669 dvmCompilerFlushAllRegs(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07002670
Ben Chengba4fc8b2009-06-01 13:00:29 -07002671 if (mir->dalvikInsn.opCode == OP_INVOKE_INTERFACE)
2672 genProcessArgsNoRange(cUnit, mir, dInsn, &pcrLabel);
2673 else
2674 genProcessArgsRange(cUnit, mir, dInsn, &pcrLabel);
2675
Ben Cheng38329f52009-07-07 14:19:20 -07002676 /* "this" is already left in r0 by genProcessArgs* */
2677
2678 /* r4PC = dalvikCallsite */
2679 loadConstant(cUnit, r4PC,
2680 (int) (cUnit->method->insns + mir->offset));
2681
2682 /* r1 = &retChainingCell */
Bill Buzbee270c1d62009-08-13 16:58:07 -07002683 ArmLIR *addrRetChain =
Bill Buzbee1465db52009-09-23 17:17:35 -07002684 opRegRegImm(cUnit, kOpAdd, r1, rpc, 0);
Ben Cheng38329f52009-07-07 14:19:20 -07002685 addrRetChain->generic.target = (LIR *) retChainingCell;
2686
2687 /* r2 = &predictedChainingCell */
Bill Buzbee89efc3d2009-07-28 11:22:22 -07002688 ArmLIR *predictedChainingCell =
Bill Buzbee1465db52009-09-23 17:17:35 -07002689 opRegRegImm(cUnit, kOpAdd, r2, rpc, 0);
Ben Cheng38329f52009-07-07 14:19:20 -07002690 predictedChainingCell->generic.target = (LIR *) predChainingCell;
2691
2692 genDispatchToHandler(cUnit, TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN);
2693
2694 /* return through lr - jump to the chaining cell */
2695 genUnconditionalBranch(cUnit, predChainingCell);
2696
2697 /*
2698 * null-check on "this" may have been eliminated, but we still need
2699 * a PC-reconstruction label for stack overflow bailout.
2700 */
2701 if (pcrLabel == NULL) {
2702 int dPC = (int) (cUnit->method->insns + mir->offset);
Bill Buzbee89efc3d2009-07-28 11:22:22 -07002703 pcrLabel = dvmCompilerNew(sizeof(ArmLIR), true);
Bill Buzbee1465db52009-09-23 17:17:35 -07002704 pcrLabel->opCode = ARM_PSEUDO_kPCReconstruction_CELL;
Ben Cheng38329f52009-07-07 14:19:20 -07002705 pcrLabel->operands[0] = dPC;
2706 pcrLabel->operands[1] = mir->offset;
2707 /* Insert the place holder to the growable list */
2708 dvmInsertGrowableList(&cUnit->pcReconstructionList, pcrLabel);
2709 }
2710
2711 /* return through lr+2 - punt to the interpreter */
2712 genUnconditionalBranch(cUnit, pcrLabel);
2713
2714 /*
2715 * return through lr+4 - fully resolve the callee method.
2716 * r1 <- count
2717 * r2 <- &predictedChainCell
2718 * r3 <- this->class
2719 * r4 <- dPC
2720 * r7 <- this->class->vtable
2721 */
2722
2723 /* Save count, &predictedChainCell, and class to high regs first */
Bill Buzbee1465db52009-09-23 17:17:35 -07002724 genRegCopy(cUnit, r8, r1);
2725 genRegCopy(cUnit, r9, r2);
2726 genRegCopy(cUnit, r10, r3);
Ben Cheng38329f52009-07-07 14:19:20 -07002727
Ben Chengba4fc8b2009-06-01 13:00:29 -07002728 /* r0 now contains this->clazz */
Bill Buzbee1465db52009-09-23 17:17:35 -07002729 genRegCopy(cUnit, r0, r3);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002730
2731 /* r1 = BBBB */
2732 loadConstant(cUnit, r1, dInsn->vB);
2733
2734 /* r2 = method (caller) */
2735 loadConstant(cUnit, r2, (int) cUnit->method);
2736
2737 /* r3 = pDvmDex */
2738 loadConstant(cUnit, r3, (int) cUnit->method->clazz->pDvmDex);
2739
2740 loadConstant(cUnit, r7,
2741 (intptr_t) dvmFindInterfaceMethodInCache);
Bill Buzbee1465db52009-09-23 17:17:35 -07002742 opReg(cUnit, kOpBlx, r7);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002743
2744 /* r0 = calleeMethod (returned from dvmFindInterfaceMethodInCache */
2745
Bill Buzbee1465db52009-09-23 17:17:35 -07002746 genRegCopy(cUnit, r1, r8);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002747
Ben Cheng38329f52009-07-07 14:19:20 -07002748 /* Check if rechain limit is reached */
Bill Buzbee1465db52009-09-23 17:17:35 -07002749 opRegImm(cUnit, kOpCmp, r1, 0);
Ben Cheng38329f52009-07-07 14:19:20 -07002750
Bill Buzbee1465db52009-09-23 17:17:35 -07002751 ArmLIR *bypassRechaining = opCondBranch(cUnit, kArmCondGt);
Ben Cheng38329f52009-07-07 14:19:20 -07002752
Bill Buzbee270c1d62009-08-13 16:58:07 -07002753 loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
2754 jitToInterpEntries.dvmJitToPatchPredictedChain), r7);
Ben Cheng38329f52009-07-07 14:19:20 -07002755
Bill Buzbee1465db52009-09-23 17:17:35 -07002756 genRegCopy(cUnit, r2, r9);
2757 genRegCopy(cUnit, r3, r10);
Ben Cheng38329f52009-07-07 14:19:20 -07002758
2759 /*
2760 * r0 = calleeMethod
2761 * r2 = &predictedChainingCell
2762 * r3 = class
2763 *
2764 * &returnChainingCell has been loaded into r1 but is not needed
2765 * when patching the chaining cell and will be clobbered upon
2766 * returning so it will be reconstructed again.
2767 */
Bill Buzbee1465db52009-09-23 17:17:35 -07002768 opReg(cUnit, kOpBlx, r7);
Ben Cheng38329f52009-07-07 14:19:20 -07002769
2770 /* r1 = &retChainingCell */
Bill Buzbee1465db52009-09-23 17:17:35 -07002771 addrRetChain = opRegRegImm(cUnit, kOpAdd, r1, rpc, 0);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002772 addrRetChain->generic.target = (LIR *) retChainingCell;
Ben Cheng38329f52009-07-07 14:19:20 -07002773
2774 bypassRechaining->generic.target = (LIR *) addrRetChain;
2775
Ben Chengba4fc8b2009-06-01 13:00:29 -07002776 /*
2777 * r0 = this, r1 = calleeMethod,
2778 * r1 = &ChainingCell,
2779 * r4PC = callsiteDPC,
2780 */
2781 genDispatchToHandler(cUnit, TEMPLATE_INVOKE_METHOD_NO_OPT);
2782#if defined(INVOKE_STATS)
Ben Cheng38329f52009-07-07 14:19:20 -07002783 gDvmJit.invokePredictedChain++;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002784#endif
2785 /* Handle exceptions using the interpreter */
2786 genTrap(cUnit, mir->offset, pcrLabel);
2787 break;
2788 }
2789 /* NOP */
2790 case OP_INVOKE_DIRECT_EMPTY: {
2791 return false;
2792 }
2793 case OP_FILLED_NEW_ARRAY:
2794 case OP_FILLED_NEW_ARRAY_RANGE: {
2795 /* Just let the interpreter deal with these */
2796 genInterpSingleStep(cUnit, mir);
2797 break;
2798 }
2799 default:
2800 return true;
2801 }
2802 return false;
2803}
2804
2805static bool handleFmt35ms_3rms(CompilationUnit *cUnit, MIR *mir,
Bill Buzbee89efc3d2009-07-28 11:22:22 -07002806 BasicBlock *bb, ArmLIR *labelList)
Ben Chengba4fc8b2009-06-01 13:00:29 -07002807{
Bill Buzbee89efc3d2009-07-28 11:22:22 -07002808 ArmLIR *retChainingCell = &labelList[bb->fallThrough->id];
2809 ArmLIR *predChainingCell = &labelList[bb->taken->id];
2810 ArmLIR *pcrLabel = NULL;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002811
2812 DecodedInstruction *dInsn = &mir->dalvikInsn;
2813 switch (mir->dalvikInsn.opCode) {
2814 /* calleeMethod = this->clazz->vtable[BBBB] */
2815 case OP_INVOKE_VIRTUAL_QUICK_RANGE:
2816 case OP_INVOKE_VIRTUAL_QUICK: {
2817 int methodIndex = dInsn->vB;
2818 if (mir->dalvikInsn.opCode == OP_INVOKE_VIRTUAL_QUICK)
2819 genProcessArgsNoRange(cUnit, mir, dInsn, &pcrLabel);
2820 else
2821 genProcessArgsRange(cUnit, mir, dInsn, &pcrLabel);
2822
Ben Cheng38329f52009-07-07 14:19:20 -07002823 genInvokeVirtualCommon(cUnit, mir, methodIndex,
2824 retChainingCell,
2825 predChainingCell,
2826 pcrLabel);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002827 break;
2828 }
2829 /* calleeMethod = method->clazz->super->vtable[BBBB] */
2830 case OP_INVOKE_SUPER_QUICK:
2831 case OP_INVOKE_SUPER_QUICK_RANGE: {
2832 const Method *calleeMethod =
2833 cUnit->method->clazz->super->vtable[dInsn->vB];
2834
2835 if (mir->dalvikInsn.opCode == OP_INVOKE_SUPER_QUICK)
2836 genProcessArgsNoRange(cUnit, mir, dInsn, &pcrLabel);
2837 else
2838 genProcessArgsRange(cUnit, mir, dInsn, &pcrLabel);
2839
2840 /* r0 = calleeMethod */
2841 loadConstant(cUnit, r0, (int) calleeMethod);
2842
Ben Cheng38329f52009-07-07 14:19:20 -07002843 genInvokeSingletonCommon(cUnit, mir, bb, labelList, pcrLabel,
2844 calleeMethod);
2845 /* Handle exceptions using the interpreter */
2846 genTrap(cUnit, mir->offset, pcrLabel);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002847 break;
2848 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07002849 default:
2850 return true;
2851 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07002852 return false;
2853}
2854
2855/*
Bill Buzbeefd023aa2009-11-02 09:23:49 -08002856 * This operation is complex enough that we'll do it partly inline
2857 * and partly with a handler. NOTE: the handler uses hardcoded
2858 * values for string object offsets and must be revisitied if the
2859 * layout changes.
2860 */
2861static bool genInlinedCompareTo(CompilationUnit *cUnit, MIR *mir)
2862{
2863#if defined(USE_GLOBAL_STRING_DEFS)
2864 return false;
2865#else
2866 ArmLIR *rollback;
Bill Buzbeec6f10662010-02-09 11:16:15 -08002867 RegLocation rlThis = dvmCompilerGetSrc(cUnit, mir, 0);
2868 RegLocation rlComp = dvmCompilerGetSrc(cUnit, mir, 1);
Bill Buzbeefd023aa2009-11-02 09:23:49 -08002869
2870 loadValueDirectFixed(cUnit, rlThis, r0);
2871 loadValueDirectFixed(cUnit, rlComp, r1);
2872 /* Test objects for NULL */
2873 rollback = genNullCheck(cUnit, rlThis.sRegLow, r0, mir->offset, NULL);
2874 genNullCheck(cUnit, rlComp.sRegLow, r1, mir->offset, rollback);
2875 /*
2876 * TUNING: we could check for object pointer equality before invoking
2877 * handler. Unclear whether the gain would be worth the added code size
2878 * expansion.
2879 */
2880 genDispatchToHandler(cUnit, TEMPLATE_STRING_COMPARETO);
Bill Buzbeec6f10662010-02-09 11:16:15 -08002881 storeValue(cUnit, inlinedTarget(cUnit, mir, false),
2882 dvmCompilerGetReturn(cUnit));
Bill Buzbeefd023aa2009-11-02 09:23:49 -08002883 return true;
2884#endif
2885}
2886
2887static bool genInlinedIndexOf(CompilationUnit *cUnit, MIR *mir, bool singleI)
2888{
2889#if defined(USE_GLOBAL_STRING_DEFS)
2890 return false;
2891#else
Bill Buzbeec6f10662010-02-09 11:16:15 -08002892 RegLocation rlThis = dvmCompilerGetSrc(cUnit, mir, 0);
2893 RegLocation rlChar = dvmCompilerGetSrc(cUnit, mir, 1);
Bill Buzbeefd023aa2009-11-02 09:23:49 -08002894
2895 loadValueDirectFixed(cUnit, rlThis, r0);
2896 loadValueDirectFixed(cUnit, rlChar, r1);
2897 if (!singleI) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08002898 RegLocation rlStart = dvmCompilerGetSrc(cUnit, mir, 2);
Bill Buzbeefd023aa2009-11-02 09:23:49 -08002899 loadValueDirectFixed(cUnit, rlStart, r2);
2900 } else {
2901 loadConstant(cUnit, r2, 0);
2902 }
2903 /* Test objects for NULL */
2904 genNullCheck(cUnit, rlThis.sRegLow, r0, mir->offset, NULL);
2905 genDispatchToHandler(cUnit, TEMPLATE_STRING_INDEXOF);
Bill Buzbeec6f10662010-02-09 11:16:15 -08002906 storeValue(cUnit, inlinedTarget(cUnit, mir, false),
2907 dvmCompilerGetReturn(cUnit));
Bill Buzbeefd023aa2009-11-02 09:23:49 -08002908 return true;
2909#endif
2910}
2911
2912
2913/*
Bill Buzbeece46c942009-11-20 15:41:34 -08002914 * NOTE: Handles both range and non-range versions (arguments
2915 * have already been normalized by this point).
Ben Chengba4fc8b2009-06-01 13:00:29 -07002916 */
Bill Buzbeece46c942009-11-20 15:41:34 -08002917static bool handleExecuteInline(CompilationUnit *cUnit, MIR *mir)
Ben Chengba4fc8b2009-06-01 13:00:29 -07002918{
2919 DecodedInstruction *dInsn = &mir->dalvikInsn;
2920 switch( mir->dalvikInsn.opCode) {
Bill Buzbeece46c942009-11-20 15:41:34 -08002921 case OP_EXECUTE_INLINE_RANGE:
Ben Chengba4fc8b2009-06-01 13:00:29 -07002922 case OP_EXECUTE_INLINE: {
2923 unsigned int i;
2924 const InlineOperation* inLineTable = dvmGetInlineOpsTable();
Bill Buzbee50a6bf22009-07-08 13:08:04 -07002925 int offset = offsetof(InterpState, retval);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002926 int operation = dInsn->vB;
Bill Buzbee1465db52009-09-23 17:17:35 -07002927 int tReg1;
2928 int tReg2;
Bill Buzbee50a6bf22009-07-08 13:08:04 -07002929 switch (operation) {
2930 case INLINE_EMPTYINLINEMETHOD:
2931 return false; /* Nop */
2932 case INLINE_STRING_LENGTH:
2933 return genInlinedStringLength(cUnit, mir);
2934 case INLINE_MATH_ABS_INT:
2935 return genInlinedAbsInt(cUnit, mir);
2936 case INLINE_MATH_ABS_LONG:
2937 return genInlinedAbsLong(cUnit, mir);
2938 case INLINE_MATH_MIN_INT:
2939 return genInlinedMinMaxInt(cUnit, mir, true);
2940 case INLINE_MATH_MAX_INT:
2941 return genInlinedMinMaxInt(cUnit, mir, false);
2942 case INLINE_STRING_CHARAT:
2943 return genInlinedStringCharAt(cUnit, mir);
2944 case INLINE_MATH_SQRT:
2945 if (genInlineSqrt(cUnit, mir))
Bill Buzbee9727c3d2009-08-01 11:32:36 -07002946 return false;
Bill Buzbee50a6bf22009-07-08 13:08:04 -07002947 else
2948 break; /* Handle with C routine */
Bill Buzbee50a6bf22009-07-08 13:08:04 -07002949 case INLINE_MATH_ABS_FLOAT:
Bill Buzbee1465db52009-09-23 17:17:35 -07002950 if (genInlinedAbsFloat(cUnit, mir))
2951 return false;
2952 else
2953 break;
Bill Buzbee50a6bf22009-07-08 13:08:04 -07002954 case INLINE_MATH_ABS_DOUBLE:
Bill Buzbee1465db52009-09-23 17:17:35 -07002955 if (genInlinedAbsDouble(cUnit, mir))
2956 return false;
2957 else
2958 break;
Bill Buzbee50a6bf22009-07-08 13:08:04 -07002959 case INLINE_STRING_COMPARETO:
Bill Buzbeefd023aa2009-11-02 09:23:49 -08002960 if (genInlinedCompareTo(cUnit, mir))
2961 return false;
2962 else
2963 break;
Bill Buzbee12ba0152009-09-03 14:03:09 -07002964 case INLINE_STRING_INDEXOF_I:
Bill Buzbeefd023aa2009-11-02 09:23:49 -08002965 if (genInlinedIndexOf(cUnit, mir, true /* I */))
2966 return false;
2967 else
2968 break;
Bill Buzbee12ba0152009-09-03 14:03:09 -07002969 case INLINE_STRING_INDEXOF_II:
Bill Buzbeefd023aa2009-11-02 09:23:49 -08002970 if (genInlinedIndexOf(cUnit, mir, false /* I */))
2971 return false;
2972 else
2973 break;
2974 case INLINE_STRING_EQUALS:
2975 case INLINE_MATH_COS:
2976 case INLINE_MATH_SIN:
2977 break; /* Handle with C routine */
Bill Buzbee50a6bf22009-07-08 13:08:04 -07002978 default:
2979 dvmAbort();
Ben Chengba4fc8b2009-06-01 13:00:29 -07002980 }
Bill Buzbeec6f10662010-02-09 11:16:15 -08002981 dvmCompilerFlushAllRegs(cUnit); /* Everything to home location */
2982 dvmCompilerColbberCallRegs(cUnit);
2983 dvmCompilerClobber(cUnit, r4PC);
2984 dvmCompilerClobber(cUnit, r7);
Bill Buzbee1465db52009-09-23 17:17:35 -07002985 opRegRegImm(cUnit, kOpAdd, r4PC, rGLUE, offset);
2986 opImm(cUnit, kOpPush, (1<<r4PC) | (1<<r7));
Ben Chengba4fc8b2009-06-01 13:00:29 -07002987 loadConstant(cUnit, r4PC, (int)inLineTable[operation].func);
Bill Buzbee1465db52009-09-23 17:17:35 -07002988 genExportPC(cUnit, mir);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002989 for (i=0; i < dInsn->vA; i++) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08002990 loadValueDirect(cUnit, dvmCompilerGetSrc(cUnit, mir, i), i);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002991 }
Bill Buzbee1465db52009-09-23 17:17:35 -07002992 opReg(cUnit, kOpBlx, r4PC);
2993 opRegImm(cUnit, kOpAdd, r13, 8);
Bill Buzbeece46c942009-11-20 15:41:34 -08002994 opRegImm(cUnit, kOpCmp, r0, 0); /* NULL? */
2995 ArmLIR *branchOver = opCondBranch(cUnit, kArmCondNe);
2996 loadConstant(cUnit, r0,
2997 (int) (cUnit->method->insns + mir->offset));
2998 genDispatchToHandler(cUnit, TEMPLATE_THROW_EXCEPTION_COMMON);
2999 ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel);
3000 target->defMask = ENCODE_ALL;
3001 branchOver->generic.target = (LIR *) target;
Ben Chengba4fc8b2009-06-01 13:00:29 -07003002 break;
3003 }
3004 default:
3005 return true;
3006 }
3007 return false;
3008}
3009
3010static bool handleFmt51l(CompilationUnit *cUnit, MIR *mir)
3011{
Bill Buzbee1465db52009-09-23 17:17:35 -07003012 //TUNING: We're using core regs here - not optimal when target is a double
Bill Buzbeec6f10662010-02-09 11:16:15 -08003013 RegLocation rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
3014 RegLocation rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07003015 loadConstantValue(cUnit, rlResult.lowReg,
3016 mir->dalvikInsn.vB_wide & 0xFFFFFFFFUL);
3017 loadConstantValue(cUnit, rlResult.highReg,
3018 (mir->dalvikInsn.vB_wide>>32) & 0xFFFFFFFFUL);
3019 storeValueWide(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003020 return false;
3021}
3022
Ben Chengba4fc8b2009-06-01 13:00:29 -07003023/*
3024 * The following are special processing routines that handle transfer of
3025 * controls between compiled code and the interpreter. Certain VM states like
3026 * Dalvik PC and special-purpose registers are reconstructed here.
3027 */
3028
Ben Cheng1efc9c52009-06-08 18:25:27 -07003029/* Chaining cell for code that may need warmup. */
3030static void handleNormalChainingCell(CompilationUnit *cUnit,
3031 unsigned int offset)
Ben Chengba4fc8b2009-06-01 13:00:29 -07003032{
Bill Buzbee270c1d62009-08-13 16:58:07 -07003033 loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
3034 jitToInterpEntries.dvmJitToInterpNormal), r0);
Bill Buzbee1465db52009-09-23 17:17:35 -07003035 opReg(cUnit, kOpBlx, r0);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003036 addWordData(cUnit, (int) (cUnit->method->insns + offset), true);
3037}
3038
3039/*
Ben Cheng1efc9c52009-06-08 18:25:27 -07003040 * Chaining cell for instructions that immediately following already translated
3041 * code.
Ben Chengba4fc8b2009-06-01 13:00:29 -07003042 */
Ben Cheng1efc9c52009-06-08 18:25:27 -07003043static void handleHotChainingCell(CompilationUnit *cUnit,
3044 unsigned int offset)
Ben Chengba4fc8b2009-06-01 13:00:29 -07003045{
Bill Buzbee270c1d62009-08-13 16:58:07 -07003046 loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
3047 jitToInterpEntries.dvmJitToTraceSelect), r0);
Bill Buzbee1465db52009-09-23 17:17:35 -07003048 opReg(cUnit, kOpBlx, r0);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003049 addWordData(cUnit, (int) (cUnit->method->insns + offset), true);
3050}
3051
Bill Buzbee9c4b7c82009-09-10 10:10:38 -07003052#if defined(WITH_SELF_VERIFICATION) || defined(WITH_JIT_TUNING)
Jeff Hao97319a82009-08-12 16:57:15 -07003053/* Chaining cell for branches that branch back into the same basic block */
3054static void handleBackwardBranchChainingCell(CompilationUnit *cUnit,
3055 unsigned int offset)
3056{
Bill Buzbee9c4b7c82009-09-10 10:10:38 -07003057#if defined(WITH_SELF_VERIFICATION)
Bill Buzbee1465db52009-09-23 17:17:35 -07003058 newLIR3(cUnit, kThumbLdrRRI5, r0, rGLUE,
Jeff Hao97319a82009-08-12 16:57:15 -07003059 offsetof(InterpState, jitToInterpEntries.dvmJitToBackwardBranch) >> 2);
Bill Buzbee9c4b7c82009-09-10 10:10:38 -07003060#else
Bill Buzbee1465db52009-09-23 17:17:35 -07003061 newLIR3(cUnit, kThumbLdrRRI5, r0, rGLUE,
Bill Buzbee9c4b7c82009-09-10 10:10:38 -07003062 offsetof(InterpState, jitToInterpEntries.dvmJitToInterpNormal) >> 2);
3063#endif
Bill Buzbee1465db52009-09-23 17:17:35 -07003064 newLIR1(cUnit, kThumbBlxR, r0);
Jeff Hao97319a82009-08-12 16:57:15 -07003065 addWordData(cUnit, (int) (cUnit->method->insns + offset), true);
3066}
3067
3068#endif
Ben Chengba4fc8b2009-06-01 13:00:29 -07003069/* Chaining cell for monomorphic method invocations. */
Ben Cheng38329f52009-07-07 14:19:20 -07003070static void handleInvokeSingletonChainingCell(CompilationUnit *cUnit,
3071 const Method *callee)
Ben Chengba4fc8b2009-06-01 13:00:29 -07003072{
Bill Buzbee270c1d62009-08-13 16:58:07 -07003073 loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
3074 jitToInterpEntries.dvmJitToTraceSelect), r0);
Bill Buzbee1465db52009-09-23 17:17:35 -07003075 opReg(cUnit, kOpBlx, r0);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003076 addWordData(cUnit, (int) (callee->insns), true);
3077}
3078
Ben Cheng38329f52009-07-07 14:19:20 -07003079/* Chaining cell for monomorphic method invocations. */
3080static void handleInvokePredictedChainingCell(CompilationUnit *cUnit)
3081{
3082
3083 /* Should not be executed in the initial state */
3084 addWordData(cUnit, PREDICTED_CHAIN_BX_PAIR_INIT, true);
3085 /* To be filled: class */
3086 addWordData(cUnit, PREDICTED_CHAIN_CLAZZ_INIT, true);
3087 /* To be filled: method */
3088 addWordData(cUnit, PREDICTED_CHAIN_METHOD_INIT, true);
3089 /*
3090 * Rechain count. The initial value of 0 here will trigger chaining upon
3091 * the first invocation of this callsite.
3092 */
3093 addWordData(cUnit, PREDICTED_CHAIN_COUNTER_INIT, true);
3094}
3095
Ben Chengba4fc8b2009-06-01 13:00:29 -07003096/* Load the Dalvik PC into r0 and jump to the specified target */
3097static void handlePCReconstruction(CompilationUnit *cUnit,
Bill Buzbee89efc3d2009-07-28 11:22:22 -07003098 ArmLIR *targetLabel)
Ben Chengba4fc8b2009-06-01 13:00:29 -07003099{
Bill Buzbee89efc3d2009-07-28 11:22:22 -07003100 ArmLIR **pcrLabel =
3101 (ArmLIR **) cUnit->pcReconstructionList.elemList;
Ben Chengba4fc8b2009-06-01 13:00:29 -07003102 int numElems = cUnit->pcReconstructionList.numUsed;
3103 int i;
3104 for (i = 0; i < numElems; i++) {
3105 dvmCompilerAppendLIR(cUnit, (LIR *) pcrLabel[i]);
3106 /* r0 = dalvik PC */
3107 loadConstant(cUnit, r0, pcrLabel[i]->operands[0]);
3108 genUnconditionalBranch(cUnit, targetLabel);
3109 }
3110}
3111
Bill Buzbee1465db52009-09-23 17:17:35 -07003112static char *extendedMIROpNames[kMirOpLast - kMirOpFirst] = {
3113 "kMirOpPhi",
3114 "kMirOpNullNRangeUpCheck",
3115 "kMirOpNullNRangeDownCheck",
3116 "kMirOpLowerBound",
3117 "kMirOpPunt",
Ben Cheng4238ec22009-08-24 16:32:22 -07003118};
3119
3120/*
3121 * vA = arrayReg;
3122 * vB = idxReg;
3123 * vC = endConditionReg;
3124 * arg[0] = maxC
3125 * arg[1] = minC
3126 * arg[2] = loopBranchConditionCode
3127 */
3128static void genHoistedChecksForCountUpLoop(CompilationUnit *cUnit, MIR *mir)
3129{
Bill Buzbee1465db52009-09-23 17:17:35 -07003130 /*
3131 * NOTE: these synthesized blocks don't have ssa names assigned
3132 * for Dalvik registers. However, because they dominate the following
3133 * blocks we can simply use the Dalvik name w/ subscript 0 as the
3134 * ssa name.
3135 */
Ben Cheng4238ec22009-08-24 16:32:22 -07003136 DecodedInstruction *dInsn = &mir->dalvikInsn;
3137 const int lenOffset = offsetof(ArrayObject, length);
Ben Cheng4238ec22009-08-24 16:32:22 -07003138 const int maxC = dInsn->arg[0];
3139 const int minC = dInsn->arg[1];
Bill Buzbee1465db52009-09-23 17:17:35 -07003140 int regLength;
3141 RegLocation rlArray = cUnit->regLocation[mir->dalvikInsn.vA];
3142 RegLocation rlIdxEnd = cUnit->regLocation[mir->dalvikInsn.vC];
Ben Cheng4238ec22009-08-24 16:32:22 -07003143
3144 /* regArray <- arrayRef */
Bill Buzbee1465db52009-09-23 17:17:35 -07003145 rlArray = loadValue(cUnit, rlArray, kCoreReg);
3146 rlIdxEnd = loadValue(cUnit, rlIdxEnd, kCoreReg);
3147 genRegImmCheck(cUnit, kArmCondEq, rlArray.lowReg, 0, 0,
Ben Cheng4238ec22009-08-24 16:32:22 -07003148 (ArmLIR *) cUnit->loopAnalysis->branchToPCR);
3149
3150 /* regLength <- len(arrayRef) */
Bill Buzbeec6f10662010-02-09 11:16:15 -08003151 regLength = dvmCompilerAllocTemp(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07003152 loadWordDisp(cUnit, rlArray.lowReg, lenOffset, regLength);
Ben Cheng4238ec22009-08-24 16:32:22 -07003153
3154 int delta = maxC;
3155 /*
3156 * If the loop end condition is ">=" instead of ">", then the largest value
3157 * of the index is "endCondition - 1".
3158 */
3159 if (dInsn->arg[2] == OP_IF_GE) {
3160 delta--;
3161 }
3162
3163 if (delta) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08003164 int tReg = dvmCompilerAllocTemp(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07003165 opRegRegImm(cUnit, kOpAdd, tReg, rlIdxEnd.lowReg, delta);
3166 rlIdxEnd.lowReg = tReg;
Bill Buzbeec6f10662010-02-09 11:16:15 -08003167 dvmCompilerFreeTemp(cUnit, tReg);
Ben Cheng4238ec22009-08-24 16:32:22 -07003168 }
3169 /* Punt if "regIdxEnd < len(Array)" is false */
Bill Buzbee1465db52009-09-23 17:17:35 -07003170 genRegRegCheck(cUnit, kArmCondGe, rlIdxEnd.lowReg, regLength, 0,
Ben Cheng0fd31e42009-09-03 14:40:16 -07003171 (ArmLIR *) cUnit->loopAnalysis->branchToPCR);
Ben Cheng4238ec22009-08-24 16:32:22 -07003172}
3173
3174/*
3175 * vA = arrayReg;
3176 * vB = idxReg;
3177 * vC = endConditionReg;
3178 * arg[0] = maxC
3179 * arg[1] = minC
3180 * arg[2] = loopBranchConditionCode
3181 */
3182static void genHoistedChecksForCountDownLoop(CompilationUnit *cUnit, MIR *mir)
3183{
3184 DecodedInstruction *dInsn = &mir->dalvikInsn;
3185 const int lenOffset = offsetof(ArrayObject, length);
Bill Buzbeec6f10662010-02-09 11:16:15 -08003186 const int regLength = dvmCompilerAllocTemp(cUnit);
Ben Cheng4238ec22009-08-24 16:32:22 -07003187 const int maxC = dInsn->arg[0];
3188 const int minC = dInsn->arg[1];
Bill Buzbee1465db52009-09-23 17:17:35 -07003189 RegLocation rlArray = cUnit->regLocation[mir->dalvikInsn.vA];
3190 RegLocation rlIdxInit = cUnit->regLocation[mir->dalvikInsn.vB];
Ben Cheng4238ec22009-08-24 16:32:22 -07003191
3192 /* regArray <- arrayRef */
Bill Buzbee1465db52009-09-23 17:17:35 -07003193 rlArray = loadValue(cUnit, rlArray, kCoreReg);
3194 rlIdxInit = loadValue(cUnit, rlIdxInit, kCoreReg);
3195 genRegImmCheck(cUnit, kArmCondEq, rlArray.lowReg, 0, 0,
Ben Cheng4238ec22009-08-24 16:32:22 -07003196 (ArmLIR *) cUnit->loopAnalysis->branchToPCR);
3197
3198 /* regLength <- len(arrayRef) */
Bill Buzbee1465db52009-09-23 17:17:35 -07003199 loadWordDisp(cUnit, rlArray.lowReg, lenOffset, regLength);
Ben Cheng4238ec22009-08-24 16:32:22 -07003200
3201 if (maxC) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08003202 int tReg = dvmCompilerAllocTemp(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07003203 opRegRegImm(cUnit, kOpAdd, tReg, rlIdxInit.lowReg, maxC);
3204 rlIdxInit.lowReg = tReg;
Bill Buzbeec6f10662010-02-09 11:16:15 -08003205 dvmCompilerFreeTemp(cUnit, tReg);
Ben Cheng4238ec22009-08-24 16:32:22 -07003206 }
3207
3208 /* Punt if "regIdxInit < len(Array)" is false */
Bill Buzbee1465db52009-09-23 17:17:35 -07003209 genRegRegCheck(cUnit, kArmCondGe, rlIdxInit.lowReg, regLength, 0,
Ben Cheng0fd31e42009-09-03 14:40:16 -07003210 (ArmLIR *) cUnit->loopAnalysis->branchToPCR);
Ben Cheng4238ec22009-08-24 16:32:22 -07003211}
3212
3213/*
3214 * vA = idxReg;
3215 * vB = minC;
3216 */
3217static void genHoistedLowerBoundCheck(CompilationUnit *cUnit, MIR *mir)
3218{
3219 DecodedInstruction *dInsn = &mir->dalvikInsn;
Ben Cheng4238ec22009-08-24 16:32:22 -07003220 const int minC = dInsn->vB;
Bill Buzbee1465db52009-09-23 17:17:35 -07003221 RegLocation rlIdx = cUnit->regLocation[mir->dalvikInsn.vA];
Ben Cheng4238ec22009-08-24 16:32:22 -07003222
3223 /* regIdx <- initial index value */
Bill Buzbee1465db52009-09-23 17:17:35 -07003224 rlIdx = loadValue(cUnit, rlIdx, kCoreReg);
Ben Cheng4238ec22009-08-24 16:32:22 -07003225
3226 /* Punt if "regIdxInit + minC >= 0" is false */
Bill Buzbee1465db52009-09-23 17:17:35 -07003227 genRegImmCheck(cUnit, kArmCondLt, rlIdx.lowReg, -minC, 0,
Ben Cheng4238ec22009-08-24 16:32:22 -07003228 (ArmLIR *) cUnit->loopAnalysis->branchToPCR);
3229}
3230
3231/* Extended MIR instructions like PHI */
3232static void handleExtendedMIR(CompilationUnit *cUnit, MIR *mir)
3233{
Bill Buzbee1465db52009-09-23 17:17:35 -07003234 int opOffset = mir->dalvikInsn.opCode - kMirOpFirst;
Ben Cheng4238ec22009-08-24 16:32:22 -07003235 char *msg = dvmCompilerNew(strlen(extendedMIROpNames[opOffset]) + 1,
3236 false);
3237 strcpy(msg, extendedMIROpNames[opOffset]);
Bill Buzbee1465db52009-09-23 17:17:35 -07003238 newLIR1(cUnit, kArmPseudoExtended, (int) msg);
Ben Cheng4238ec22009-08-24 16:32:22 -07003239
3240 switch (mir->dalvikInsn.opCode) {
Bill Buzbee1465db52009-09-23 17:17:35 -07003241 case kMirOpPhi: {
Ben Cheng4238ec22009-08-24 16:32:22 -07003242 char *ssaString = dvmCompilerGetSSAString(cUnit, mir->ssaRep);
Bill Buzbee1465db52009-09-23 17:17:35 -07003243 newLIR1(cUnit, kArmPseudoSSARep, (int) ssaString);
Ben Cheng4238ec22009-08-24 16:32:22 -07003244 break;
3245 }
Bill Buzbee1465db52009-09-23 17:17:35 -07003246 case kMirOpNullNRangeUpCheck: {
Ben Cheng4238ec22009-08-24 16:32:22 -07003247 genHoistedChecksForCountUpLoop(cUnit, mir);
3248 break;
3249 }
Bill Buzbee1465db52009-09-23 17:17:35 -07003250 case kMirOpNullNRangeDownCheck: {
Ben Cheng4238ec22009-08-24 16:32:22 -07003251 genHoistedChecksForCountDownLoop(cUnit, mir);
3252 break;
3253 }
Bill Buzbee1465db52009-09-23 17:17:35 -07003254 case kMirOpLowerBound: {
Ben Cheng4238ec22009-08-24 16:32:22 -07003255 genHoistedLowerBoundCheck(cUnit, mir);
3256 break;
3257 }
Bill Buzbee1465db52009-09-23 17:17:35 -07003258 case kMirOpPunt: {
Ben Cheng4238ec22009-08-24 16:32:22 -07003259 genUnconditionalBranch(cUnit,
3260 (ArmLIR *) cUnit->loopAnalysis->branchToPCR);
3261 break;
3262 }
3263 default:
3264 break;
3265 }
3266}
3267
3268/*
3269 * Create a PC-reconstruction cell for the starting offset of this trace.
3270 * Since the PCR cell is placed near the end of the compiled code which is
3271 * usually out of range for a conditional branch, we put two branches (one
3272 * branch over to the loop body and one layover branch to the actual PCR) at the
3273 * end of the entry block.
3274 */
3275static void setupLoopEntryBlock(CompilationUnit *cUnit, BasicBlock *entry,
3276 ArmLIR *bodyLabel)
3277{
3278 /* Set up the place holder to reconstruct this Dalvik PC */
3279 ArmLIR *pcrLabel = dvmCompilerNew(sizeof(ArmLIR), true);
Bill Buzbee1465db52009-09-23 17:17:35 -07003280 pcrLabel->opCode = ARM_PSEUDO_kPCReconstruction_CELL;
Ben Cheng4238ec22009-08-24 16:32:22 -07003281 pcrLabel->operands[0] =
3282 (int) (cUnit->method->insns + entry->startOffset);
3283 pcrLabel->operands[1] = entry->startOffset;
3284 /* Insert the place holder to the growable list */
3285 dvmInsertGrowableList(&cUnit->pcReconstructionList, pcrLabel);
3286
3287 /*
3288 * Next, create two branches - one branch over to the loop body and the
3289 * other branch to the PCR cell to punt.
3290 */
3291 ArmLIR *branchToBody = dvmCompilerNew(sizeof(ArmLIR), true);
Bill Buzbee1465db52009-09-23 17:17:35 -07003292 branchToBody->opCode = kThumbBUncond;
Ben Cheng4238ec22009-08-24 16:32:22 -07003293 branchToBody->generic.target = (LIR *) bodyLabel;
Ben Chengdcf3e5d2009-09-11 13:42:05 -07003294 setupResourceMasks(branchToBody);
Ben Cheng4238ec22009-08-24 16:32:22 -07003295 cUnit->loopAnalysis->branchToBody = (LIR *) branchToBody;
3296
3297 ArmLIR *branchToPCR = dvmCompilerNew(sizeof(ArmLIR), true);
Bill Buzbee1465db52009-09-23 17:17:35 -07003298 branchToPCR->opCode = kThumbBUncond;
Ben Cheng4238ec22009-08-24 16:32:22 -07003299 branchToPCR->generic.target = (LIR *) pcrLabel;
Ben Chengdcf3e5d2009-09-11 13:42:05 -07003300 setupResourceMasks(branchToPCR);
Ben Cheng4238ec22009-08-24 16:32:22 -07003301 cUnit->loopAnalysis->branchToPCR = (LIR *) branchToPCR;
3302}
3303
Ben Chengba4fc8b2009-06-01 13:00:29 -07003304void dvmCompilerMIR2LIR(CompilationUnit *cUnit)
3305{
3306 /* Used to hold the labels of each block */
Bill Buzbee89efc3d2009-07-28 11:22:22 -07003307 ArmLIR *labelList =
3308 dvmCompilerNew(sizeof(ArmLIR) * cUnit->numBlocks, true);
Ben Chengcec26f62010-01-15 15:29:33 -08003309 GrowableList chainingListByType[kChainingCellGap];
Ben Chengba4fc8b2009-06-01 13:00:29 -07003310 int i;
3311
3312 /*
Ben Cheng38329f52009-07-07 14:19:20 -07003313 * Initialize various types chaining lists.
Ben Chengba4fc8b2009-06-01 13:00:29 -07003314 */
Ben Chengcec26f62010-01-15 15:29:33 -08003315 for (i = 0; i < kChainingCellGap; i++) {
Ben Chengba4fc8b2009-06-01 13:00:29 -07003316 dvmInitGrowableList(&chainingListByType[i], 2);
3317 }
3318
3319 BasicBlock **blockList = cUnit->blockList;
3320
Bill Buzbee6e963e12009-06-17 16:56:19 -07003321 if (cUnit->executionCount) {
3322 /*
3323 * Reserve 6 bytes at the beginning of the trace
3324 * +----------------------------+
3325 * | execution count (4 bytes) |
3326 * +----------------------------+
3327 * | chain cell offset (2 bytes)|
3328 * +----------------------------+
3329 * ...and then code to increment the execution
3330 * count:
3331 * mov r0, pc @ move adr of "mov r0,pc" + 4 to r0
3332 * sub r0, #10 @ back up to addr of executionCount
3333 * ldr r1, [r0]
3334 * add r1, #1
3335 * str r1, [r0]
3336 */
Bill Buzbee1465db52009-09-23 17:17:35 -07003337 newLIR1(cUnit, kArm16BitData, 0);
3338 newLIR1(cUnit, kArm16BitData, 0);
Ben Chengcc6600c2009-06-22 14:45:16 -07003339 cUnit->chainCellOffsetLIR =
Bill Buzbee1465db52009-09-23 17:17:35 -07003340 (LIR *) newLIR1(cUnit, kArm16BitData, CHAIN_CELL_OFFSET_TAG);
Bill Buzbee6e963e12009-06-17 16:56:19 -07003341 cUnit->headerSize = 6;
Bill Buzbee270c1d62009-08-13 16:58:07 -07003342 /* Thumb instruction used directly here to ensure correct size */
Bill Buzbee1465db52009-09-23 17:17:35 -07003343 newLIR2(cUnit, kThumbMovRR_H2L, r0, rpc);
3344 newLIR2(cUnit, kThumbSubRI8, r0, 10);
3345 newLIR3(cUnit, kThumbLdrRRI5, r1, r0, 0);
3346 newLIR2(cUnit, kThumbAddRI8, r1, 1);
3347 newLIR3(cUnit, kThumbStrRRI5, r1, r0, 0);
Bill Buzbee6e963e12009-06-17 16:56:19 -07003348 } else {
3349 /* Just reserve 2 bytes for the chain cell offset */
Ben Chengcc6600c2009-06-22 14:45:16 -07003350 cUnit->chainCellOffsetLIR =
Bill Buzbee1465db52009-09-23 17:17:35 -07003351 (LIR *) newLIR1(cUnit, kArm16BitData, CHAIN_CELL_OFFSET_TAG);
Bill Buzbee6e963e12009-06-17 16:56:19 -07003352 cUnit->headerSize = 2;
3353 }
Ben Cheng1efc9c52009-06-08 18:25:27 -07003354
Ben Chengba4fc8b2009-06-01 13:00:29 -07003355 /* Handle the content in each basic block */
3356 for (i = 0; i < cUnit->numBlocks; i++) {
3357 blockList[i]->visited = true;
3358 MIR *mir;
3359
3360 labelList[i].operands[0] = blockList[i]->startOffset;
3361
Ben Chengcec26f62010-01-15 15:29:33 -08003362 if (blockList[i]->blockType >= kChainingCellGap) {
Ben Chengba4fc8b2009-06-01 13:00:29 -07003363 /*
3364 * Append the label pseudo LIR first. Chaining cells will be handled
3365 * separately afterwards.
3366 */
3367 dvmCompilerAppendLIR(cUnit, (LIR *) &labelList[i]);
3368 }
3369
Bill Buzbee1465db52009-09-23 17:17:35 -07003370 if (blockList[i]->blockType == kEntryBlock) {
3371 labelList[i].opCode = ARM_PSEUDO_kEntryBlock;
Ben Cheng4238ec22009-08-24 16:32:22 -07003372 if (blockList[i]->firstMIRInsn == NULL) {
3373 continue;
3374 } else {
3375 setupLoopEntryBlock(cUnit, blockList[i],
3376 &labelList[blockList[i]->fallThrough->id]);
3377 }
Bill Buzbee1465db52009-09-23 17:17:35 -07003378 } else if (blockList[i]->blockType == kExitBlock) {
3379 labelList[i].opCode = ARM_PSEUDO_kExitBlock;
Ben Cheng4238ec22009-08-24 16:32:22 -07003380 goto gen_fallthrough;
Bill Buzbee1465db52009-09-23 17:17:35 -07003381 } else if (blockList[i]->blockType == kDalvikByteCode) {
3382 labelList[i].opCode = kArmPseudoNormalBlockLabel;
Ben Chenge9695e52009-06-16 16:11:47 -07003383 /* Reset the register state */
Bill Buzbeec6f10662010-02-09 11:16:15 -08003384 dvmCompilerResetRegPool(cUnit);
3385 dvmCompilerClobberAllRegs(cUnit);
3386 dvmCompilerResetNullCheck(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003387 } else {
3388 switch (blockList[i]->blockType) {
Bill Buzbee1465db52009-09-23 17:17:35 -07003389 case kChainingCellNormal:
3390 labelList[i].opCode = ARM_PSEUDO_kChainingCellNormal;
Ben Chengba4fc8b2009-06-01 13:00:29 -07003391 /* handle the codegen later */
3392 dvmInsertGrowableList(
Bill Buzbee1465db52009-09-23 17:17:35 -07003393 &chainingListByType[kChainingCellNormal], (void *) i);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003394 break;
Bill Buzbee1465db52009-09-23 17:17:35 -07003395 case kChainingCellInvokeSingleton:
Ben Cheng38329f52009-07-07 14:19:20 -07003396 labelList[i].opCode =
Bill Buzbee1465db52009-09-23 17:17:35 -07003397 ARM_PSEUDO_kChainingCellInvokeSingleton;
Ben Chengba4fc8b2009-06-01 13:00:29 -07003398 labelList[i].operands[0] =
3399 (int) blockList[i]->containingMethod;
3400 /* handle the codegen later */
3401 dvmInsertGrowableList(
Bill Buzbee1465db52009-09-23 17:17:35 -07003402 &chainingListByType[kChainingCellInvokeSingleton],
Ben Cheng38329f52009-07-07 14:19:20 -07003403 (void *) i);
3404 break;
Bill Buzbee1465db52009-09-23 17:17:35 -07003405 case kChainingCellInvokePredicted:
Ben Cheng38329f52009-07-07 14:19:20 -07003406 labelList[i].opCode =
Bill Buzbee1465db52009-09-23 17:17:35 -07003407 ARM_PSEUDO_kChainingCellInvokePredicted;
Ben Cheng38329f52009-07-07 14:19:20 -07003408 /* handle the codegen later */
3409 dvmInsertGrowableList(
Bill Buzbee1465db52009-09-23 17:17:35 -07003410 &chainingListByType[kChainingCellInvokePredicted],
Ben Cheng38329f52009-07-07 14:19:20 -07003411 (void *) i);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003412 break;
Bill Buzbee1465db52009-09-23 17:17:35 -07003413 case kChainingCellHot:
Ben Chengba4fc8b2009-06-01 13:00:29 -07003414 labelList[i].opCode =
Bill Buzbee1465db52009-09-23 17:17:35 -07003415 ARM_PSEUDO_kChainingCellHot;
Ben Chengba4fc8b2009-06-01 13:00:29 -07003416 /* handle the codegen later */
3417 dvmInsertGrowableList(
Bill Buzbee1465db52009-09-23 17:17:35 -07003418 &chainingListByType[kChainingCellHot],
Ben Chengba4fc8b2009-06-01 13:00:29 -07003419 (void *) i);
3420 break;
Bill Buzbee1465db52009-09-23 17:17:35 -07003421 case kPCReconstruction:
Ben Chengba4fc8b2009-06-01 13:00:29 -07003422 /* Make sure exception handling block is next */
3423 labelList[i].opCode =
Bill Buzbee1465db52009-09-23 17:17:35 -07003424 ARM_PSEUDO_kPCReconstruction_BLOCK_LABEL;
Ben Chengba4fc8b2009-06-01 13:00:29 -07003425 assert (i == cUnit->numBlocks - 2);
3426 handlePCReconstruction(cUnit, &labelList[i+1]);
3427 break;
Bill Buzbee1465db52009-09-23 17:17:35 -07003428 case kExceptionHandling:
3429 labelList[i].opCode = kArmPseudoEHBlockLabel;
Ben Chengba4fc8b2009-06-01 13:00:29 -07003430 if (cUnit->pcReconstructionList.numUsed) {
Bill Buzbee270c1d62009-08-13 16:58:07 -07003431 loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
3432 jitToInterpEntries.dvmJitToInterpPunt),
3433 r1);
Bill Buzbee1465db52009-09-23 17:17:35 -07003434 opReg(cUnit, kOpBlx, r1);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003435 }
3436 break;
Bill Buzbee9c4b7c82009-09-10 10:10:38 -07003437#if defined(WITH_SELF_VERIFICATION) || defined(WITH_JIT_TUNING)
Bill Buzbee1465db52009-09-23 17:17:35 -07003438 case kChainingCellBackwardBranch:
Jeff Hao97319a82009-08-12 16:57:15 -07003439 labelList[i].opCode =
Bill Buzbee1465db52009-09-23 17:17:35 -07003440 ARM_PSEUDO_kChainingCellBackwardBranch;
Jeff Hao97319a82009-08-12 16:57:15 -07003441 /* handle the codegen later */
3442 dvmInsertGrowableList(
Bill Buzbee1465db52009-09-23 17:17:35 -07003443 &chainingListByType[kChainingCellBackwardBranch],
Jeff Hao97319a82009-08-12 16:57:15 -07003444 (void *) i);
3445 break;
3446#endif
Ben Chengba4fc8b2009-06-01 13:00:29 -07003447 default:
3448 break;
3449 }
3450 continue;
3451 }
Ben Chenge9695e52009-06-16 16:11:47 -07003452
Bill Buzbee89efc3d2009-07-28 11:22:22 -07003453 ArmLIR *headLIR = NULL;
Ben Chenge9695e52009-06-16 16:11:47 -07003454
Ben Chengba4fc8b2009-06-01 13:00:29 -07003455 for (mir = blockList[i]->firstMIRInsn; mir; mir = mir->next) {
Bill Buzbee1465db52009-09-23 17:17:35 -07003456
Bill Buzbeec6f10662010-02-09 11:16:15 -08003457 dvmCompilerResetRegPool(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07003458 if (gDvmJit.disableOpt & (1 << kTrackLiveTemps)) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08003459 dvmCompilerClobberAllRegs(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07003460 }
3461
3462 if (gDvmJit.disableOpt & (1 << kSuppressLoads)) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08003463 dvmCompilerResetDefTracking(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07003464 }
3465
3466 if (mir->dalvikInsn.opCode >= kMirOpFirst) {
Ben Cheng4238ec22009-08-24 16:32:22 -07003467 handleExtendedMIR(cUnit, mir);
3468 continue;
3469 }
3470
Bill Buzbee1465db52009-09-23 17:17:35 -07003471
Ben Chengba4fc8b2009-06-01 13:00:29 -07003472 OpCode dalvikOpCode = mir->dalvikInsn.opCode;
3473 InstructionFormat dalvikFormat =
3474 dexGetInstrFormat(gDvm.instrFormat, dalvikOpCode);
Bill Buzbee89efc3d2009-07-28 11:22:22 -07003475 ArmLIR *boundaryLIR =
Bill Buzbee1465db52009-09-23 17:17:35 -07003476 newLIR2(cUnit, ARM_PSEUDO_kDalvikByteCode_BOUNDARY,
Ben Chengccd6c012009-10-15 14:52:45 -07003477 mir->offset,
3478 (int) dvmCompilerGetDalvikDisassembly(&mir->dalvikInsn)
3479 );
Ben Cheng4238ec22009-08-24 16:32:22 -07003480 if (mir->ssaRep) {
3481 char *ssaString = dvmCompilerGetSSAString(cUnit, mir->ssaRep);
Bill Buzbee1465db52009-09-23 17:17:35 -07003482 newLIR1(cUnit, kArmPseudoSSARep, (int) ssaString);
Ben Cheng4238ec22009-08-24 16:32:22 -07003483 }
3484
Ben Chenge9695e52009-06-16 16:11:47 -07003485 /* Remember the first LIR for this block */
3486 if (headLIR == NULL) {
3487 headLIR = boundaryLIR;
Ben Chengd7d426a2009-09-22 11:23:36 -07003488 /* Set the first boundaryLIR as a scheduling barrier */
3489 headLIR->defMask = ENCODE_ALL;
Ben Chenge9695e52009-06-16 16:11:47 -07003490 }
Ben Cheng4238ec22009-08-24 16:32:22 -07003491
Ben Chengba4fc8b2009-06-01 13:00:29 -07003492 bool notHandled;
3493 /*
3494 * Debugging: screen the opcode first to see if it is in the
3495 * do[-not]-compile list
3496 */
3497 bool singleStepMe =
3498 gDvmJit.includeSelectedOp !=
3499 ((gDvmJit.opList[dalvikOpCode >> 3] &
3500 (1 << (dalvikOpCode & 0x7))) !=
3501 0);
3502 if (singleStepMe || cUnit->allSingleStep) {
3503 notHandled = false;
3504 genInterpSingleStep(cUnit, mir);
3505 } else {
3506 opcodeCoverage[dalvikOpCode]++;
3507 switch (dalvikFormat) {
3508 case kFmt10t:
3509 case kFmt20t:
3510 case kFmt30t:
3511 notHandled = handleFmt10t_Fmt20t_Fmt30t(cUnit,
3512 mir, blockList[i], labelList);
3513 break;
3514 case kFmt10x:
3515 notHandled = handleFmt10x(cUnit, mir);
3516 break;
3517 case kFmt11n:
3518 case kFmt31i:
3519 notHandled = handleFmt11n_Fmt31i(cUnit, mir);
3520 break;
3521 case kFmt11x:
3522 notHandled = handleFmt11x(cUnit, mir);
3523 break;
3524 case kFmt12x:
3525 notHandled = handleFmt12x(cUnit, mir);
3526 break;
3527 case kFmt20bc:
3528 notHandled = handleFmt20bc(cUnit, mir);
3529 break;
3530 case kFmt21c:
3531 case kFmt31c:
3532 notHandled = handleFmt21c_Fmt31c(cUnit, mir);
3533 break;
3534 case kFmt21h:
3535 notHandled = handleFmt21h(cUnit, mir);
3536 break;
3537 case kFmt21s:
3538 notHandled = handleFmt21s(cUnit, mir);
3539 break;
3540 case kFmt21t:
3541 notHandled = handleFmt21t(cUnit, mir, blockList[i],
3542 labelList);
3543 break;
3544 case kFmt22b:
3545 case kFmt22s:
3546 notHandled = handleFmt22b_Fmt22s(cUnit, mir);
3547 break;
3548 case kFmt22c:
3549 notHandled = handleFmt22c(cUnit, mir);
3550 break;
3551 case kFmt22cs:
3552 notHandled = handleFmt22cs(cUnit, mir);
3553 break;
3554 case kFmt22t:
3555 notHandled = handleFmt22t(cUnit, mir, blockList[i],
3556 labelList);
3557 break;
3558 case kFmt22x:
3559 case kFmt32x:
3560 notHandled = handleFmt22x_Fmt32x(cUnit, mir);
3561 break;
3562 case kFmt23x:
3563 notHandled = handleFmt23x(cUnit, mir);
3564 break;
3565 case kFmt31t:
3566 notHandled = handleFmt31t(cUnit, mir);
3567 break;
3568 case kFmt3rc:
3569 case kFmt35c:
3570 notHandled = handleFmt35c_3rc(cUnit, mir, blockList[i],
3571 labelList);
3572 break;
3573 case kFmt3rms:
3574 case kFmt35ms:
3575 notHandled = handleFmt35ms_3rms(cUnit, mir,blockList[i],
3576 labelList);
3577 break;
3578 case kFmt3inline:
Andy McFaddenb0a05412009-11-19 10:23:41 -08003579 case kFmt3rinline:
Bill Buzbeece46c942009-11-20 15:41:34 -08003580 notHandled = handleExecuteInline(cUnit, mir);
Andy McFaddenb0a05412009-11-19 10:23:41 -08003581 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07003582 case kFmt51l:
3583 notHandled = handleFmt51l(cUnit, mir);
3584 break;
3585 default:
3586 notHandled = true;
3587 break;
3588 }
3589 }
3590 if (notHandled) {
3591 LOGE("%#06x: Opcode 0x%x (%s) / Fmt %d not handled\n",
3592 mir->offset,
3593 dalvikOpCode, getOpcodeName(dalvikOpCode),
3594 dalvikFormat);
3595 dvmAbort();
3596 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07003597 }
3598 }
Ben Cheng4238ec22009-08-24 16:32:22 -07003599
Bill Buzbee1465db52009-09-23 17:17:35 -07003600 if (blockList[i]->blockType == kEntryBlock) {
Ben Cheng4238ec22009-08-24 16:32:22 -07003601 dvmCompilerAppendLIR(cUnit,
3602 (LIR *) cUnit->loopAnalysis->branchToBody);
3603 dvmCompilerAppendLIR(cUnit,
3604 (LIR *) cUnit->loopAnalysis->branchToPCR);
3605 }
3606
3607 if (headLIR) {
3608 /*
3609 * Eliminate redundant loads/stores and delay stores into later
3610 * slots
3611 */
3612 dvmCompilerApplyLocalOptimizations(cUnit, (LIR *) headLIR,
3613 cUnit->lastLIRInsn);
3614 }
3615
3616gen_fallthrough:
Ben Cheng1efc9c52009-06-08 18:25:27 -07003617 /*
3618 * Check if the block is terminated due to trace length constraint -
3619 * insert an unconditional branch to the chaining cell.
3620 */
3621 if (blockList[i]->needFallThroughBranch) {
3622 genUnconditionalBranch(cUnit,
3623 &labelList[blockList[i]->fallThrough->id]);
3624 }
3625
Ben Chengba4fc8b2009-06-01 13:00:29 -07003626 }
3627
Ben Chenge9695e52009-06-16 16:11:47 -07003628 /* Handle the chaining cells in predefined order */
Ben Chengcec26f62010-01-15 15:29:33 -08003629 for (i = 0; i < kChainingCellGap; i++) {
Ben Chengba4fc8b2009-06-01 13:00:29 -07003630 size_t j;
3631 int *blockIdList = (int *) chainingListByType[i].elemList;
3632
3633 cUnit->numChainingCells[i] = chainingListByType[i].numUsed;
3634
3635 /* No chaining cells of this type */
3636 if (cUnit->numChainingCells[i] == 0)
3637 continue;
3638
3639 /* Record the first LIR for a new type of chaining cell */
3640 cUnit->firstChainingLIR[i] = (LIR *) &labelList[blockIdList[0]];
3641
3642 for (j = 0; j < chainingListByType[i].numUsed; j++) {
3643 int blockId = blockIdList[j];
3644
3645 /* Align this chaining cell first */
Bill Buzbee1465db52009-09-23 17:17:35 -07003646 newLIR0(cUnit, kArmPseudoPseudoAlign4);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003647
3648 /* Insert the pseudo chaining instruction */
3649 dvmCompilerAppendLIR(cUnit, (LIR *) &labelList[blockId]);
3650
3651
3652 switch (blockList[blockId]->blockType) {
Bill Buzbee1465db52009-09-23 17:17:35 -07003653 case kChainingCellNormal:
Ben Cheng1efc9c52009-06-08 18:25:27 -07003654 handleNormalChainingCell(cUnit,
Ben Chengba4fc8b2009-06-01 13:00:29 -07003655 blockList[blockId]->startOffset);
3656 break;
Bill Buzbee1465db52009-09-23 17:17:35 -07003657 case kChainingCellInvokeSingleton:
Ben Cheng38329f52009-07-07 14:19:20 -07003658 handleInvokeSingletonChainingCell(cUnit,
Ben Chengba4fc8b2009-06-01 13:00:29 -07003659 blockList[blockId]->containingMethod);
3660 break;
Bill Buzbee1465db52009-09-23 17:17:35 -07003661 case kChainingCellInvokePredicted:
Ben Cheng38329f52009-07-07 14:19:20 -07003662 handleInvokePredictedChainingCell(cUnit);
3663 break;
Bill Buzbee1465db52009-09-23 17:17:35 -07003664 case kChainingCellHot:
Ben Cheng1efc9c52009-06-08 18:25:27 -07003665 handleHotChainingCell(cUnit,
Ben Chengba4fc8b2009-06-01 13:00:29 -07003666 blockList[blockId]->startOffset);
3667 break;
Bill Buzbee9c4b7c82009-09-10 10:10:38 -07003668#if defined(WITH_SELF_VERIFICATION) || defined(WITH_JIT_TUNING)
Bill Buzbee1465db52009-09-23 17:17:35 -07003669 case kChainingCellBackwardBranch:
Jeff Hao97319a82009-08-12 16:57:15 -07003670 handleBackwardBranchChainingCell(cUnit,
3671 blockList[blockId]->startOffset);
3672 break;
3673#endif
Ben Chengba4fc8b2009-06-01 13:00:29 -07003674 default:
Bill Buzbee1465db52009-09-23 17:17:35 -07003675 LOGE("Bad blocktype %d", blockList[blockId]->blockType);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003676 dvmAbort();
3677 break;
3678 }
3679 }
3680 }
Ben Chenge9695e52009-06-16 16:11:47 -07003681
Ben Chengcec26f62010-01-15 15:29:33 -08003682 /* Mark the bottom of chaining cells */
3683 cUnit->chainingCellBottom = (LIR *) newLIR0(cUnit, kArmChainingCellBottom);
3684
Ben Cheng6c10a972009-10-29 14:39:18 -07003685 /*
3686 * Generate the branch to the dvmJitToInterpNoChain entry point at the end
3687 * of all chaining cells for the overflow cases.
3688 */
3689 if (cUnit->switchOverflowPad) {
3690 loadConstant(cUnit, r0, (int) cUnit->switchOverflowPad);
3691 loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
3692 jitToInterpEntries.dvmJitToInterpNoChain), r2);
3693 opRegReg(cUnit, kOpAdd, r1, r1);
3694 opRegRegReg(cUnit, kOpAdd, r4PC, r0, r1);
3695#if defined(EXIT_STATS)
3696 loadConstant(cUnit, r0, kSwitchOverflow);
3697#endif
3698 opReg(cUnit, kOpBlx, r2);
3699 }
3700
Ben Chenge9695e52009-06-16 16:11:47 -07003701 dvmCompilerApplyGlobalOptimizations(cUnit);
jeffhao9e45c0b2010-02-03 10:24:05 -08003702
3703#if defined(WITH_SELF_VERIFICATION)
3704 selfVerificationBranchInsertPass(cUnit);
3705#endif
Ben Chengba4fc8b2009-06-01 13:00:29 -07003706}
3707
3708/* Accept the work and start compiling */
Bill Buzbee716f1202009-07-23 13:22:09 -07003709bool dvmCompilerDoWork(CompilerWorkOrder *work)
Ben Chengba4fc8b2009-06-01 13:00:29 -07003710{
Ben Chengccd6c012009-10-15 14:52:45 -07003711 bool res;
Ben Chengba4fc8b2009-06-01 13:00:29 -07003712
Ben Cheng6999d842010-01-26 16:46:15 -08003713 if (gDvmJit.codeCacheFull) {
Ben Chengccd6c012009-10-15 14:52:45 -07003714 return false;
3715 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07003716
Ben Chengccd6c012009-10-15 14:52:45 -07003717 switch (work->kind) {
3718 case kWorkOrderMethod:
3719 res = dvmCompileMethod(work->info, &work->result);
3720 break;
3721 case kWorkOrderTrace:
3722 /* Start compilation with maximally allowed trace length */
3723 res = dvmCompileTrace(work->info, JIT_MAX_TRACE_LEN, &work->result);
3724 break;
3725 case kWorkOrderTraceDebug: {
3726 bool oldPrintMe = gDvmJit.printMe;
3727 gDvmJit.printMe = true;
3728 /* Start compilation with maximally allowed trace length */
3729 res = dvmCompileTrace(work->info, JIT_MAX_TRACE_LEN, &work->result);
3730 gDvmJit.printMe = oldPrintMe;;
3731 break;
3732 }
3733 default:
3734 res = false;
3735 dvmAbort();
3736 }
3737 return res;
Ben Chengba4fc8b2009-06-01 13:00:29 -07003738}
3739
Ben Chengba4fc8b2009-06-01 13:00:29 -07003740/* Architectural-specific debugging helpers go here */
3741void dvmCompilerArchDump(void)
3742{
3743 /* Print compiled opcode in this VM instance */
3744 int i, start, streak;
3745 char buf[1024];
3746
3747 streak = i = 0;
3748 buf[0] = 0;
3749 while (opcodeCoverage[i] == 0 && i < 256) {
3750 i++;
3751 }
3752 if (i == 256) {
3753 return;
3754 }
3755 for (start = i++, streak = 1; i < 256; i++) {
3756 if (opcodeCoverage[i]) {
3757 streak++;
3758 } else {
3759 if (streak == 1) {
3760 sprintf(buf+strlen(buf), "%x,", start);
3761 } else {
3762 sprintf(buf+strlen(buf), "%x-%x,", start, start + streak - 1);
3763 }
3764 streak = 0;
3765 while (opcodeCoverage[i] == 0 && i < 256) {
3766 i++;
3767 }
3768 if (i < 256) {
3769 streak = 1;
3770 start = i;
3771 }
3772 }
3773 }
3774 if (streak) {
3775 if (streak == 1) {
3776 sprintf(buf+strlen(buf), "%x", start);
3777 } else {
3778 sprintf(buf+strlen(buf), "%x-%x", start, start + streak - 1);
3779 }
3780 }
3781 if (strlen(buf)) {
Ben Cheng8b258bf2009-06-24 17:27:07 -07003782 LOGD("dalvik.vm.jit.op = %s", buf);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003783 }
3784}
Ben Chengd7d426a2009-09-22 11:23:36 -07003785
3786/* Common initialization routine for an architecture family */
3787bool dvmCompilerArchInit()
3788{
3789 int i;
3790
Bill Buzbee1465db52009-09-23 17:17:35 -07003791 for (i = 0; i < kArmLast; i++) {
Ben Chengd7d426a2009-09-22 11:23:36 -07003792 if (EncodingMap[i].opCode != i) {
3793 LOGE("Encoding order for %s is wrong: expecting %d, seeing %d",
3794 EncodingMap[i].name, i, EncodingMap[i].opCode);
3795 dvmAbort();
3796 }
3797 }
3798
Ben Cheng5d90c202009-11-22 23:31:11 -08003799 return dvmCompilerArchVariantInit();
3800}
3801
3802void *dvmCompilerGetInterpretTemplate()
3803{
3804 return (void*) ((int)gDvmJit.codeCache +
3805 templateEntryOffsets[TEMPLATE_INTERPRET]);
3806}
3807
3808/* Needed by the ld/st optmizatons */
3809ArmLIR* dvmCompilerRegCopyNoInsert(CompilationUnit *cUnit, int rDest, int rSrc)
3810{
3811 return genRegCopyNoInsert(cUnit, rDest, rSrc);
3812}
3813
3814/* Needed by the register allocator */
3815ArmLIR* dvmCompilerRegCopy(CompilationUnit *cUnit, int rDest, int rSrc)
3816{
3817 return genRegCopy(cUnit, rDest, rSrc);
3818}
3819
3820/* Needed by the register allocator */
3821void dvmCompilerRegCopyWide(CompilationUnit *cUnit, int destLo, int destHi,
3822 int srcLo, int srcHi)
3823{
3824 genRegCopyWide(cUnit, destLo, destHi, srcLo, srcHi);
3825}
3826
3827void dvmCompilerFlushRegImpl(CompilationUnit *cUnit, int rBase,
3828 int displacement, int rSrc, OpSize size)
3829{
3830 storeBaseDisp(cUnit, rBase, displacement, rSrc, size);
3831}
3832
3833void dvmCompilerFlushRegWideImpl(CompilationUnit *cUnit, int rBase,
3834 int displacement, int rSrcLo, int rSrcHi)
3835{
3836 storeBaseDispWide(cUnit, rBase, displacement, rSrcLo, rSrcHi);
Ben Chengd7d426a2009-09-22 11:23:36 -07003837}