blob: 5b4e83f468c8322845f8fc7de62fffe23e1b2866 [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 Buzbeec6f10662010-02-09 11:16:15 -08001279 dvmCompilerColbberCallRegs(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07001280 }
Bill Buzbee270c1d62009-08-13 16:58:07 -07001281}
1282
Ben Chengba4fc8b2009-06-01 13:00:29 -07001283/*
1284 * The following are the first-level codegen routines that analyze the format
1285 * of each bytecode then either dispatch special purpose codegen routines
1286 * or produce corresponding Thumb instructions directly.
1287 */
1288
1289static bool handleFmt10t_Fmt20t_Fmt30t(CompilationUnit *cUnit, MIR *mir,
Bill Buzbee89efc3d2009-07-28 11:22:22 -07001290 BasicBlock *bb, ArmLIR *labelList)
Ben Chengba4fc8b2009-06-01 13:00:29 -07001291{
1292 /* For OP_GOTO, OP_GOTO_16, and OP_GOTO_32 */
1293 genUnconditionalBranch(cUnit, &labelList[bb->taken->id]);
1294 return false;
1295}
1296
1297static bool handleFmt10x(CompilationUnit *cUnit, MIR *mir)
1298{
1299 OpCode dalvikOpCode = mir->dalvikInsn.opCode;
1300 if (((dalvikOpCode >= OP_UNUSED_3E) && (dalvikOpCode <= OP_UNUSED_43)) ||
Andy McFadden96516932009-10-28 17:39:02 -07001301 ((dalvikOpCode >= OP_UNUSED_E3) && (dalvikOpCode <= OP_UNUSED_EB))) {
Ben Chengba4fc8b2009-06-01 13:00:29 -07001302 LOGE("Codegen: got unused opcode 0x%x\n",dalvikOpCode);
1303 return true;
1304 }
1305 switch (dalvikOpCode) {
1306 case OP_RETURN_VOID:
1307 genReturnCommon(cUnit,mir);
1308 break;
1309 case OP_UNUSED_73:
1310 case OP_UNUSED_79:
1311 case OP_UNUSED_7A:
1312 LOGE("Codegen: got unused opcode 0x%x\n",dalvikOpCode);
1313 return true;
1314 case OP_NOP:
1315 break;
1316 default:
1317 return true;
1318 }
1319 return false;
1320}
1321
1322static bool handleFmt11n_Fmt31i(CompilationUnit *cUnit, MIR *mir)
1323{
Bill Buzbee1465db52009-09-23 17:17:35 -07001324 RegLocation rlDest;
1325 RegLocation rlResult;
1326 if (mir->ssaRep->numDefs == 2) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001327 rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -07001328 } else {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001329 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001330 }
Ben Chenge9695e52009-06-16 16:11:47 -07001331
Ben Chengba4fc8b2009-06-01 13:00:29 -07001332 switch (mir->dalvikInsn.opCode) {
1333 case OP_CONST:
Ben Chenge9695e52009-06-16 16:11:47 -07001334 case OP_CONST_4: {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001335 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001336 loadConstantValue(cUnit, rlResult.lowReg, mir->dalvikInsn.vB);
1337 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001338 break;
Ben Chenge9695e52009-06-16 16:11:47 -07001339 }
1340 case OP_CONST_WIDE_32: {
Bill Buzbee1465db52009-09-23 17:17:35 -07001341 //TUNING: single routine to load constant pair for support doubles
Bill Buzbee964a7b02010-01-28 12:54:19 -08001342 //TUNING: load 0/-1 separately to avoid load dependency
Bill Buzbeec6f10662010-02-09 11:16:15 -08001343 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001344 loadConstantValue(cUnit, rlResult.lowReg, mir->dalvikInsn.vB);
1345 opRegRegImm(cUnit, kOpAsr, rlResult.highReg,
1346 rlResult.lowReg, 31);
1347 storeValueWide(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001348 break;
Ben Chenge9695e52009-06-16 16:11:47 -07001349 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07001350 default:
1351 return true;
1352 }
1353 return false;
1354}
1355
1356static bool handleFmt21h(CompilationUnit *cUnit, MIR *mir)
1357{
Bill Buzbee1465db52009-09-23 17:17:35 -07001358 RegLocation rlDest;
1359 RegLocation rlResult;
1360 if (mir->ssaRep->numDefs == 2) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001361 rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -07001362 } else {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001363 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001364 }
Bill Buzbeec6f10662010-02-09 11:16:15 -08001365 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
Ben Chenge9695e52009-06-16 16:11:47 -07001366
Ben Chengba4fc8b2009-06-01 13:00:29 -07001367 switch (mir->dalvikInsn.opCode) {
Ben Chenge9695e52009-06-16 16:11:47 -07001368 case OP_CONST_HIGH16: {
Bill Buzbee1465db52009-09-23 17:17:35 -07001369 loadConstantValue(cUnit, rlResult.lowReg, mir->dalvikInsn.vB << 16);
1370 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001371 break;
Ben Chenge9695e52009-06-16 16:11:47 -07001372 }
1373 case OP_CONST_WIDE_HIGH16: {
Bill Buzbee1465db52009-09-23 17:17:35 -07001374 loadConstantValueWide(cUnit, rlResult.lowReg, rlResult.highReg,
1375 0, mir->dalvikInsn.vB << 16);
1376 storeValueWide(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001377 break;
Ben Chenge9695e52009-06-16 16:11:47 -07001378 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07001379 default:
1380 return true;
1381 }
1382 return false;
1383}
1384
1385static bool handleFmt20bc(CompilationUnit *cUnit, MIR *mir)
1386{
1387 /* For OP_THROW_VERIFICATION_ERROR */
1388 genInterpSingleStep(cUnit, mir);
1389 return false;
1390}
1391
1392static bool handleFmt21c_Fmt31c(CompilationUnit *cUnit, MIR *mir)
1393{
Bill Buzbee1465db52009-09-23 17:17:35 -07001394 RegLocation rlResult;
1395 RegLocation rlDest;
1396 RegLocation rlSrc;
Ben Chenge9695e52009-06-16 16:11:47 -07001397
Ben Chengba4fc8b2009-06-01 13:00:29 -07001398 switch (mir->dalvikInsn.opCode) {
Ben Chengba4fc8b2009-06-01 13:00:29 -07001399 case OP_CONST_STRING_JUMBO:
1400 case OP_CONST_STRING: {
1401 void *strPtr = (void*)
1402 (cUnit->method->clazz->pDvmDex->pResStrings[mir->dalvikInsn.vB]);
1403 assert(strPtr != NULL);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001404 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
1405 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001406 loadConstantValue(cUnit, rlResult.lowReg, (int) strPtr );
1407 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001408 break;
1409 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07001410 case OP_CONST_CLASS: {
1411 void *classPtr = (void*)
1412 (cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vB]);
1413 assert(classPtr != NULL);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001414 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
1415 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001416 loadConstantValue(cUnit, rlResult.lowReg, (int) classPtr );
1417 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001418 break;
1419 }
1420 case OP_SGET_OBJECT:
1421 case OP_SGET_BOOLEAN:
1422 case OP_SGET_CHAR:
1423 case OP_SGET_BYTE:
1424 case OP_SGET_SHORT:
1425 case OP_SGET: {
Bill Buzbee50a6bf22009-07-08 13:08:04 -07001426 int valOffset = offsetof(StaticField, value);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001427 int tReg = dvmCompilerAllocTemp(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001428 void *fieldPtr = (void*)
1429 (cUnit->method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vB]);
1430 assert(fieldPtr != NULL);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001431 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
1432 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001433 loadConstant(cUnit, tReg, (int) fieldPtr + valOffset);
jeffhao9e45c0b2010-02-03 10:24:05 -08001434#if defined(WITH_SELF_VERIFICATION)
1435 cUnit->heapMemOp = true;
1436#endif
Bill Buzbee1465db52009-09-23 17:17:35 -07001437 loadWordDisp(cUnit, tReg, 0, rlResult.lowReg);
jeffhao9e45c0b2010-02-03 10:24:05 -08001438#if defined(WITH_SELF_VERIFICATION)
1439 cUnit->heapMemOp = false;
Jeff Hao97319a82009-08-12 16:57:15 -07001440#endif
Bill Buzbee1465db52009-09-23 17:17:35 -07001441 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001442 break;
1443 }
1444 case OP_SGET_WIDE: {
Bill Buzbee50a6bf22009-07-08 13:08:04 -07001445 int valOffset = offsetof(StaticField, value);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001446 void *fieldPtr = (void*)
1447 (cUnit->method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vB]);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001448 int tReg = dvmCompilerAllocTemp(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001449 assert(fieldPtr != NULL);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001450 rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
1451 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001452 loadConstant(cUnit, tReg, (int) fieldPtr + valOffset);
jeffhao9e45c0b2010-02-03 10:24:05 -08001453#if defined(WITH_SELF_VERIFICATION)
1454 cUnit->heapMemOp = true;
1455#endif
Bill Buzbee1465db52009-09-23 17:17:35 -07001456 loadPair(cUnit, tReg, rlResult.lowReg, rlResult.highReg);
jeffhao9e45c0b2010-02-03 10:24:05 -08001457#if defined(WITH_SELF_VERIFICATION)
1458 cUnit->heapMemOp = false;
Jeff Hao97319a82009-08-12 16:57:15 -07001459#endif
Bill Buzbee1465db52009-09-23 17:17:35 -07001460 storeValueWide(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001461 break;
1462 }
1463 case OP_SPUT_OBJECT:
1464 case OP_SPUT_BOOLEAN:
1465 case OP_SPUT_CHAR:
1466 case OP_SPUT_BYTE:
1467 case OP_SPUT_SHORT:
1468 case OP_SPUT: {
Bill Buzbee50a6bf22009-07-08 13:08:04 -07001469 int valOffset = offsetof(StaticField, value);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001470 int tReg = dvmCompilerAllocTemp(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001471 void *fieldPtr = (void*)
1472 (cUnit->method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vB]);
Ben Chenge9695e52009-06-16 16:11:47 -07001473
Ben Chengba4fc8b2009-06-01 13:00:29 -07001474 assert(fieldPtr != NULL);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001475 rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001476 rlSrc = loadValue(cUnit, rlSrc, kAnyReg);
1477 loadConstant(cUnit, tReg, (int) fieldPtr + valOffset);
jeffhao9e45c0b2010-02-03 10:24:05 -08001478#if defined(WITH_SELF_VERIFICATION)
1479 cUnit->heapMemOp = true;
1480#endif
Bill Buzbee1465db52009-09-23 17:17:35 -07001481 storeWordDisp(cUnit, tReg, 0 ,rlSrc.lowReg);
jeffhao9e45c0b2010-02-03 10:24:05 -08001482#if defined(WITH_SELF_VERIFICATION)
1483 cUnit->heapMemOp = false;
Jeff Hao97319a82009-08-12 16:57:15 -07001484#endif
Ben Chengba4fc8b2009-06-01 13:00:29 -07001485 break;
1486 }
1487 case OP_SPUT_WIDE: {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001488 int tReg = dvmCompilerAllocTemp(cUnit);
Bill Buzbee50a6bf22009-07-08 13:08:04 -07001489 int valOffset = offsetof(StaticField, value);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001490 void *fieldPtr = (void*)
1491 (cUnit->method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vB]);
Ben Chenge9695e52009-06-16 16:11:47 -07001492
Ben Chengba4fc8b2009-06-01 13:00:29 -07001493 assert(fieldPtr != NULL);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001494 rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -07001495 rlSrc = loadValueWide(cUnit, rlSrc, kAnyReg);
1496 loadConstant(cUnit, tReg, (int) fieldPtr + valOffset);
jeffhao9e45c0b2010-02-03 10:24:05 -08001497#if defined(WITH_SELF_VERIFICATION)
1498 cUnit->heapMemOp = true;
1499#endif
Bill Buzbee1465db52009-09-23 17:17:35 -07001500 storePair(cUnit, tReg, rlSrc.lowReg, rlSrc.highReg);
jeffhao9e45c0b2010-02-03 10:24:05 -08001501#if defined(WITH_SELF_VERIFICATION)
1502 cUnit->heapMemOp = false;
Jeff Hao97319a82009-08-12 16:57:15 -07001503#endif
Ben Chengba4fc8b2009-06-01 13:00:29 -07001504 break;
1505 }
1506 case OP_NEW_INSTANCE: {
Ben Chenge9695e52009-06-16 16:11:47 -07001507 /*
1508 * Obey the calling convention and don't mess with the register
1509 * usage.
1510 */
Ben Chengba4fc8b2009-06-01 13:00:29 -07001511 ClassObject *classPtr = (void*)
1512 (cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vB]);
1513 assert(classPtr != NULL);
1514 assert(classPtr->status & CLASS_INITIALIZED);
Ben Cheng79d173c2009-09-29 16:12:51 -07001515 /*
1516 * If it is going to throw, it should not make to the trace to begin
Bill Buzbee1465db52009-09-23 17:17:35 -07001517 * with. However, Alloc might throw, so we need to genExportPC()
Ben Cheng79d173c2009-09-29 16:12:51 -07001518 */
1519 assert((classPtr->accessFlags & (ACC_INTERFACE|ACC_ABSTRACT)) == 0);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001520 dvmCompilerFlushAllRegs(cUnit); /* Everything to home location */
Bill Buzbee1465db52009-09-23 17:17:35 -07001521 genExportPC(cUnit, mir);
1522 loadConstant(cUnit, r2, (int)dvmAllocObject);
Ben Chenge9695e52009-06-16 16:11:47 -07001523 loadConstant(cUnit, r0, (int) classPtr);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001524 loadConstant(cUnit, r1, ALLOC_DONT_TRACK);
Bill Buzbee1465db52009-09-23 17:17:35 -07001525 opReg(cUnit, kOpBlx, r2);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001526 dvmCompilerColbberCallRegs(cUnit);
Ben Cheng4f489172009-09-27 17:08:35 -07001527 /* generate a branch over if allocation is successful */
Bill Buzbee1465db52009-09-23 17:17:35 -07001528 opRegImm(cUnit, kOpCmp, r0, 0); /* NULL? */
1529 ArmLIR *branchOver = opCondBranch(cUnit, kArmCondNe);
Ben Cheng4f489172009-09-27 17:08:35 -07001530 /*
1531 * OOM exception needs to be thrown here and cannot re-execute
1532 */
1533 loadConstant(cUnit, r0,
1534 (int) (cUnit->method->insns + mir->offset));
1535 genDispatchToHandler(cUnit, TEMPLATE_THROW_EXCEPTION_COMMON);
1536 /* noreturn */
1537
Bill Buzbee1465db52009-09-23 17:17:35 -07001538 ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel);
Ben Cheng4f489172009-09-27 17:08:35 -07001539 target->defMask = ENCODE_ALL;
1540 branchOver->generic.target = (LIR *) target;
Bill Buzbeec6f10662010-02-09 11:16:15 -08001541 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
1542 rlResult = dvmCompilerGetReturn(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07001543 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001544 break;
1545 }
1546 case OP_CHECK_CAST: {
Ben Chenge9695e52009-06-16 16:11:47 -07001547 /*
1548 * Obey the calling convention and don't mess with the register
1549 * usage.
1550 */
Ben Chengba4fc8b2009-06-01 13:00:29 -07001551 ClassObject *classPtr =
1552 (cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vB]);
Bill Buzbee4df41a52009-11-12 17:07:16 -08001553 /*
1554 * Note: It is possible that classPtr is NULL at this point,
1555 * even though this instruction has been successfully interpreted.
1556 * If the previous interpretation had a null source, the
1557 * interpreter would not have bothered to resolve the clazz.
1558 * Bail out to the interpreter in this case, and log it
1559 * so that we can tell if it happens frequently.
1560 */
1561 if (classPtr == NULL) {
1562 LOGD("null clazz in OP_CHECK_CAST, single-stepping");
1563 genInterpSingleStep(cUnit, mir);
1564 return false;
1565 }
Bill Buzbeec6f10662010-02-09 11:16:15 -08001566 dvmCompilerFlushAllRegs(cUnit); /* Everything to home location */
Ben Chengba4fc8b2009-06-01 13:00:29 -07001567 loadConstant(cUnit, r1, (int) classPtr );
Bill Buzbeec6f10662010-02-09 11:16:15 -08001568 rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001569 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
1570 opRegImm(cUnit, kOpCmp, rlSrc.lowReg, 0); /* Null? */
1571 ArmLIR *branch1 = opCondBranch(cUnit, kArmCondEq);
1572 /*
1573 * rlSrc.lowReg now contains object->clazz. Note that
1574 * it could have been allocated r0, but we're okay so long
1575 * as we don't do anything desctructive until r0 is loaded
1576 * with clazz.
1577 */
Ben Chengba4fc8b2009-06-01 13:00:29 -07001578 /* r0 now contains object->clazz */
Bill Buzbee1465db52009-09-23 17:17:35 -07001579 loadWordDisp(cUnit, rlSrc.lowReg, offsetof(Object, clazz), r0);
1580 loadConstant(cUnit, r2, (int)dvmInstanceofNonTrivial);
1581 opRegReg(cUnit, kOpCmp, r0, r1);
1582 ArmLIR *branch2 = opCondBranch(cUnit, kArmCondEq);
1583 opReg(cUnit, kOpBlx, r2);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001584 dvmCompilerColbberCallRegs(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07001585 /*
1586 * If null, check cast failed - punt to the interpreter. Because
1587 * interpreter will be the one throwing, we don't need to
1588 * genExportPC() here.
1589 */
Bill Buzbee270c1d62009-08-13 16:58:07 -07001590 genZeroCheck(cUnit, r0, mir->offset, NULL);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001591 /* check cast passed - branch target here */
Bill Buzbee1465db52009-09-23 17:17:35 -07001592 ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel);
Ben Chengd7d426a2009-09-22 11:23:36 -07001593 target->defMask = ENCODE_ALL;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001594 branch1->generic.target = (LIR *)target;
1595 branch2->generic.target = (LIR *)target;
1596 break;
1597 }
1598 default:
1599 return true;
1600 }
1601 return false;
1602}
1603
1604static bool handleFmt11x(CompilationUnit *cUnit, MIR *mir)
1605{
1606 OpCode dalvikOpCode = mir->dalvikInsn.opCode;
Bill Buzbee1465db52009-09-23 17:17:35 -07001607 RegLocation rlResult;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001608 switch (dalvikOpCode) {
1609 case OP_MOVE_EXCEPTION: {
1610 int offset = offsetof(InterpState, self);
1611 int exOffset = offsetof(Thread, exception);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001612 int selfReg = dvmCompilerAllocTemp(cUnit);
1613 int resetReg = dvmCompilerAllocTemp(cUnit);
1614 RegLocation rlDest = dvmCompilerGetDest(cUnit, mir, 0);
1615 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001616 loadWordDisp(cUnit, rGLUE, offset, selfReg);
Bill Buzbeef9f33282009-11-22 12:45:30 -08001617 loadConstant(cUnit, resetReg, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001618 loadWordDisp(cUnit, selfReg, exOffset, rlResult.lowReg);
Bill Buzbeef9f33282009-11-22 12:45:30 -08001619 storeWordDisp(cUnit, selfReg, exOffset, resetReg);
Bill Buzbee1465db52009-09-23 17:17:35 -07001620 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001621 break;
1622 }
1623 case OP_MOVE_RESULT:
1624 case OP_MOVE_RESULT_OBJECT: {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001625 RegLocation rlDest = dvmCompilerGetDest(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001626 RegLocation rlSrc = LOC_DALVIK_RETURN_VAL;
1627 rlSrc.fp = rlDest.fp;
1628 storeValue(cUnit, rlDest, rlSrc);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001629 break;
1630 }
1631 case OP_MOVE_RESULT_WIDE: {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001632 RegLocation rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -07001633 RegLocation rlSrc = LOC_DALVIK_RETURN_VAL_WIDE;
1634 rlSrc.fp = rlDest.fp;
1635 storeValueWide(cUnit, rlDest, rlSrc);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001636 break;
1637 }
1638 case OP_RETURN_WIDE: {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001639 RegLocation rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -07001640 RegLocation rlDest = LOC_DALVIK_RETURN_VAL_WIDE;
1641 rlDest.fp = rlSrc.fp;
1642 storeValueWide(cUnit, rlDest, rlSrc);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001643 genReturnCommon(cUnit,mir);
1644 break;
1645 }
1646 case OP_RETURN:
1647 case OP_RETURN_OBJECT: {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001648 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001649 RegLocation rlDest = LOC_DALVIK_RETURN_VAL;
1650 rlDest.fp = rlSrc.fp;
1651 storeValue(cUnit, rlDest, rlSrc);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001652 genReturnCommon(cUnit,mir);
1653 break;
1654 }
Bill Buzbee1465db52009-09-23 17:17:35 -07001655 case OP_MONITOR_EXIT:
Ben Chengba4fc8b2009-06-01 13:00:29 -07001656 case OP_MONITOR_ENTER:
Bill Buzbeed0937ef2009-12-22 16:15:39 -08001657#if defined(WITH_DEADLOCK_PREDICTION) || defined(WITH_MONITOR_TRACKING)
Ben Cheng5d90c202009-11-22 23:31:11 -08001658 genMonitorPortable(cUnit, mir);
Bill Buzbee1465db52009-09-23 17:17:35 -07001659#else
Ben Cheng5d90c202009-11-22 23:31:11 -08001660 genMonitor(cUnit, mir);
Bill Buzbee1465db52009-09-23 17:17:35 -07001661#endif
Ben Chengba4fc8b2009-06-01 13:00:29 -07001662 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001663 case OP_THROW: {
1664 genInterpSingleStep(cUnit, mir);
1665 break;
1666 }
1667 default:
1668 return true;
1669 }
1670 return false;
1671}
1672
Bill Buzbeed45ba372009-06-15 17:00:57 -07001673static bool handleFmt12x(CompilationUnit *cUnit, MIR *mir)
1674{
1675 OpCode opCode = mir->dalvikInsn.opCode;
Bill Buzbee1465db52009-09-23 17:17:35 -07001676 RegLocation rlDest;
1677 RegLocation rlSrc;
1678 RegLocation rlResult;
Bill Buzbeed45ba372009-06-15 17:00:57 -07001679
Ben Chengba4fc8b2009-06-01 13:00:29 -07001680 if ( (opCode >= OP_ADD_INT_2ADDR) && (opCode <= OP_REM_DOUBLE_2ADDR)) {
Ben Cheng5d90c202009-11-22 23:31:11 -08001681 return genArithOp( cUnit, mir );
Ben Chengba4fc8b2009-06-01 13:00:29 -07001682 }
1683
Bill Buzbee1465db52009-09-23 17:17:35 -07001684 if (mir->ssaRep->numUses == 2)
Bill Buzbeec6f10662010-02-09 11:16:15 -08001685 rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -07001686 else
Bill Buzbeec6f10662010-02-09 11:16:15 -08001687 rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001688 if (mir->ssaRep->numDefs == 2)
Bill Buzbeec6f10662010-02-09 11:16:15 -08001689 rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -07001690 else
Bill Buzbeec6f10662010-02-09 11:16:15 -08001691 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
Ben Chenge9695e52009-06-16 16:11:47 -07001692
Ben Chengba4fc8b2009-06-01 13:00:29 -07001693 switch (opCode) {
Bill Buzbee1465db52009-09-23 17:17:35 -07001694 case OP_DOUBLE_TO_INT:
Ben Chengba4fc8b2009-06-01 13:00:29 -07001695 case OP_INT_TO_FLOAT:
Ben Chengba4fc8b2009-06-01 13:00:29 -07001696 case OP_FLOAT_TO_INT:
Ben Chengba4fc8b2009-06-01 13:00:29 -07001697 case OP_DOUBLE_TO_FLOAT:
Ben Chengba4fc8b2009-06-01 13:00:29 -07001698 case OP_FLOAT_TO_DOUBLE:
Ben Chengba4fc8b2009-06-01 13:00:29 -07001699 case OP_INT_TO_DOUBLE:
Ben Chengba4fc8b2009-06-01 13:00:29 -07001700 case OP_FLOAT_TO_LONG:
Ben Chengba4fc8b2009-06-01 13:00:29 -07001701 case OP_LONG_TO_FLOAT:
Ben Chengba4fc8b2009-06-01 13:00:29 -07001702 case OP_DOUBLE_TO_LONG:
Ben Chengba4fc8b2009-06-01 13:00:29 -07001703 case OP_LONG_TO_DOUBLE:
Ben Cheng5d90c202009-11-22 23:31:11 -08001704 return genConversion(cUnit, mir);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001705 case OP_NEG_INT:
1706 case OP_NOT_INT:
Ben Cheng5d90c202009-11-22 23:31:11 -08001707 return genArithOpInt(cUnit, mir, rlDest, rlSrc, rlSrc);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001708 case OP_NEG_LONG:
1709 case OP_NOT_LONG:
Ben Cheng5d90c202009-11-22 23:31:11 -08001710 return genArithOpLong(cUnit, mir, rlDest, rlSrc, rlSrc);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001711 case OP_NEG_FLOAT:
Ben Cheng5d90c202009-11-22 23:31:11 -08001712 return genArithOpFloat(cUnit, mir, rlDest, rlSrc, rlSrc);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001713 case OP_NEG_DOUBLE:
Ben Cheng5d90c202009-11-22 23:31:11 -08001714 return genArithOpDouble(cUnit, mir, rlDest, rlSrc, rlSrc);
Bill Buzbee1465db52009-09-23 17:17:35 -07001715 case OP_MOVE_WIDE:
1716 storeValueWide(cUnit, rlDest, rlSrc);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001717 break;
Bill Buzbee1465db52009-09-23 17:17:35 -07001718 case OP_INT_TO_LONG:
Bill Buzbeec6f10662010-02-09 11:16:15 -08001719 rlSrc = dvmCompilerUpdateLoc(cUnit, rlSrc);
1720 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee964a7b02010-01-28 12:54:19 -08001721 //TUNING: shouldn't loadValueDirect already check for phys reg?
Bill Buzbee1465db52009-09-23 17:17:35 -07001722 if (rlSrc.location == kLocPhysReg) {
1723 genRegCopy(cUnit, rlResult.lowReg, rlSrc.lowReg);
1724 } else {
1725 loadValueDirect(cUnit, rlSrc, rlResult.lowReg);
1726 }
1727 opRegRegImm(cUnit, kOpAsr, rlResult.highReg,
1728 rlResult.lowReg, 31);
1729 storeValueWide(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001730 break;
Bill Buzbee1465db52009-09-23 17:17:35 -07001731 case OP_LONG_TO_INT:
Bill Buzbeec6f10662010-02-09 11:16:15 -08001732 rlSrc = dvmCompilerUpdateLocWide(cUnit, rlSrc);
1733 rlSrc = dvmCompilerWideToNarrow(cUnit, rlSrc);
Bill Buzbee1465db52009-09-23 17:17:35 -07001734 // Intentional fallthrough
Ben Chengba4fc8b2009-06-01 13:00:29 -07001735 case OP_MOVE:
1736 case OP_MOVE_OBJECT:
Bill Buzbee1465db52009-09-23 17:17:35 -07001737 storeValue(cUnit, rlDest, rlSrc);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001738 break;
1739 case OP_INT_TO_BYTE:
Bill Buzbee1465db52009-09-23 17:17:35 -07001740 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001741 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001742 opRegReg(cUnit, kOp2Byte, rlResult.lowReg, rlSrc.lowReg);
1743 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001744 break;
1745 case OP_INT_TO_SHORT:
Bill Buzbee1465db52009-09-23 17:17:35 -07001746 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001747 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001748 opRegReg(cUnit, kOp2Short, rlResult.lowReg, rlSrc.lowReg);
1749 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001750 break;
1751 case OP_INT_TO_CHAR:
Bill Buzbee1465db52009-09-23 17:17:35 -07001752 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001753 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001754 opRegReg(cUnit, kOp2Char, rlResult.lowReg, rlSrc.lowReg);
1755 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001756 break;
1757 case OP_ARRAY_LENGTH: {
1758 int lenOffset = offsetof(ArrayObject, length);
Bill Buzbee1465db52009-09-23 17:17:35 -07001759 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
1760 genNullCheck(cUnit, rlSrc.sRegLow, rlSrc.lowReg,
1761 mir->offset, NULL);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001762 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001763 loadWordDisp(cUnit, rlSrc.lowReg, lenOffset,
1764 rlResult.lowReg);
1765 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001766 break;
1767 }
1768 default:
1769 return true;
1770 }
1771 return false;
1772}
1773
1774static bool handleFmt21s(CompilationUnit *cUnit, MIR *mir)
1775{
1776 OpCode dalvikOpCode = mir->dalvikInsn.opCode;
Bill Buzbee1465db52009-09-23 17:17:35 -07001777 RegLocation rlDest;
1778 RegLocation rlResult;
1779 int BBBB = mir->dalvikInsn.vB;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001780 if (dalvikOpCode == OP_CONST_WIDE_16) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001781 rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
1782 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001783 loadConstantValue(cUnit, rlResult.lowReg, BBBB);
Bill Buzbee964a7b02010-01-28 12:54:19 -08001784 //TUNING: do high separately to avoid load dependency
Bill Buzbee1465db52009-09-23 17:17:35 -07001785 opRegRegImm(cUnit, kOpAsr, rlResult.highReg, rlResult.lowReg, 31);
1786 storeValueWide(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001787 } else if (dalvikOpCode == OP_CONST_16) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001788 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
1789 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001790 loadConstantValue(cUnit, rlResult.lowReg, BBBB);
1791 storeValue(cUnit, rlDest, rlResult);
1792 } else
Ben Chengba4fc8b2009-06-01 13:00:29 -07001793 return true;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001794 return false;
1795}
1796
1797/* Compare agaist zero */
1798static bool handleFmt21t(CompilationUnit *cUnit, MIR *mir, BasicBlock *bb,
Bill Buzbee89efc3d2009-07-28 11:22:22 -07001799 ArmLIR *labelList)
Ben Chengba4fc8b2009-06-01 13:00:29 -07001800{
1801 OpCode dalvikOpCode = mir->dalvikInsn.opCode;
Bill Buzbee89efc3d2009-07-28 11:22:22 -07001802 ArmConditionCode cond;
Bill Buzbeec6f10662010-02-09 11:16:15 -08001803 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001804 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
1805 opRegImm(cUnit, kOpCmp, rlSrc.lowReg, 0);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001806
Bill Buzbee270c1d62009-08-13 16:58:07 -07001807//TUNING: break this out to allow use of Thumb2 CB[N]Z
Ben Chengba4fc8b2009-06-01 13:00:29 -07001808 switch (dalvikOpCode) {
1809 case OP_IF_EQZ:
Bill Buzbee1465db52009-09-23 17:17:35 -07001810 cond = kArmCondEq;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001811 break;
1812 case OP_IF_NEZ:
Bill Buzbee1465db52009-09-23 17:17:35 -07001813 cond = kArmCondNe;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001814 break;
1815 case OP_IF_LTZ:
Bill Buzbee1465db52009-09-23 17:17:35 -07001816 cond = kArmCondLt;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001817 break;
1818 case OP_IF_GEZ:
Bill Buzbee1465db52009-09-23 17:17:35 -07001819 cond = kArmCondGe;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001820 break;
1821 case OP_IF_GTZ:
Bill Buzbee1465db52009-09-23 17:17:35 -07001822 cond = kArmCondGt;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001823 break;
1824 case OP_IF_LEZ:
Bill Buzbee1465db52009-09-23 17:17:35 -07001825 cond = kArmCondLe;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001826 break;
1827 default:
1828 cond = 0;
1829 LOGE("Unexpected opcode (%d) for Fmt21t\n", dalvikOpCode);
1830 dvmAbort();
1831 }
1832 genConditionalBranch(cUnit, cond, &labelList[bb->taken->id]);
1833 /* This mostly likely will be optimized away in a later phase */
1834 genUnconditionalBranch(cUnit, &labelList[bb->fallThrough->id]);
1835 return false;
1836}
1837
1838static bool handleFmt22b_Fmt22s(CompilationUnit *cUnit, MIR *mir)
1839{
1840 OpCode dalvikOpCode = mir->dalvikInsn.opCode;
Bill Buzbeec6f10662010-02-09 11:16:15 -08001841 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
1842 RegLocation rlDest = dvmCompilerGetDest(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001843 RegLocation rlResult;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001844 int lit = mir->dalvikInsn.vC;
Ben Cheng4f489172009-09-27 17:08:35 -07001845 OpKind op = 0; /* Make gcc happy */
Bill Buzbee1465db52009-09-23 17:17:35 -07001846 int shiftOp = false;
1847 bool isDiv = false;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001848
Ben Chengba4fc8b2009-06-01 13:00:29 -07001849 int __aeabi_idivmod(int op1, int op2);
1850 int __aeabi_idiv(int op1, int op2);
1851
1852 switch (dalvikOpCode) {
Bill Buzbee1465db52009-09-23 17:17:35 -07001853 case OP_RSUB_INT_LIT8:
1854 case OP_RSUB_INT: {
1855 int tReg;
1856 //TUNING: add support for use of Arm rsub op
1857 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001858 tReg = dvmCompilerAllocTemp(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07001859 loadConstant(cUnit, tReg, lit);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001860 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001861 opRegRegReg(cUnit, kOpSub, rlResult.lowReg,
1862 tReg, rlSrc.lowReg);
1863 storeValue(cUnit, rlDest, rlResult);
1864 return false;
1865 break;
1866 }
1867
Ben Chengba4fc8b2009-06-01 13:00:29 -07001868 case OP_ADD_INT_LIT8:
1869 case OP_ADD_INT_LIT16:
Bill Buzbee1465db52009-09-23 17:17:35 -07001870 op = kOpAdd;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001871 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001872 case OP_MUL_INT_LIT8:
1873 case OP_MUL_INT_LIT16:
Bill Buzbee1465db52009-09-23 17:17:35 -07001874 op = kOpMul;
1875 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001876 case OP_AND_INT_LIT8:
1877 case OP_AND_INT_LIT16:
Bill Buzbee1465db52009-09-23 17:17:35 -07001878 op = kOpAnd;
1879 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001880 case OP_OR_INT_LIT8:
1881 case OP_OR_INT_LIT16:
Bill Buzbee1465db52009-09-23 17:17:35 -07001882 op = kOpOr;
1883 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001884 case OP_XOR_INT_LIT8:
1885 case OP_XOR_INT_LIT16:
Bill Buzbee1465db52009-09-23 17:17:35 -07001886 op = kOpXor;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001887 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001888 case OP_SHL_INT_LIT8:
Bill Buzbee0e605272009-12-01 14:28:05 -08001889 lit &= 31;
Bill Buzbee1465db52009-09-23 17:17:35 -07001890 shiftOp = true;
1891 op = kOpLsl;
1892 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001893 case OP_SHR_INT_LIT8:
Bill Buzbee0e605272009-12-01 14:28:05 -08001894 lit &= 31;
Bill Buzbee1465db52009-09-23 17:17:35 -07001895 shiftOp = true;
1896 op = kOpAsr;
1897 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001898 case OP_USHR_INT_LIT8:
Bill Buzbee0e605272009-12-01 14:28:05 -08001899 lit &= 31;
Bill Buzbee1465db52009-09-23 17:17:35 -07001900 shiftOp = true;
1901 op = kOpLsr;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001902 break;
1903
1904 case OP_DIV_INT_LIT8:
1905 case OP_DIV_INT_LIT16:
Ben Chengba4fc8b2009-06-01 13:00:29 -07001906 case OP_REM_INT_LIT8:
1907 case OP_REM_INT_LIT16:
1908 if (lit == 0) {
1909 /* Let the interpreter deal with div by 0 */
1910 genInterpSingleStep(cUnit, mir);
1911 return false;
1912 }
Bill Buzbeec6f10662010-02-09 11:16:15 -08001913 dvmCompilerFlushAllRegs(cUnit); /* Everything to home location */
Bill Buzbee1465db52009-09-23 17:17:35 -07001914 loadValueDirectFixed(cUnit, rlSrc, r0);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001915 dvmCompilerClobber(cUnit, r0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001916 if ((dalvikOpCode == OP_DIV_INT_LIT8) ||
1917 (dalvikOpCode == OP_DIV_INT_LIT16)) {
1918 loadConstant(cUnit, r2, (int)__aeabi_idiv);
1919 isDiv = true;
1920 } else {
1921 loadConstant(cUnit, r2, (int)__aeabi_idivmod);
1922 isDiv = false;
1923 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07001924 loadConstant(cUnit, r1, lit);
Bill Buzbee1465db52009-09-23 17:17:35 -07001925 opReg(cUnit, kOpBlx, r2);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001926 dvmCompilerColbberCallRegs(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07001927 if (isDiv)
Bill Buzbeec6f10662010-02-09 11:16:15 -08001928 rlResult = dvmCompilerGetReturn(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07001929 else
Bill Buzbeec6f10662010-02-09 11:16:15 -08001930 rlResult = dvmCompilerGetReturnAlt(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07001931 storeValue(cUnit, rlDest, rlResult);
1932 return false;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001933 break;
1934 default:
1935 return true;
1936 }
Bill Buzbee1465db52009-09-23 17:17:35 -07001937 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001938 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07001939 // Avoid shifts by literal 0 - no support in Thumb. Change to copy
1940 if (shiftOp && (lit == 0)) {
1941 genRegCopy(cUnit, rlResult.lowReg, rlSrc.lowReg);
1942 } else {
1943 opRegRegImm(cUnit, op, rlResult.lowReg, rlSrc.lowReg, lit);
1944 }
1945 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07001946 return false;
1947}
1948
1949static bool handleFmt22c(CompilationUnit *cUnit, MIR *mir)
1950{
1951 OpCode dalvikOpCode = mir->dalvikInsn.opCode;
1952 int fieldOffset;
1953
1954 if (dalvikOpCode >= OP_IGET && dalvikOpCode <= OP_IPUT_SHORT) {
1955 InstField *pInstField = (InstField *)
1956 cUnit->method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vC];
Ben Chengba4fc8b2009-06-01 13:00:29 -07001957
1958 assert(pInstField != NULL);
1959 fieldOffset = pInstField->byteOffset;
1960 } else {
Ben Chenga0e7b602009-10-13 23:09:01 -07001961 /* Deliberately break the code while make the compiler happy */
1962 fieldOffset = -1;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001963 }
1964 switch (dalvikOpCode) {
Ben Chengba4fc8b2009-06-01 13:00:29 -07001965 case OP_NEW_ARRAY: {
Bill Buzbee1465db52009-09-23 17:17:35 -07001966 // Generates a call - use explicit registers
Bill Buzbeec6f10662010-02-09 11:16:15 -08001967 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
1968 RegLocation rlDest = dvmCompilerGetDest(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07001969 RegLocation rlResult;
Ben Chengba4fc8b2009-06-01 13:00:29 -07001970 void *classPtr = (void*)
1971 (cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vC]);
1972 assert(classPtr != NULL);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001973 dvmCompilerFlushAllRegs(cUnit); /* Everything to home location */
Bill Buzbee1465db52009-09-23 17:17:35 -07001974 genExportPC(cUnit, mir);
1975 loadValueDirectFixed(cUnit, rlSrc, r1); /* Len */
Ben Chengba4fc8b2009-06-01 13:00:29 -07001976 loadConstant(cUnit, r0, (int) classPtr );
Bill Buzbee1465db52009-09-23 17:17:35 -07001977 loadConstant(cUnit, r3, (int)dvmAllocArrayByClass);
Ben Cheng4f489172009-09-27 17:08:35 -07001978 /*
1979 * "len < 0": bail to the interpreter to re-execute the
1980 * instruction
1981 */
Bill Buzbee89efc3d2009-07-28 11:22:22 -07001982 ArmLIR *pcrLabel =
Bill Buzbee1465db52009-09-23 17:17:35 -07001983 genRegImmCheck(cUnit, kArmCondMi, r1, 0, mir->offset, NULL);
Bill Buzbee270c1d62009-08-13 16:58:07 -07001984 loadConstant(cUnit, r2, ALLOC_DONT_TRACK);
Bill Buzbee1465db52009-09-23 17:17:35 -07001985 opReg(cUnit, kOpBlx, r3);
Bill Buzbeec6f10662010-02-09 11:16:15 -08001986 dvmCompilerColbberCallRegs(cUnit);
Ben Cheng4f489172009-09-27 17:08:35 -07001987 /* generate a branch over if allocation is successful */
Bill Buzbee1465db52009-09-23 17:17:35 -07001988 opRegImm(cUnit, kOpCmp, r0, 0); /* NULL? */
1989 ArmLIR *branchOver = opCondBranch(cUnit, kArmCondNe);
Ben Cheng4f489172009-09-27 17:08:35 -07001990 /*
1991 * OOM exception needs to be thrown here and cannot re-execute
1992 */
1993 loadConstant(cUnit, r0,
1994 (int) (cUnit->method->insns + mir->offset));
1995 genDispatchToHandler(cUnit, TEMPLATE_THROW_EXCEPTION_COMMON);
1996 /* noreturn */
1997
Bill Buzbee1465db52009-09-23 17:17:35 -07001998 ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel);
Ben Cheng4f489172009-09-27 17:08:35 -07001999 target->defMask = ENCODE_ALL;
2000 branchOver->generic.target = (LIR *) target;
Bill Buzbeec6f10662010-02-09 11:16:15 -08002001 rlResult = dvmCompilerGetReturn(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07002002 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002003 break;
2004 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07002005 case OP_INSTANCE_OF: {
Bill Buzbee1465db52009-09-23 17:17:35 -07002006 // May generate a call - use explicit registers
Bill Buzbeec6f10662010-02-09 11:16:15 -08002007 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
2008 RegLocation rlDest = dvmCompilerGetDest(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07002009 RegLocation rlResult;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002010 ClassObject *classPtr =
2011 (cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vC]);
Bill Buzbee480e6782010-01-27 15:43:08 -08002012 /*
2013 * Note: It is possible that classPtr is NULL at this point,
2014 * even though this instruction has been successfully interpreted.
2015 * If the previous interpretation had a null source, the
2016 * interpreter would not have bothered to resolve the clazz.
2017 * Bail out to the interpreter in this case, and log it
2018 * so that we can tell if it happens frequently.
2019 */
2020 if (classPtr == NULL) {
2021 LOGD("null clazz in OP_INSTANCE_OF, single-stepping");
2022 genInterpSingleStep(cUnit, mir);
2023 break;
2024 }
Bill Buzbeec6f10662010-02-09 11:16:15 -08002025 dvmCompilerFlushAllRegs(cUnit); /* Everything to home location */
Bill Buzbee1465db52009-09-23 17:17:35 -07002026 loadValueDirectFixed(cUnit, rlSrc, r0); /* Ref */
Ben Chengba4fc8b2009-06-01 13:00:29 -07002027 loadConstant(cUnit, r2, (int) classPtr );
Bill Buzbee270c1d62009-08-13 16:58:07 -07002028//TUNING: compare to 0 primative to allow use of CB[N]Z
Bill Buzbee1465db52009-09-23 17:17:35 -07002029 opRegImm(cUnit, kOpCmp, r0, 0); /* NULL? */
Ben Cheng752c7942009-06-22 10:50:07 -07002030 /* When taken r0 has NULL which can be used for store directly */
Bill Buzbee1465db52009-09-23 17:17:35 -07002031 ArmLIR *branch1 = opCondBranch(cUnit, kArmCondEq);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002032 /* r1 now contains object->clazz */
Bill Buzbee270c1d62009-08-13 16:58:07 -07002033 loadWordDisp(cUnit, r0, offsetof(Object, clazz), r1);
Bill Buzbee1465db52009-09-23 17:17:35 -07002034 /* r1 now contains object->clazz */
2035 loadConstant(cUnit, r3, (int)dvmInstanceofNonTrivial);
Ben Cheng752c7942009-06-22 10:50:07 -07002036 loadConstant(cUnit, r0, 1); /* Assume true */
Bill Buzbee1465db52009-09-23 17:17:35 -07002037 opRegReg(cUnit, kOpCmp, r1, r2);
2038 ArmLIR *branch2 = opCondBranch(cUnit, kArmCondEq);
2039 genRegCopy(cUnit, r0, r1);
2040 genRegCopy(cUnit, r1, r2);
2041 opReg(cUnit, kOpBlx, r3);
Bill Buzbeec6f10662010-02-09 11:16:15 -08002042 dvmCompilerColbberCallRegs(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002043 /* branch target here */
Bill Buzbee1465db52009-09-23 17:17:35 -07002044 ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel);
Ben Chengd7d426a2009-09-22 11:23:36 -07002045 target->defMask = ENCODE_ALL;
Bill Buzbeec6f10662010-02-09 11:16:15 -08002046 rlResult = dvmCompilerGetReturn(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07002047 storeValue(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002048 branch1->generic.target = (LIR *)target;
2049 branch2->generic.target = (LIR *)target;
2050 break;
2051 }
2052 case OP_IGET_WIDE:
2053 genIGetWide(cUnit, mir, fieldOffset);
2054 break;
2055 case OP_IGET:
2056 case OP_IGET_OBJECT:
Bill Buzbee1465db52009-09-23 17:17:35 -07002057 genIGet(cUnit, mir, kWord, fieldOffset);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002058 break;
2059 case OP_IGET_BOOLEAN:
Bill Buzbee1465db52009-09-23 17:17:35 -07002060 genIGet(cUnit, mir, kUnsignedByte, fieldOffset);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002061 break;
2062 case OP_IGET_BYTE:
Bill Buzbee1465db52009-09-23 17:17:35 -07002063 genIGet(cUnit, mir, kSignedByte, fieldOffset);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002064 break;
2065 case OP_IGET_CHAR:
Bill Buzbee1465db52009-09-23 17:17:35 -07002066 genIGet(cUnit, mir, kUnsignedHalf, fieldOffset);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002067 break;
2068 case OP_IGET_SHORT:
Bill Buzbee1465db52009-09-23 17:17:35 -07002069 genIGet(cUnit, mir, kSignedHalf, fieldOffset);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002070 break;
2071 case OP_IPUT_WIDE:
2072 genIPutWide(cUnit, mir, fieldOffset);
2073 break;
2074 case OP_IPUT:
2075 case OP_IPUT_OBJECT:
Bill Buzbee1465db52009-09-23 17:17:35 -07002076 genIPut(cUnit, mir, kWord, fieldOffset);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002077 break;
2078 case OP_IPUT_SHORT:
2079 case OP_IPUT_CHAR:
Bill Buzbee1465db52009-09-23 17:17:35 -07002080 genIPut(cUnit, mir, kUnsignedHalf, fieldOffset);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002081 break;
2082 case OP_IPUT_BYTE:
2083 case OP_IPUT_BOOLEAN:
Bill Buzbee1465db52009-09-23 17:17:35 -07002084 genIPut(cUnit, mir, kUnsignedByte, fieldOffset);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002085 break;
2086 default:
2087 return true;
2088 }
2089 return false;
2090}
2091
2092static bool handleFmt22cs(CompilationUnit *cUnit, MIR *mir)
2093{
2094 OpCode dalvikOpCode = mir->dalvikInsn.opCode;
2095 int fieldOffset = mir->dalvikInsn.vC;
2096 switch (dalvikOpCode) {
2097 case OP_IGET_QUICK:
2098 case OP_IGET_OBJECT_QUICK:
Bill Buzbee1465db52009-09-23 17:17:35 -07002099 genIGet(cUnit, mir, kWord, fieldOffset);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002100 break;
2101 case OP_IPUT_QUICK:
2102 case OP_IPUT_OBJECT_QUICK:
Bill Buzbee1465db52009-09-23 17:17:35 -07002103 genIPut(cUnit, mir, kWord, fieldOffset);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002104 break;
2105 case OP_IGET_WIDE_QUICK:
2106 genIGetWide(cUnit, mir, fieldOffset);
2107 break;
2108 case OP_IPUT_WIDE_QUICK:
2109 genIPutWide(cUnit, mir, fieldOffset);
2110 break;
2111 default:
2112 return true;
2113 }
2114 return false;
2115
2116}
2117
2118/* Compare agaist zero */
2119static bool handleFmt22t(CompilationUnit *cUnit, MIR *mir, BasicBlock *bb,
Bill Buzbee89efc3d2009-07-28 11:22:22 -07002120 ArmLIR *labelList)
Ben Chengba4fc8b2009-06-01 13:00:29 -07002121{
2122 OpCode dalvikOpCode = mir->dalvikInsn.opCode;
Bill Buzbee89efc3d2009-07-28 11:22:22 -07002123 ArmConditionCode cond;
Bill Buzbeec6f10662010-02-09 11:16:15 -08002124 RegLocation rlSrc1 = dvmCompilerGetSrc(cUnit, mir, 0);
2125 RegLocation rlSrc2 = dvmCompilerGetSrc(cUnit, mir, 1);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002126
Bill Buzbee1465db52009-09-23 17:17:35 -07002127 rlSrc1 = loadValue(cUnit, rlSrc1, kCoreReg);
2128 rlSrc2 = loadValue(cUnit, rlSrc2, kCoreReg);
2129 opRegReg(cUnit, kOpCmp, rlSrc1.lowReg, rlSrc2.lowReg);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002130
2131 switch (dalvikOpCode) {
2132 case OP_IF_EQ:
Bill Buzbee1465db52009-09-23 17:17:35 -07002133 cond = kArmCondEq;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002134 break;
2135 case OP_IF_NE:
Bill Buzbee1465db52009-09-23 17:17:35 -07002136 cond = kArmCondNe;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002137 break;
2138 case OP_IF_LT:
Bill Buzbee1465db52009-09-23 17:17:35 -07002139 cond = kArmCondLt;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002140 break;
2141 case OP_IF_GE:
Bill Buzbee1465db52009-09-23 17:17:35 -07002142 cond = kArmCondGe;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002143 break;
2144 case OP_IF_GT:
Bill Buzbee1465db52009-09-23 17:17:35 -07002145 cond = kArmCondGt;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002146 break;
2147 case OP_IF_LE:
Bill Buzbee1465db52009-09-23 17:17:35 -07002148 cond = kArmCondLe;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002149 break;
2150 default:
2151 cond = 0;
2152 LOGE("Unexpected opcode (%d) for Fmt22t\n", dalvikOpCode);
2153 dvmAbort();
2154 }
2155 genConditionalBranch(cUnit, cond, &labelList[bb->taken->id]);
2156 /* This mostly likely will be optimized away in a later phase */
2157 genUnconditionalBranch(cUnit, &labelList[bb->fallThrough->id]);
2158 return false;
2159}
2160
2161static bool handleFmt22x_Fmt32x(CompilationUnit *cUnit, MIR *mir)
2162{
2163 OpCode opCode = mir->dalvikInsn.opCode;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002164
2165 switch (opCode) {
2166 case OP_MOVE_16:
2167 case OP_MOVE_OBJECT_16:
2168 case OP_MOVE_FROM16:
Ben Chenge9695e52009-06-16 16:11:47 -07002169 case OP_MOVE_OBJECT_FROM16: {
Bill Buzbeec6f10662010-02-09 11:16:15 -08002170 storeValue(cUnit, dvmCompilerGetDest(cUnit, mir, 0),
2171 dvmCompilerGetSrc(cUnit, mir, 0));
Ben Chengba4fc8b2009-06-01 13:00:29 -07002172 break;
Ben Chenge9695e52009-06-16 16:11:47 -07002173 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07002174 case OP_MOVE_WIDE_16:
Ben Chenge9695e52009-06-16 16:11:47 -07002175 case OP_MOVE_WIDE_FROM16: {
Bill Buzbeec6f10662010-02-09 11:16:15 -08002176 storeValueWide(cUnit, dvmCompilerGetDestWide(cUnit, mir, 0, 1),
2177 dvmCompilerGetSrcWide(cUnit, mir, 0, 1));
Ben Chengba4fc8b2009-06-01 13:00:29 -07002178 break;
Ben Chenge9695e52009-06-16 16:11:47 -07002179 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07002180 default:
2181 return true;
2182 }
2183 return false;
2184}
2185
2186static bool handleFmt23x(CompilationUnit *cUnit, MIR *mir)
2187{
2188 OpCode opCode = mir->dalvikInsn.opCode;
Bill Buzbee1465db52009-09-23 17:17:35 -07002189 RegLocation rlSrc1;
2190 RegLocation rlSrc2;
2191 RegLocation rlDest;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002192
2193 if ( (opCode >= OP_ADD_INT) && (opCode <= OP_REM_DOUBLE)) {
Ben Cheng5d90c202009-11-22 23:31:11 -08002194 return genArithOp( cUnit, mir );
Ben Chengba4fc8b2009-06-01 13:00:29 -07002195 }
2196
Bill Buzbee1465db52009-09-23 17:17:35 -07002197 /* APUTs have 3 sources and no targets */
2198 if (mir->ssaRep->numDefs == 0) {
2199 if (mir->ssaRep->numUses == 3) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08002200 rlDest = dvmCompilerGetSrc(cUnit, mir, 0);
2201 rlSrc1 = dvmCompilerGetSrc(cUnit, mir, 1);
2202 rlSrc2 = dvmCompilerGetSrc(cUnit, mir, 2);
Bill Buzbee1465db52009-09-23 17:17:35 -07002203 } else {
2204 assert(mir->ssaRep->numUses == 4);
Bill Buzbeec6f10662010-02-09 11:16:15 -08002205 rlDest = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
2206 rlSrc1 = dvmCompilerGetSrc(cUnit, mir, 2);
2207 rlSrc2 = dvmCompilerGetSrc(cUnit, mir, 3);
Bill Buzbee1465db52009-09-23 17:17:35 -07002208 }
2209 } else {
2210 /* Two sources and 1 dest. Deduce the operand sizes */
2211 if (mir->ssaRep->numUses == 4) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08002212 rlSrc1 = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
2213 rlSrc2 = dvmCompilerGetSrcWide(cUnit, mir, 2, 3);
Bill Buzbee1465db52009-09-23 17:17:35 -07002214 } else {
2215 assert(mir->ssaRep->numUses == 2);
Bill Buzbeec6f10662010-02-09 11:16:15 -08002216 rlSrc1 = dvmCompilerGetSrc(cUnit, mir, 0);
2217 rlSrc2 = dvmCompilerGetSrc(cUnit, mir, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -07002218 }
2219 if (mir->ssaRep->numDefs == 2) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08002220 rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
Bill Buzbee1465db52009-09-23 17:17:35 -07002221 } else {
2222 assert(mir->ssaRep->numDefs == 1);
Bill Buzbeec6f10662010-02-09 11:16:15 -08002223 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07002224 }
2225 }
2226
2227
Ben Chengba4fc8b2009-06-01 13:00:29 -07002228 switch (opCode) {
Bill Buzbeed45ba372009-06-15 17:00:57 -07002229 case OP_CMPL_FLOAT:
2230 case OP_CMPG_FLOAT:
2231 case OP_CMPL_DOUBLE:
2232 case OP_CMPG_DOUBLE:
Ben Cheng5d90c202009-11-22 23:31:11 -08002233 return genCmpFP(cUnit, mir, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002234 case OP_CMP_LONG:
Bill Buzbee1465db52009-09-23 17:17:35 -07002235 genCmpLong(cUnit, mir, rlDest, rlSrc1, rlSrc2);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002236 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002237 case OP_AGET_WIDE:
Bill Buzbee1465db52009-09-23 17:17:35 -07002238 genArrayGet(cUnit, mir, kLong, rlSrc1, rlSrc2, rlDest, 3);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002239 break;
2240 case OP_AGET:
2241 case OP_AGET_OBJECT:
Bill Buzbee1465db52009-09-23 17:17:35 -07002242 genArrayGet(cUnit, mir, kWord, rlSrc1, rlSrc2, rlDest, 2);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002243 break;
2244 case OP_AGET_BOOLEAN:
Bill Buzbee1465db52009-09-23 17:17:35 -07002245 genArrayGet(cUnit, mir, kUnsignedByte, rlSrc1, rlSrc2, rlDest, 0);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002246 break;
2247 case OP_AGET_BYTE:
Bill Buzbee1465db52009-09-23 17:17:35 -07002248 genArrayGet(cUnit, mir, kSignedByte, rlSrc1, rlSrc2, rlDest, 0);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002249 break;
2250 case OP_AGET_CHAR:
Bill Buzbee1465db52009-09-23 17:17:35 -07002251 genArrayGet(cUnit, mir, kUnsignedHalf, rlSrc1, rlSrc2, rlDest, 1);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002252 break;
2253 case OP_AGET_SHORT:
Bill Buzbee1465db52009-09-23 17:17:35 -07002254 genArrayGet(cUnit, mir, kSignedHalf, rlSrc1, rlSrc2, rlDest, 1);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002255 break;
2256 case OP_APUT_WIDE:
Bill Buzbee1465db52009-09-23 17:17:35 -07002257 genArrayPut(cUnit, mir, kLong, rlSrc1, rlSrc2, rlDest, 3);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002258 break;
2259 case OP_APUT:
2260 case OP_APUT_OBJECT:
Bill Buzbee1465db52009-09-23 17:17:35 -07002261 genArrayPut(cUnit, mir, kWord, rlSrc1, rlSrc2, rlDest, 2);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002262 break;
2263 case OP_APUT_SHORT:
2264 case OP_APUT_CHAR:
Bill Buzbee1465db52009-09-23 17:17:35 -07002265 genArrayPut(cUnit, mir, kUnsignedHalf, rlSrc1, rlSrc2, rlDest, 1);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002266 break;
2267 case OP_APUT_BYTE:
2268 case OP_APUT_BOOLEAN:
Bill Buzbee1465db52009-09-23 17:17:35 -07002269 genArrayPut(cUnit, mir, kUnsignedByte, rlSrc1, rlSrc2, rlDest, 0);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002270 break;
2271 default:
2272 return true;
2273 }
2274 return false;
2275}
2276
Ben Cheng6c10a972009-10-29 14:39:18 -07002277/*
2278 * Find the matching case.
2279 *
2280 * return values:
2281 * r0 (low 32-bit): pc of the chaining cell corresponding to the resolved case,
2282 * including default which is placed at MIN(size, MAX_CHAINED_SWITCH_CASES).
2283 * r1 (high 32-bit): the branch offset of the matching case (only for indexes
2284 * above MAX_CHAINED_SWITCH_CASES).
2285 *
2286 * Instructions around the call are:
2287 *
2288 * mov r2, pc
2289 * blx &findPackedSwitchIndex
2290 * mov pc, r0
2291 * .align4
2292 * chaining cell for case 0 [8 bytes]
2293 * chaining cell for case 1 [8 bytes]
2294 * :
2295 * chaining cell for case MIN(size, MAX_CHAINED_SWITCH_CASES)-1 [8 bytes]
2296 * chaining cell for case default [8 bytes]
2297 * noChain exit
2298 */
2299s8 findPackedSwitchIndex(const u2* switchData, int testVal, int pc)
2300{
2301 int size;
2302 int firstKey;
2303 const int *entries;
2304 int index;
2305 int jumpIndex;
2306 int caseDPCOffset = 0;
2307 /* In Thumb mode pc is 4 ahead of the "mov r2, pc" instruction */
2308 int chainingPC = (pc + 4) & ~3;
2309
2310 /*
2311 * Packed switch data format:
2312 * ushort ident = 0x0100 magic value
2313 * ushort size number of entries in the table
2314 * int first_key first (and lowest) switch case value
2315 * int targets[size] branch targets, relative to switch opcode
2316 *
2317 * Total size is (4+size*2) 16-bit code units.
2318 */
2319 size = switchData[1];
2320 assert(size > 0);
2321
2322 firstKey = switchData[2];
2323 firstKey |= switchData[3] << 16;
2324
2325
2326 /* The entries are guaranteed to be aligned on a 32-bit boundary;
2327 * we can treat them as a native int array.
2328 */
2329 entries = (const int*) &switchData[4];
2330 assert(((u4)entries & 0x3) == 0);
2331
2332 index = testVal - firstKey;
2333
2334 /* Jump to the default cell */
2335 if (index < 0 || index >= size) {
2336 jumpIndex = MIN(size, MAX_CHAINED_SWITCH_CASES);
2337 /* Jump to the non-chaining exit point */
2338 } else if (index >= MAX_CHAINED_SWITCH_CASES) {
2339 jumpIndex = MAX_CHAINED_SWITCH_CASES + 1;
2340 caseDPCOffset = entries[index];
2341 /* Jump to the inline chaining cell */
2342 } else {
2343 jumpIndex = index;
2344 }
2345
2346 chainingPC += jumpIndex * 8;
2347 return (((s8) caseDPCOffset) << 32) | (u8) chainingPC;
2348}
2349
2350/* See comments for findPackedSwitchIndex */
2351s8 findSparseSwitchIndex(const u2* switchData, int testVal, int pc)
2352{
2353 int size;
2354 const int *keys;
2355 const int *entries;
2356 int chainingPC = (pc + 4) & ~3;
2357 int i;
2358
2359 /*
2360 * Sparse switch data format:
2361 * ushort ident = 0x0200 magic value
2362 * ushort size number of entries in the table; > 0
2363 * int keys[size] keys, sorted low-to-high; 32-bit aligned
2364 * int targets[size] branch targets, relative to switch opcode
2365 *
2366 * Total size is (2+size*4) 16-bit code units.
2367 */
2368
2369 size = switchData[1];
2370 assert(size > 0);
2371
2372 /* The keys are guaranteed to be aligned on a 32-bit boundary;
2373 * we can treat them as a native int array.
2374 */
2375 keys = (const int*) &switchData[2];
2376 assert(((u4)keys & 0x3) == 0);
2377
2378 /* The entries are guaranteed to be aligned on a 32-bit boundary;
2379 * we can treat them as a native int array.
2380 */
2381 entries = keys + size;
2382 assert(((u4)entries & 0x3) == 0);
2383
2384 /*
2385 * Run through the list of keys, which are guaranteed to
2386 * be sorted low-to-high.
2387 *
2388 * Most tables have 3-4 entries. Few have more than 10. A binary
2389 * search here is probably not useful.
2390 */
2391 for (i = 0; i < size; i++) {
2392 int k = keys[i];
2393 if (k == testVal) {
2394 /* MAX_CHAINED_SWITCH_CASES + 1 is the start of the overflow case */
2395 int jumpIndex = (i < MAX_CHAINED_SWITCH_CASES) ?
2396 i : MAX_CHAINED_SWITCH_CASES + 1;
2397 chainingPC += jumpIndex * 8;
2398 return (((s8) entries[i]) << 32) | (u8) chainingPC;
2399 } else if (k > testVal) {
2400 break;
2401 }
2402 }
2403 return chainingPC + MIN(size, MAX_CHAINED_SWITCH_CASES) * 8;
2404}
2405
Ben Chengba4fc8b2009-06-01 13:00:29 -07002406static bool handleFmt31t(CompilationUnit *cUnit, MIR *mir)
2407{
2408 OpCode dalvikOpCode = mir->dalvikInsn.opCode;
2409 switch (dalvikOpCode) {
2410 case OP_FILL_ARRAY_DATA: {
Bill Buzbeec6f10662010-02-09 11:16:15 -08002411 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
Bill Buzbee1465db52009-09-23 17:17:35 -07002412 // Making a call - use explicit registers
Bill Buzbeec6f10662010-02-09 11:16:15 -08002413 dvmCompilerFlushAllRegs(cUnit); /* Everything to home location */
Bill Buzbee1465db52009-09-23 17:17:35 -07002414 genExportPC(cUnit, mir);
2415 loadValueDirectFixed(cUnit, rlSrc, r0);
Bill Buzbeefd023aa2009-11-02 09:23:49 -08002416 loadConstant(cUnit, r2, (int)dvmInterpHandleFillArrayData);
Ben Cheng6c10a972009-10-29 14:39:18 -07002417 loadConstant(cUnit, r1,
2418 (int) (cUnit->method->insns + mir->offset + mir->dalvikInsn.vB));
Bill Buzbee1465db52009-09-23 17:17:35 -07002419 opReg(cUnit, kOpBlx, r2);
Bill Buzbeec6f10662010-02-09 11:16:15 -08002420 dvmCompilerColbberCallRegs(cUnit);
Bill Buzbeefd023aa2009-11-02 09:23:49 -08002421 /* generate a branch over if successful */
2422 opRegImm(cUnit, kOpCmp, r0, 0); /* NULL? */
2423 ArmLIR *branchOver = opCondBranch(cUnit, kArmCondNe);
2424 loadConstant(cUnit, r0,
2425 (int) (cUnit->method->insns + mir->offset));
2426 genDispatchToHandler(cUnit, TEMPLATE_THROW_EXCEPTION_COMMON);
2427 ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel);
2428 target->defMask = ENCODE_ALL;
2429 branchOver->generic.target = (LIR *) target;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002430 break;
2431 }
2432 /*
Ben Cheng6c10a972009-10-29 14:39:18 -07002433 * Compute the goto target of up to
2434 * MIN(switchSize, MAX_CHAINED_SWITCH_CASES) + 1 chaining cells.
2435 * See the comment before findPackedSwitchIndex for the code layout.
Ben Chengba4fc8b2009-06-01 13:00:29 -07002436 */
2437 case OP_PACKED_SWITCH:
2438 case OP_SPARSE_SWITCH: {
Bill Buzbeec6f10662010-02-09 11:16:15 -08002439 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
2440 dvmCompilerFlushAllRegs(cUnit); /* Everything to home location */
Bill Buzbee1465db52009-09-23 17:17:35 -07002441 loadValueDirectFixed(cUnit, rlSrc, r1);
Bill Buzbeec6f10662010-02-09 11:16:15 -08002442 dvmCompilerLockAllTemps(cUnit);
Ben Cheng6c10a972009-10-29 14:39:18 -07002443 const u2 *switchData =
2444 cUnit->method->insns + mir->offset + mir->dalvikInsn.vB;
2445 u2 size = switchData[1];
2446
Ben Chengba4fc8b2009-06-01 13:00:29 -07002447 if (dalvikOpCode == OP_PACKED_SWITCH) {
Ben Cheng6c10a972009-10-29 14:39:18 -07002448 loadConstant(cUnit, r4PC, (int)findPackedSwitchIndex);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002449 } else {
Ben Cheng6c10a972009-10-29 14:39:18 -07002450 loadConstant(cUnit, r4PC, (int)findSparseSwitchIndex);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002451 }
Ben Cheng6c10a972009-10-29 14:39:18 -07002452 /* r0 <- Addr of the switch data */
2453 loadConstant(cUnit, r0,
2454 (int) (cUnit->method->insns + mir->offset + mir->dalvikInsn.vB));
2455 /* r2 <- pc of the instruction following the blx */
2456 opRegReg(cUnit, kOpMov, r2, rpc);
Bill Buzbee1465db52009-09-23 17:17:35 -07002457 opReg(cUnit, kOpBlx, r4PC);
Bill Buzbeec6f10662010-02-09 11:16:15 -08002458 dvmCompilerColbberCallRegs(cUnit);
Ben Cheng6c10a972009-10-29 14:39:18 -07002459 /* pc <- computed goto target */
2460 opRegReg(cUnit, kOpMov, rpc, r0);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002461 break;
2462 }
2463 default:
2464 return true;
2465 }
2466 return false;
2467}
2468
2469static bool handleFmt35c_3rc(CompilationUnit *cUnit, MIR *mir, BasicBlock *bb,
Bill Buzbee89efc3d2009-07-28 11:22:22 -07002470 ArmLIR *labelList)
Ben Chengba4fc8b2009-06-01 13:00:29 -07002471{
Bill Buzbee9bc3df32009-07-30 10:52:29 -07002472 ArmLIR *retChainingCell = NULL;
Bill Buzbee89efc3d2009-07-28 11:22:22 -07002473 ArmLIR *pcrLabel = NULL;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002474
Bill Buzbeef4ce16f2009-07-28 13:28:25 -07002475 if (bb->fallThrough != NULL)
2476 retChainingCell = &labelList[bb->fallThrough->id];
2477
Ben Chengba4fc8b2009-06-01 13:00:29 -07002478 DecodedInstruction *dInsn = &mir->dalvikInsn;
2479 switch (mir->dalvikInsn.opCode) {
2480 /*
2481 * calleeMethod = this->clazz->vtable[
2482 * method->clazz->pDvmDex->pResMethods[BBBB]->methodIndex
2483 * ]
2484 */
2485 case OP_INVOKE_VIRTUAL:
2486 case OP_INVOKE_VIRTUAL_RANGE: {
Bill Buzbee89efc3d2009-07-28 11:22:22 -07002487 ArmLIR *predChainingCell = &labelList[bb->taken->id];
Ben Chengba4fc8b2009-06-01 13:00:29 -07002488 int methodIndex =
2489 cUnit->method->clazz->pDvmDex->pResMethods[dInsn->vB]->
2490 methodIndex;
2491
2492 if (mir->dalvikInsn.opCode == OP_INVOKE_VIRTUAL)
2493 genProcessArgsNoRange(cUnit, mir, dInsn, &pcrLabel);
2494 else
2495 genProcessArgsRange(cUnit, mir, dInsn, &pcrLabel);
2496
Ben Cheng38329f52009-07-07 14:19:20 -07002497 genInvokeVirtualCommon(cUnit, mir, methodIndex,
2498 retChainingCell,
2499 predChainingCell,
2500 pcrLabel);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002501 break;
2502 }
2503 /*
2504 * calleeMethod = method->clazz->super->vtable[method->clazz->pDvmDex
2505 * ->pResMethods[BBBB]->methodIndex]
2506 */
2507 /* TODO - not excersized in RunPerf.jar */
2508 case OP_INVOKE_SUPER:
2509 case OP_INVOKE_SUPER_RANGE: {
2510 int mIndex = cUnit->method->clazz->pDvmDex->
2511 pResMethods[dInsn->vB]->methodIndex;
2512 const Method *calleeMethod =
2513 cUnit->method->clazz->super->vtable[mIndex];
2514
2515 if (mir->dalvikInsn.opCode == OP_INVOKE_SUPER)
2516 genProcessArgsNoRange(cUnit, mir, dInsn, &pcrLabel);
2517 else
2518 genProcessArgsRange(cUnit, mir, dInsn, &pcrLabel);
2519
2520 /* r0 = calleeMethod */
2521 loadConstant(cUnit, r0, (int) calleeMethod);
2522
Ben Cheng38329f52009-07-07 14:19:20 -07002523 genInvokeSingletonCommon(cUnit, mir, bb, labelList, pcrLabel,
2524 calleeMethod);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002525 break;
2526 }
2527 /* calleeMethod = method->clazz->pDvmDex->pResMethods[BBBB] */
2528 case OP_INVOKE_DIRECT:
2529 case OP_INVOKE_DIRECT_RANGE: {
2530 const Method *calleeMethod =
2531 cUnit->method->clazz->pDvmDex->pResMethods[dInsn->vB];
2532
2533 if (mir->dalvikInsn.opCode == OP_INVOKE_DIRECT)
2534 genProcessArgsNoRange(cUnit, mir, dInsn, &pcrLabel);
2535 else
2536 genProcessArgsRange(cUnit, mir, dInsn, &pcrLabel);
2537
2538 /* r0 = calleeMethod */
2539 loadConstant(cUnit, r0, (int) calleeMethod);
2540
Ben Cheng38329f52009-07-07 14:19:20 -07002541 genInvokeSingletonCommon(cUnit, mir, bb, labelList, pcrLabel,
2542 calleeMethod);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002543 break;
2544 }
2545 /* calleeMethod = method->clazz->pDvmDex->pResMethods[BBBB] */
2546 case OP_INVOKE_STATIC:
2547 case OP_INVOKE_STATIC_RANGE: {
2548 const Method *calleeMethod =
2549 cUnit->method->clazz->pDvmDex->pResMethods[dInsn->vB];
2550
2551 if (mir->dalvikInsn.opCode == OP_INVOKE_STATIC)
2552 genProcessArgsNoRange(cUnit, mir, dInsn,
2553 NULL /* no null check */);
2554 else
2555 genProcessArgsRange(cUnit, mir, dInsn,
2556 NULL /* no null check */);
2557
2558 /* r0 = calleeMethod */
2559 loadConstant(cUnit, r0, (int) calleeMethod);
2560
Ben Cheng38329f52009-07-07 14:19:20 -07002561 genInvokeSingletonCommon(cUnit, mir, bb, labelList, pcrLabel,
2562 calleeMethod);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002563 break;
2564 }
Bill Buzbee1465db52009-09-23 17:17:35 -07002565 /*
Ben Chengba4fc8b2009-06-01 13:00:29 -07002566 * calleeMethod = dvmFindInterfaceMethodInCache(this->clazz,
2567 * BBBB, method, method->clazz->pDvmDex)
Ben Cheng38329f52009-07-07 14:19:20 -07002568 *
2569 * Given "invoke-interface {v0}", the following is the generated code:
2570 *
2571 * 0x426a9abe : ldr r0, [r5, #0] --+
2572 * 0x426a9ac0 : mov r7, r5 |
2573 * 0x426a9ac2 : sub r7, #24 |
2574 * 0x426a9ac4 : cmp r0, #0 | genProcessArgsNoRange
2575 * 0x426a9ac6 : beq 0x426a9afe |
2576 * 0x426a9ac8 : stmia r7, <r0> --+
2577 * 0x426a9aca : ldr r4, [pc, #104] --> r4 <- dalvikPC of this invoke
2578 * 0x426a9acc : add r1, pc, #52 --> r1 <- &retChainingCell
2579 * 0x426a9ace : add r2, pc, #60 --> r2 <- &predictedChainingCell
2580 * 0x426a9ad0 : blx_1 0x426a918c --+ TEMPLATE_INVOKE_METHOD_
2581 * 0x426a9ad2 : blx_2 see above --+ PREDICTED_CHAIN
2582 * 0x426a9ad4 : b 0x426a9b0c --> off to the predicted chain
2583 * 0x426a9ad6 : b 0x426a9afe --> punt to the interpreter
Ben Chenga8e64a72009-10-20 13:01:36 -07002584 * 0x426a9ad8 : mov r8, r1 --+
2585 * 0x426a9ada : mov r9, r2 |
2586 * 0x426a9adc : mov r10, r3 |
Ben Cheng38329f52009-07-07 14:19:20 -07002587 * 0x426a9ade : mov r0, r3 |
2588 * 0x426a9ae0 : mov r1, #74 | dvmFindInterfaceMethodInCache
2589 * 0x426a9ae2 : ldr r2, [pc, #76] |
2590 * 0x426a9ae4 : ldr r3, [pc, #68] |
2591 * 0x426a9ae6 : ldr r7, [pc, #64] |
2592 * 0x426a9ae8 : blx r7 --+
Ben Chenga8e64a72009-10-20 13:01:36 -07002593 * 0x426a9aea : mov r1, r8 --> r1 <- rechain count
Ben Cheng38329f52009-07-07 14:19:20 -07002594 * 0x426a9aec : cmp r1, #0 --> compare against 0
2595 * 0x426a9aee : bgt 0x426a9af8 --> >=0? don't rechain
2596 * 0x426a9af0 : ldr r7, [r6, #96] --+
Ben Chenga8e64a72009-10-20 13:01:36 -07002597 * 0x426a9af2 : mov r2, r9 | dvmJitToPatchPredictedChain
2598 * 0x426a9af4 : mov r3, r10 |
Ben Cheng38329f52009-07-07 14:19:20 -07002599 * 0x426a9af6 : blx r7 --+
2600 * 0x426a9af8 : add r1, pc, #8 --> r1 <- &retChainingCell
2601 * 0x426a9afa : blx_1 0x426a9098 --+ TEMPLATE_INVOKE_METHOD_NO_OPT
2602 * 0x426a9afc : blx_2 see above --+
2603 * -------- reconstruct dalvik PC : 0x428b786c @ +0x001e
2604 * 0x426a9afe (0042): ldr r0, [pc, #52]
2605 * Exception_Handling:
2606 * 0x426a9b00 (0044): ldr r1, [r6, #84]
2607 * 0x426a9b02 (0046): blx r1
2608 * 0x426a9b04 (0048): .align4
2609 * -------- chaining cell (hot): 0x0021
2610 * 0x426a9b04 (0048): ldr r0, [r6, #92]
2611 * 0x426a9b06 (004a): blx r0
2612 * 0x426a9b08 (004c): data 0x7872(30834)
2613 * 0x426a9b0a (004e): data 0x428b(17035)
2614 * 0x426a9b0c (0050): .align4
2615 * -------- chaining cell (predicted)
2616 * 0x426a9b0c (0050): data 0x0000(0) --> will be patched into bx
2617 * 0x426a9b0e (0052): data 0x0000(0)
2618 * 0x426a9b10 (0054): data 0x0000(0) --> class
2619 * 0x426a9b12 (0056): data 0x0000(0)
2620 * 0x426a9b14 (0058): data 0x0000(0) --> method
2621 * 0x426a9b16 (005a): data 0x0000(0)
2622 * 0x426a9b18 (005c): data 0x0000(0) --> reset count
2623 * 0x426a9b1a (005e): data 0x0000(0)
2624 * 0x426a9b28 (006c): .word (0xad0392a5)
2625 * 0x426a9b2c (0070): .word (0x6e750)
2626 * 0x426a9b30 (0074): .word (0x4109a618)
2627 * 0x426a9b34 (0078): .word (0x428b786c)
Ben Chengba4fc8b2009-06-01 13:00:29 -07002628 */
2629 case OP_INVOKE_INTERFACE:
2630 case OP_INVOKE_INTERFACE_RANGE: {
Bill Buzbee89efc3d2009-07-28 11:22:22 -07002631 ArmLIR *predChainingCell = &labelList[bb->taken->id];
Ben Chengba4fc8b2009-06-01 13:00:29 -07002632 int methodIndex = dInsn->vB;
2633
Bill Buzbee1465db52009-09-23 17:17:35 -07002634 /* Ensure that nothing is both live and dirty */
Bill Buzbeec6f10662010-02-09 11:16:15 -08002635 dvmCompilerFlushAllRegs(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07002636
Ben Chengba4fc8b2009-06-01 13:00:29 -07002637 if (mir->dalvikInsn.opCode == OP_INVOKE_INTERFACE)
2638 genProcessArgsNoRange(cUnit, mir, dInsn, &pcrLabel);
2639 else
2640 genProcessArgsRange(cUnit, mir, dInsn, &pcrLabel);
2641
Ben Cheng38329f52009-07-07 14:19:20 -07002642 /* "this" is already left in r0 by genProcessArgs* */
2643
2644 /* r4PC = dalvikCallsite */
2645 loadConstant(cUnit, r4PC,
2646 (int) (cUnit->method->insns + mir->offset));
2647
2648 /* r1 = &retChainingCell */
Bill Buzbee270c1d62009-08-13 16:58:07 -07002649 ArmLIR *addrRetChain =
Bill Buzbee1465db52009-09-23 17:17:35 -07002650 opRegRegImm(cUnit, kOpAdd, r1, rpc, 0);
Ben Cheng38329f52009-07-07 14:19:20 -07002651 addrRetChain->generic.target = (LIR *) retChainingCell;
2652
2653 /* r2 = &predictedChainingCell */
Bill Buzbee89efc3d2009-07-28 11:22:22 -07002654 ArmLIR *predictedChainingCell =
Bill Buzbee1465db52009-09-23 17:17:35 -07002655 opRegRegImm(cUnit, kOpAdd, r2, rpc, 0);
Ben Cheng38329f52009-07-07 14:19:20 -07002656 predictedChainingCell->generic.target = (LIR *) predChainingCell;
2657
2658 genDispatchToHandler(cUnit, TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN);
2659
2660 /* return through lr - jump to the chaining cell */
2661 genUnconditionalBranch(cUnit, predChainingCell);
2662
2663 /*
2664 * null-check on "this" may have been eliminated, but we still need
2665 * a PC-reconstruction label for stack overflow bailout.
2666 */
2667 if (pcrLabel == NULL) {
2668 int dPC = (int) (cUnit->method->insns + mir->offset);
Bill Buzbee89efc3d2009-07-28 11:22:22 -07002669 pcrLabel = dvmCompilerNew(sizeof(ArmLIR), true);
Bill Buzbee1465db52009-09-23 17:17:35 -07002670 pcrLabel->opCode = ARM_PSEUDO_kPCReconstruction_CELL;
Ben Cheng38329f52009-07-07 14:19:20 -07002671 pcrLabel->operands[0] = dPC;
2672 pcrLabel->operands[1] = mir->offset;
2673 /* Insert the place holder to the growable list */
2674 dvmInsertGrowableList(&cUnit->pcReconstructionList, pcrLabel);
2675 }
2676
2677 /* return through lr+2 - punt to the interpreter */
2678 genUnconditionalBranch(cUnit, pcrLabel);
2679
2680 /*
2681 * return through lr+4 - fully resolve the callee method.
2682 * r1 <- count
2683 * r2 <- &predictedChainCell
2684 * r3 <- this->class
2685 * r4 <- dPC
2686 * r7 <- this->class->vtable
2687 */
2688
2689 /* Save count, &predictedChainCell, and class to high regs first */
Bill Buzbee1465db52009-09-23 17:17:35 -07002690 genRegCopy(cUnit, r8, r1);
2691 genRegCopy(cUnit, r9, r2);
2692 genRegCopy(cUnit, r10, r3);
Ben Cheng38329f52009-07-07 14:19:20 -07002693
Ben Chengba4fc8b2009-06-01 13:00:29 -07002694 /* r0 now contains this->clazz */
Bill Buzbee1465db52009-09-23 17:17:35 -07002695 genRegCopy(cUnit, r0, r3);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002696
2697 /* r1 = BBBB */
2698 loadConstant(cUnit, r1, dInsn->vB);
2699
2700 /* r2 = method (caller) */
2701 loadConstant(cUnit, r2, (int) cUnit->method);
2702
2703 /* r3 = pDvmDex */
2704 loadConstant(cUnit, r3, (int) cUnit->method->clazz->pDvmDex);
2705
2706 loadConstant(cUnit, r7,
2707 (intptr_t) dvmFindInterfaceMethodInCache);
Bill Buzbee1465db52009-09-23 17:17:35 -07002708 opReg(cUnit, kOpBlx, r7);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002709
2710 /* r0 = calleeMethod (returned from dvmFindInterfaceMethodInCache */
2711
Bill Buzbee1465db52009-09-23 17:17:35 -07002712 genRegCopy(cUnit, r1, r8);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002713
Ben Cheng38329f52009-07-07 14:19:20 -07002714 /* Check if rechain limit is reached */
Bill Buzbee1465db52009-09-23 17:17:35 -07002715 opRegImm(cUnit, kOpCmp, r1, 0);
Ben Cheng38329f52009-07-07 14:19:20 -07002716
Bill Buzbee1465db52009-09-23 17:17:35 -07002717 ArmLIR *bypassRechaining = opCondBranch(cUnit, kArmCondGt);
Ben Cheng38329f52009-07-07 14:19:20 -07002718
Bill Buzbee270c1d62009-08-13 16:58:07 -07002719 loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
2720 jitToInterpEntries.dvmJitToPatchPredictedChain), r7);
Ben Cheng38329f52009-07-07 14:19:20 -07002721
Bill Buzbee1465db52009-09-23 17:17:35 -07002722 genRegCopy(cUnit, r2, r9);
2723 genRegCopy(cUnit, r3, r10);
Ben Cheng38329f52009-07-07 14:19:20 -07002724
2725 /*
2726 * r0 = calleeMethod
2727 * r2 = &predictedChainingCell
2728 * r3 = class
2729 *
2730 * &returnChainingCell has been loaded into r1 but is not needed
2731 * when patching the chaining cell and will be clobbered upon
2732 * returning so it will be reconstructed again.
2733 */
Bill Buzbee1465db52009-09-23 17:17:35 -07002734 opReg(cUnit, kOpBlx, r7);
Ben Cheng38329f52009-07-07 14:19:20 -07002735
2736 /* r1 = &retChainingCell */
Bill Buzbee1465db52009-09-23 17:17:35 -07002737 addrRetChain = opRegRegImm(cUnit, kOpAdd, r1, rpc, 0);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002738 addrRetChain->generic.target = (LIR *) retChainingCell;
Ben Cheng38329f52009-07-07 14:19:20 -07002739
2740 bypassRechaining->generic.target = (LIR *) addrRetChain;
2741
Ben Chengba4fc8b2009-06-01 13:00:29 -07002742 /*
2743 * r0 = this, r1 = calleeMethod,
2744 * r1 = &ChainingCell,
2745 * r4PC = callsiteDPC,
2746 */
2747 genDispatchToHandler(cUnit, TEMPLATE_INVOKE_METHOD_NO_OPT);
2748#if defined(INVOKE_STATS)
Ben Cheng38329f52009-07-07 14:19:20 -07002749 gDvmJit.invokePredictedChain++;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002750#endif
2751 /* Handle exceptions using the interpreter */
2752 genTrap(cUnit, mir->offset, pcrLabel);
2753 break;
2754 }
2755 /* NOP */
2756 case OP_INVOKE_DIRECT_EMPTY: {
2757 return false;
2758 }
2759 case OP_FILLED_NEW_ARRAY:
2760 case OP_FILLED_NEW_ARRAY_RANGE: {
2761 /* Just let the interpreter deal with these */
2762 genInterpSingleStep(cUnit, mir);
2763 break;
2764 }
2765 default:
2766 return true;
2767 }
2768 return false;
2769}
2770
2771static bool handleFmt35ms_3rms(CompilationUnit *cUnit, MIR *mir,
Bill Buzbee89efc3d2009-07-28 11:22:22 -07002772 BasicBlock *bb, ArmLIR *labelList)
Ben Chengba4fc8b2009-06-01 13:00:29 -07002773{
Bill Buzbee89efc3d2009-07-28 11:22:22 -07002774 ArmLIR *retChainingCell = &labelList[bb->fallThrough->id];
2775 ArmLIR *predChainingCell = &labelList[bb->taken->id];
2776 ArmLIR *pcrLabel = NULL;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002777
2778 DecodedInstruction *dInsn = &mir->dalvikInsn;
2779 switch (mir->dalvikInsn.opCode) {
2780 /* calleeMethod = this->clazz->vtable[BBBB] */
2781 case OP_INVOKE_VIRTUAL_QUICK_RANGE:
2782 case OP_INVOKE_VIRTUAL_QUICK: {
2783 int methodIndex = dInsn->vB;
2784 if (mir->dalvikInsn.opCode == OP_INVOKE_VIRTUAL_QUICK)
2785 genProcessArgsNoRange(cUnit, mir, dInsn, &pcrLabel);
2786 else
2787 genProcessArgsRange(cUnit, mir, dInsn, &pcrLabel);
2788
Ben Cheng38329f52009-07-07 14:19:20 -07002789 genInvokeVirtualCommon(cUnit, mir, methodIndex,
2790 retChainingCell,
2791 predChainingCell,
2792 pcrLabel);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002793 break;
2794 }
2795 /* calleeMethod = method->clazz->super->vtable[BBBB] */
2796 case OP_INVOKE_SUPER_QUICK:
2797 case OP_INVOKE_SUPER_QUICK_RANGE: {
2798 const Method *calleeMethod =
2799 cUnit->method->clazz->super->vtable[dInsn->vB];
2800
2801 if (mir->dalvikInsn.opCode == OP_INVOKE_SUPER_QUICK)
2802 genProcessArgsNoRange(cUnit, mir, dInsn, &pcrLabel);
2803 else
2804 genProcessArgsRange(cUnit, mir, dInsn, &pcrLabel);
2805
2806 /* r0 = calleeMethod */
2807 loadConstant(cUnit, r0, (int) calleeMethod);
2808
Ben Cheng38329f52009-07-07 14:19:20 -07002809 genInvokeSingletonCommon(cUnit, mir, bb, labelList, pcrLabel,
2810 calleeMethod);
2811 /* Handle exceptions using the interpreter */
2812 genTrap(cUnit, mir->offset, pcrLabel);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002813 break;
2814 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07002815 default:
2816 return true;
2817 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07002818 return false;
2819}
2820
2821/*
Bill Buzbeefd023aa2009-11-02 09:23:49 -08002822 * This operation is complex enough that we'll do it partly inline
2823 * and partly with a handler. NOTE: the handler uses hardcoded
2824 * values for string object offsets and must be revisitied if the
2825 * layout changes.
2826 */
2827static bool genInlinedCompareTo(CompilationUnit *cUnit, MIR *mir)
2828{
2829#if defined(USE_GLOBAL_STRING_DEFS)
2830 return false;
2831#else
2832 ArmLIR *rollback;
Bill Buzbeec6f10662010-02-09 11:16:15 -08002833 RegLocation rlThis = dvmCompilerGetSrc(cUnit, mir, 0);
2834 RegLocation rlComp = dvmCompilerGetSrc(cUnit, mir, 1);
Bill Buzbeefd023aa2009-11-02 09:23:49 -08002835
2836 loadValueDirectFixed(cUnit, rlThis, r0);
2837 loadValueDirectFixed(cUnit, rlComp, r1);
2838 /* Test objects for NULL */
2839 rollback = genNullCheck(cUnit, rlThis.sRegLow, r0, mir->offset, NULL);
2840 genNullCheck(cUnit, rlComp.sRegLow, r1, mir->offset, rollback);
2841 /*
2842 * TUNING: we could check for object pointer equality before invoking
2843 * handler. Unclear whether the gain would be worth the added code size
2844 * expansion.
2845 */
2846 genDispatchToHandler(cUnit, TEMPLATE_STRING_COMPARETO);
Bill Buzbeec6f10662010-02-09 11:16:15 -08002847 storeValue(cUnit, inlinedTarget(cUnit, mir, false),
2848 dvmCompilerGetReturn(cUnit));
Bill Buzbeefd023aa2009-11-02 09:23:49 -08002849 return true;
2850#endif
2851}
2852
2853static bool genInlinedIndexOf(CompilationUnit *cUnit, MIR *mir, bool singleI)
2854{
2855#if defined(USE_GLOBAL_STRING_DEFS)
2856 return false;
2857#else
Bill Buzbeec6f10662010-02-09 11:16:15 -08002858 RegLocation rlThis = dvmCompilerGetSrc(cUnit, mir, 0);
2859 RegLocation rlChar = dvmCompilerGetSrc(cUnit, mir, 1);
Bill Buzbeefd023aa2009-11-02 09:23:49 -08002860
2861 loadValueDirectFixed(cUnit, rlThis, r0);
2862 loadValueDirectFixed(cUnit, rlChar, r1);
2863 if (!singleI) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08002864 RegLocation rlStart = dvmCompilerGetSrc(cUnit, mir, 2);
Bill Buzbeefd023aa2009-11-02 09:23:49 -08002865 loadValueDirectFixed(cUnit, rlStart, r2);
2866 } else {
2867 loadConstant(cUnit, r2, 0);
2868 }
2869 /* Test objects for NULL */
2870 genNullCheck(cUnit, rlThis.sRegLow, r0, mir->offset, NULL);
2871 genDispatchToHandler(cUnit, TEMPLATE_STRING_INDEXOF);
Bill Buzbeec6f10662010-02-09 11:16:15 -08002872 storeValue(cUnit, inlinedTarget(cUnit, mir, false),
2873 dvmCompilerGetReturn(cUnit));
Bill Buzbeefd023aa2009-11-02 09:23:49 -08002874 return true;
2875#endif
2876}
2877
2878
2879/*
Bill Buzbeece46c942009-11-20 15:41:34 -08002880 * NOTE: Handles both range and non-range versions (arguments
2881 * have already been normalized by this point).
Ben Chengba4fc8b2009-06-01 13:00:29 -07002882 */
Bill Buzbeece46c942009-11-20 15:41:34 -08002883static bool handleExecuteInline(CompilationUnit *cUnit, MIR *mir)
Ben Chengba4fc8b2009-06-01 13:00:29 -07002884{
2885 DecodedInstruction *dInsn = &mir->dalvikInsn;
2886 switch( mir->dalvikInsn.opCode) {
Bill Buzbeece46c942009-11-20 15:41:34 -08002887 case OP_EXECUTE_INLINE_RANGE:
Ben Chengba4fc8b2009-06-01 13:00:29 -07002888 case OP_EXECUTE_INLINE: {
2889 unsigned int i;
2890 const InlineOperation* inLineTable = dvmGetInlineOpsTable();
Bill Buzbee50a6bf22009-07-08 13:08:04 -07002891 int offset = offsetof(InterpState, retval);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002892 int operation = dInsn->vB;
Bill Buzbee1465db52009-09-23 17:17:35 -07002893 int tReg1;
2894 int tReg2;
Bill Buzbee50a6bf22009-07-08 13:08:04 -07002895 switch (operation) {
2896 case INLINE_EMPTYINLINEMETHOD:
2897 return false; /* Nop */
2898 case INLINE_STRING_LENGTH:
2899 return genInlinedStringLength(cUnit, mir);
2900 case INLINE_MATH_ABS_INT:
2901 return genInlinedAbsInt(cUnit, mir);
2902 case INLINE_MATH_ABS_LONG:
2903 return genInlinedAbsLong(cUnit, mir);
2904 case INLINE_MATH_MIN_INT:
2905 return genInlinedMinMaxInt(cUnit, mir, true);
2906 case INLINE_MATH_MAX_INT:
2907 return genInlinedMinMaxInt(cUnit, mir, false);
2908 case INLINE_STRING_CHARAT:
2909 return genInlinedStringCharAt(cUnit, mir);
2910 case INLINE_MATH_SQRT:
2911 if (genInlineSqrt(cUnit, mir))
Bill Buzbee9727c3d2009-08-01 11:32:36 -07002912 return false;
Bill Buzbee50a6bf22009-07-08 13:08:04 -07002913 else
2914 break; /* Handle with C routine */
Bill Buzbee50a6bf22009-07-08 13:08:04 -07002915 case INLINE_MATH_ABS_FLOAT:
Bill Buzbee1465db52009-09-23 17:17:35 -07002916 if (genInlinedAbsFloat(cUnit, mir))
2917 return false;
2918 else
2919 break;
Bill Buzbee50a6bf22009-07-08 13:08:04 -07002920 case INLINE_MATH_ABS_DOUBLE:
Bill Buzbee1465db52009-09-23 17:17:35 -07002921 if (genInlinedAbsDouble(cUnit, mir))
2922 return false;
2923 else
2924 break;
Bill Buzbee50a6bf22009-07-08 13:08:04 -07002925 case INLINE_STRING_COMPARETO:
Bill Buzbeefd023aa2009-11-02 09:23:49 -08002926 if (genInlinedCompareTo(cUnit, mir))
2927 return false;
2928 else
2929 break;
Bill Buzbee12ba0152009-09-03 14:03:09 -07002930 case INLINE_STRING_INDEXOF_I:
Bill Buzbeefd023aa2009-11-02 09:23:49 -08002931 if (genInlinedIndexOf(cUnit, mir, true /* I */))
2932 return false;
2933 else
2934 break;
Bill Buzbee12ba0152009-09-03 14:03:09 -07002935 case INLINE_STRING_INDEXOF_II:
Bill Buzbeefd023aa2009-11-02 09:23:49 -08002936 if (genInlinedIndexOf(cUnit, mir, false /* I */))
2937 return false;
2938 else
2939 break;
2940 case INLINE_STRING_EQUALS:
2941 case INLINE_MATH_COS:
2942 case INLINE_MATH_SIN:
2943 break; /* Handle with C routine */
Bill Buzbee50a6bf22009-07-08 13:08:04 -07002944 default:
2945 dvmAbort();
Ben Chengba4fc8b2009-06-01 13:00:29 -07002946 }
Bill Buzbeec6f10662010-02-09 11:16:15 -08002947 dvmCompilerFlushAllRegs(cUnit); /* Everything to home location */
2948 dvmCompilerColbberCallRegs(cUnit);
2949 dvmCompilerClobber(cUnit, r4PC);
2950 dvmCompilerClobber(cUnit, r7);
Bill Buzbee1465db52009-09-23 17:17:35 -07002951 opRegRegImm(cUnit, kOpAdd, r4PC, rGLUE, offset);
2952 opImm(cUnit, kOpPush, (1<<r4PC) | (1<<r7));
Ben Chengba4fc8b2009-06-01 13:00:29 -07002953 loadConstant(cUnit, r4PC, (int)inLineTable[operation].func);
Bill Buzbee1465db52009-09-23 17:17:35 -07002954 genExportPC(cUnit, mir);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002955 for (i=0; i < dInsn->vA; i++) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08002956 loadValueDirect(cUnit, dvmCompilerGetSrc(cUnit, mir, i), i);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002957 }
Bill Buzbee1465db52009-09-23 17:17:35 -07002958 opReg(cUnit, kOpBlx, r4PC);
2959 opRegImm(cUnit, kOpAdd, r13, 8);
Bill Buzbeece46c942009-11-20 15:41:34 -08002960 opRegImm(cUnit, kOpCmp, r0, 0); /* NULL? */
2961 ArmLIR *branchOver = opCondBranch(cUnit, kArmCondNe);
2962 loadConstant(cUnit, r0,
2963 (int) (cUnit->method->insns + mir->offset));
2964 genDispatchToHandler(cUnit, TEMPLATE_THROW_EXCEPTION_COMMON);
2965 ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel);
2966 target->defMask = ENCODE_ALL;
2967 branchOver->generic.target = (LIR *) target;
Ben Chengba4fc8b2009-06-01 13:00:29 -07002968 break;
2969 }
2970 default:
2971 return true;
2972 }
2973 return false;
2974}
2975
2976static bool handleFmt51l(CompilationUnit *cUnit, MIR *mir)
2977{
Bill Buzbee1465db52009-09-23 17:17:35 -07002978 //TUNING: We're using core regs here - not optimal when target is a double
Bill Buzbeec6f10662010-02-09 11:16:15 -08002979 RegLocation rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
2980 RegLocation rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
Bill Buzbee1465db52009-09-23 17:17:35 -07002981 loadConstantValue(cUnit, rlResult.lowReg,
2982 mir->dalvikInsn.vB_wide & 0xFFFFFFFFUL);
2983 loadConstantValue(cUnit, rlResult.highReg,
2984 (mir->dalvikInsn.vB_wide>>32) & 0xFFFFFFFFUL);
2985 storeValueWide(cUnit, rlDest, rlResult);
Ben Chengba4fc8b2009-06-01 13:00:29 -07002986 return false;
2987}
2988
Ben Chengba4fc8b2009-06-01 13:00:29 -07002989/*
2990 * The following are special processing routines that handle transfer of
2991 * controls between compiled code and the interpreter. Certain VM states like
2992 * Dalvik PC and special-purpose registers are reconstructed here.
2993 */
2994
Ben Cheng1efc9c52009-06-08 18:25:27 -07002995/* Chaining cell for code that may need warmup. */
2996static void handleNormalChainingCell(CompilationUnit *cUnit,
2997 unsigned int offset)
Ben Chengba4fc8b2009-06-01 13:00:29 -07002998{
Bill Buzbee270c1d62009-08-13 16:58:07 -07002999 loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
3000 jitToInterpEntries.dvmJitToInterpNormal), r0);
Bill Buzbee1465db52009-09-23 17:17:35 -07003001 opReg(cUnit, kOpBlx, r0);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003002 addWordData(cUnit, (int) (cUnit->method->insns + offset), true);
3003}
3004
3005/*
Ben Cheng1efc9c52009-06-08 18:25:27 -07003006 * Chaining cell for instructions that immediately following already translated
3007 * code.
Ben Chengba4fc8b2009-06-01 13:00:29 -07003008 */
Ben Cheng1efc9c52009-06-08 18:25:27 -07003009static void handleHotChainingCell(CompilationUnit *cUnit,
3010 unsigned int offset)
Ben Chengba4fc8b2009-06-01 13:00:29 -07003011{
Bill Buzbee270c1d62009-08-13 16:58:07 -07003012 loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
3013 jitToInterpEntries.dvmJitToTraceSelect), r0);
Bill Buzbee1465db52009-09-23 17:17:35 -07003014 opReg(cUnit, kOpBlx, r0);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003015 addWordData(cUnit, (int) (cUnit->method->insns + offset), true);
3016}
3017
Bill Buzbee9c4b7c82009-09-10 10:10:38 -07003018#if defined(WITH_SELF_VERIFICATION) || defined(WITH_JIT_TUNING)
Jeff Hao97319a82009-08-12 16:57:15 -07003019/* Chaining cell for branches that branch back into the same basic block */
3020static void handleBackwardBranchChainingCell(CompilationUnit *cUnit,
3021 unsigned int offset)
3022{
Bill Buzbee9c4b7c82009-09-10 10:10:38 -07003023#if defined(WITH_SELF_VERIFICATION)
Bill Buzbee1465db52009-09-23 17:17:35 -07003024 newLIR3(cUnit, kThumbLdrRRI5, r0, rGLUE,
Jeff Hao97319a82009-08-12 16:57:15 -07003025 offsetof(InterpState, jitToInterpEntries.dvmJitToBackwardBranch) >> 2);
Bill Buzbee9c4b7c82009-09-10 10:10:38 -07003026#else
Bill Buzbee1465db52009-09-23 17:17:35 -07003027 newLIR3(cUnit, kThumbLdrRRI5, r0, rGLUE,
Bill Buzbee9c4b7c82009-09-10 10:10:38 -07003028 offsetof(InterpState, jitToInterpEntries.dvmJitToInterpNormal) >> 2);
3029#endif
Bill Buzbee1465db52009-09-23 17:17:35 -07003030 newLIR1(cUnit, kThumbBlxR, r0);
Jeff Hao97319a82009-08-12 16:57:15 -07003031 addWordData(cUnit, (int) (cUnit->method->insns + offset), true);
3032}
3033
3034#endif
Ben Chengba4fc8b2009-06-01 13:00:29 -07003035/* Chaining cell for monomorphic method invocations. */
Ben Cheng38329f52009-07-07 14:19:20 -07003036static void handleInvokeSingletonChainingCell(CompilationUnit *cUnit,
3037 const Method *callee)
Ben Chengba4fc8b2009-06-01 13:00:29 -07003038{
Bill Buzbee270c1d62009-08-13 16:58:07 -07003039 loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
3040 jitToInterpEntries.dvmJitToTraceSelect), r0);
Bill Buzbee1465db52009-09-23 17:17:35 -07003041 opReg(cUnit, kOpBlx, r0);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003042 addWordData(cUnit, (int) (callee->insns), true);
3043}
3044
Ben Cheng38329f52009-07-07 14:19:20 -07003045/* Chaining cell for monomorphic method invocations. */
3046static void handleInvokePredictedChainingCell(CompilationUnit *cUnit)
3047{
3048
3049 /* Should not be executed in the initial state */
3050 addWordData(cUnit, PREDICTED_CHAIN_BX_PAIR_INIT, true);
3051 /* To be filled: class */
3052 addWordData(cUnit, PREDICTED_CHAIN_CLAZZ_INIT, true);
3053 /* To be filled: method */
3054 addWordData(cUnit, PREDICTED_CHAIN_METHOD_INIT, true);
3055 /*
3056 * Rechain count. The initial value of 0 here will trigger chaining upon
3057 * the first invocation of this callsite.
3058 */
3059 addWordData(cUnit, PREDICTED_CHAIN_COUNTER_INIT, true);
3060}
3061
Ben Chengba4fc8b2009-06-01 13:00:29 -07003062/* Load the Dalvik PC into r0 and jump to the specified target */
3063static void handlePCReconstruction(CompilationUnit *cUnit,
Bill Buzbee89efc3d2009-07-28 11:22:22 -07003064 ArmLIR *targetLabel)
Ben Chengba4fc8b2009-06-01 13:00:29 -07003065{
Bill Buzbee89efc3d2009-07-28 11:22:22 -07003066 ArmLIR **pcrLabel =
3067 (ArmLIR **) cUnit->pcReconstructionList.elemList;
Ben Chengba4fc8b2009-06-01 13:00:29 -07003068 int numElems = cUnit->pcReconstructionList.numUsed;
3069 int i;
3070 for (i = 0; i < numElems; i++) {
3071 dvmCompilerAppendLIR(cUnit, (LIR *) pcrLabel[i]);
3072 /* r0 = dalvik PC */
3073 loadConstant(cUnit, r0, pcrLabel[i]->operands[0]);
3074 genUnconditionalBranch(cUnit, targetLabel);
3075 }
3076}
3077
Bill Buzbee1465db52009-09-23 17:17:35 -07003078static char *extendedMIROpNames[kMirOpLast - kMirOpFirst] = {
3079 "kMirOpPhi",
3080 "kMirOpNullNRangeUpCheck",
3081 "kMirOpNullNRangeDownCheck",
3082 "kMirOpLowerBound",
3083 "kMirOpPunt",
Ben Cheng4238ec22009-08-24 16:32:22 -07003084};
3085
3086/*
3087 * vA = arrayReg;
3088 * vB = idxReg;
3089 * vC = endConditionReg;
3090 * arg[0] = maxC
3091 * arg[1] = minC
3092 * arg[2] = loopBranchConditionCode
3093 */
3094static void genHoistedChecksForCountUpLoop(CompilationUnit *cUnit, MIR *mir)
3095{
Bill Buzbee1465db52009-09-23 17:17:35 -07003096 /*
3097 * NOTE: these synthesized blocks don't have ssa names assigned
3098 * for Dalvik registers. However, because they dominate the following
3099 * blocks we can simply use the Dalvik name w/ subscript 0 as the
3100 * ssa name.
3101 */
Ben Cheng4238ec22009-08-24 16:32:22 -07003102 DecodedInstruction *dInsn = &mir->dalvikInsn;
3103 const int lenOffset = offsetof(ArrayObject, length);
Ben Cheng4238ec22009-08-24 16:32:22 -07003104 const int maxC = dInsn->arg[0];
3105 const int minC = dInsn->arg[1];
Bill Buzbee1465db52009-09-23 17:17:35 -07003106 int regLength;
3107 RegLocation rlArray = cUnit->regLocation[mir->dalvikInsn.vA];
3108 RegLocation rlIdxEnd = cUnit->regLocation[mir->dalvikInsn.vC];
Ben Cheng4238ec22009-08-24 16:32:22 -07003109
3110 /* regArray <- arrayRef */
Bill Buzbee1465db52009-09-23 17:17:35 -07003111 rlArray = loadValue(cUnit, rlArray, kCoreReg);
3112 rlIdxEnd = loadValue(cUnit, rlIdxEnd, kCoreReg);
3113 genRegImmCheck(cUnit, kArmCondEq, rlArray.lowReg, 0, 0,
Ben Cheng4238ec22009-08-24 16:32:22 -07003114 (ArmLIR *) cUnit->loopAnalysis->branchToPCR);
3115
3116 /* regLength <- len(arrayRef) */
Bill Buzbeec6f10662010-02-09 11:16:15 -08003117 regLength = dvmCompilerAllocTemp(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07003118 loadWordDisp(cUnit, rlArray.lowReg, lenOffset, regLength);
Ben Cheng4238ec22009-08-24 16:32:22 -07003119
3120 int delta = maxC;
3121 /*
3122 * If the loop end condition is ">=" instead of ">", then the largest value
3123 * of the index is "endCondition - 1".
3124 */
3125 if (dInsn->arg[2] == OP_IF_GE) {
3126 delta--;
3127 }
3128
3129 if (delta) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08003130 int tReg = dvmCompilerAllocTemp(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07003131 opRegRegImm(cUnit, kOpAdd, tReg, rlIdxEnd.lowReg, delta);
3132 rlIdxEnd.lowReg = tReg;
Bill Buzbeec6f10662010-02-09 11:16:15 -08003133 dvmCompilerFreeTemp(cUnit, tReg);
Ben Cheng4238ec22009-08-24 16:32:22 -07003134 }
3135 /* Punt if "regIdxEnd < len(Array)" is false */
Bill Buzbee1465db52009-09-23 17:17:35 -07003136 genRegRegCheck(cUnit, kArmCondGe, rlIdxEnd.lowReg, regLength, 0,
Ben Cheng0fd31e42009-09-03 14:40:16 -07003137 (ArmLIR *) cUnit->loopAnalysis->branchToPCR);
Ben Cheng4238ec22009-08-24 16:32:22 -07003138}
3139
3140/*
3141 * vA = arrayReg;
3142 * vB = idxReg;
3143 * vC = endConditionReg;
3144 * arg[0] = maxC
3145 * arg[1] = minC
3146 * arg[2] = loopBranchConditionCode
3147 */
3148static void genHoistedChecksForCountDownLoop(CompilationUnit *cUnit, MIR *mir)
3149{
3150 DecodedInstruction *dInsn = &mir->dalvikInsn;
3151 const int lenOffset = offsetof(ArrayObject, length);
Bill Buzbeec6f10662010-02-09 11:16:15 -08003152 const int regLength = dvmCompilerAllocTemp(cUnit);
Ben Cheng4238ec22009-08-24 16:32:22 -07003153 const int maxC = dInsn->arg[0];
3154 const int minC = dInsn->arg[1];
Bill Buzbee1465db52009-09-23 17:17:35 -07003155 RegLocation rlArray = cUnit->regLocation[mir->dalvikInsn.vA];
3156 RegLocation rlIdxInit = cUnit->regLocation[mir->dalvikInsn.vB];
Ben Cheng4238ec22009-08-24 16:32:22 -07003157
3158 /* regArray <- arrayRef */
Bill Buzbee1465db52009-09-23 17:17:35 -07003159 rlArray = loadValue(cUnit, rlArray, kCoreReg);
3160 rlIdxInit = loadValue(cUnit, rlIdxInit, kCoreReg);
3161 genRegImmCheck(cUnit, kArmCondEq, rlArray.lowReg, 0, 0,
Ben Cheng4238ec22009-08-24 16:32:22 -07003162 (ArmLIR *) cUnit->loopAnalysis->branchToPCR);
3163
3164 /* regLength <- len(arrayRef) */
Bill Buzbee1465db52009-09-23 17:17:35 -07003165 loadWordDisp(cUnit, rlArray.lowReg, lenOffset, regLength);
Ben Cheng4238ec22009-08-24 16:32:22 -07003166
3167 if (maxC) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08003168 int tReg = dvmCompilerAllocTemp(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07003169 opRegRegImm(cUnit, kOpAdd, tReg, rlIdxInit.lowReg, maxC);
3170 rlIdxInit.lowReg = tReg;
Bill Buzbeec6f10662010-02-09 11:16:15 -08003171 dvmCompilerFreeTemp(cUnit, tReg);
Ben Cheng4238ec22009-08-24 16:32:22 -07003172 }
3173
3174 /* Punt if "regIdxInit < len(Array)" is false */
Bill Buzbee1465db52009-09-23 17:17:35 -07003175 genRegRegCheck(cUnit, kArmCondGe, rlIdxInit.lowReg, regLength, 0,
Ben Cheng0fd31e42009-09-03 14:40:16 -07003176 (ArmLIR *) cUnit->loopAnalysis->branchToPCR);
Ben Cheng4238ec22009-08-24 16:32:22 -07003177}
3178
3179/*
3180 * vA = idxReg;
3181 * vB = minC;
3182 */
3183static void genHoistedLowerBoundCheck(CompilationUnit *cUnit, MIR *mir)
3184{
3185 DecodedInstruction *dInsn = &mir->dalvikInsn;
Ben Cheng4238ec22009-08-24 16:32:22 -07003186 const int minC = dInsn->vB;
Bill Buzbee1465db52009-09-23 17:17:35 -07003187 RegLocation rlIdx = cUnit->regLocation[mir->dalvikInsn.vA];
Ben Cheng4238ec22009-08-24 16:32:22 -07003188
3189 /* regIdx <- initial index value */
Bill Buzbee1465db52009-09-23 17:17:35 -07003190 rlIdx = loadValue(cUnit, rlIdx, kCoreReg);
Ben Cheng4238ec22009-08-24 16:32:22 -07003191
3192 /* Punt if "regIdxInit + minC >= 0" is false */
Bill Buzbee1465db52009-09-23 17:17:35 -07003193 genRegImmCheck(cUnit, kArmCondLt, rlIdx.lowReg, -minC, 0,
Ben Cheng4238ec22009-08-24 16:32:22 -07003194 (ArmLIR *) cUnit->loopAnalysis->branchToPCR);
3195}
3196
3197/* Extended MIR instructions like PHI */
3198static void handleExtendedMIR(CompilationUnit *cUnit, MIR *mir)
3199{
Bill Buzbee1465db52009-09-23 17:17:35 -07003200 int opOffset = mir->dalvikInsn.opCode - kMirOpFirst;
Ben Cheng4238ec22009-08-24 16:32:22 -07003201 char *msg = dvmCompilerNew(strlen(extendedMIROpNames[opOffset]) + 1,
3202 false);
3203 strcpy(msg, extendedMIROpNames[opOffset]);
Bill Buzbee1465db52009-09-23 17:17:35 -07003204 newLIR1(cUnit, kArmPseudoExtended, (int) msg);
Ben Cheng4238ec22009-08-24 16:32:22 -07003205
3206 switch (mir->dalvikInsn.opCode) {
Bill Buzbee1465db52009-09-23 17:17:35 -07003207 case kMirOpPhi: {
Ben Cheng4238ec22009-08-24 16:32:22 -07003208 char *ssaString = dvmCompilerGetSSAString(cUnit, mir->ssaRep);
Bill Buzbee1465db52009-09-23 17:17:35 -07003209 newLIR1(cUnit, kArmPseudoSSARep, (int) ssaString);
Ben Cheng4238ec22009-08-24 16:32:22 -07003210 break;
3211 }
Bill Buzbee1465db52009-09-23 17:17:35 -07003212 case kMirOpNullNRangeUpCheck: {
Ben Cheng4238ec22009-08-24 16:32:22 -07003213 genHoistedChecksForCountUpLoop(cUnit, mir);
3214 break;
3215 }
Bill Buzbee1465db52009-09-23 17:17:35 -07003216 case kMirOpNullNRangeDownCheck: {
Ben Cheng4238ec22009-08-24 16:32:22 -07003217 genHoistedChecksForCountDownLoop(cUnit, mir);
3218 break;
3219 }
Bill Buzbee1465db52009-09-23 17:17:35 -07003220 case kMirOpLowerBound: {
Ben Cheng4238ec22009-08-24 16:32:22 -07003221 genHoistedLowerBoundCheck(cUnit, mir);
3222 break;
3223 }
Bill Buzbee1465db52009-09-23 17:17:35 -07003224 case kMirOpPunt: {
Ben Cheng4238ec22009-08-24 16:32:22 -07003225 genUnconditionalBranch(cUnit,
3226 (ArmLIR *) cUnit->loopAnalysis->branchToPCR);
3227 break;
3228 }
3229 default:
3230 break;
3231 }
3232}
3233
3234/*
3235 * Create a PC-reconstruction cell for the starting offset of this trace.
3236 * Since the PCR cell is placed near the end of the compiled code which is
3237 * usually out of range for a conditional branch, we put two branches (one
3238 * branch over to the loop body and one layover branch to the actual PCR) at the
3239 * end of the entry block.
3240 */
3241static void setupLoopEntryBlock(CompilationUnit *cUnit, BasicBlock *entry,
3242 ArmLIR *bodyLabel)
3243{
3244 /* Set up the place holder to reconstruct this Dalvik PC */
3245 ArmLIR *pcrLabel = dvmCompilerNew(sizeof(ArmLIR), true);
Bill Buzbee1465db52009-09-23 17:17:35 -07003246 pcrLabel->opCode = ARM_PSEUDO_kPCReconstruction_CELL;
Ben Cheng4238ec22009-08-24 16:32:22 -07003247 pcrLabel->operands[0] =
3248 (int) (cUnit->method->insns + entry->startOffset);
3249 pcrLabel->operands[1] = entry->startOffset;
3250 /* Insert the place holder to the growable list */
3251 dvmInsertGrowableList(&cUnit->pcReconstructionList, pcrLabel);
3252
3253 /*
3254 * Next, create two branches - one branch over to the loop body and the
3255 * other branch to the PCR cell to punt.
3256 */
3257 ArmLIR *branchToBody = dvmCompilerNew(sizeof(ArmLIR), true);
Bill Buzbee1465db52009-09-23 17:17:35 -07003258 branchToBody->opCode = kThumbBUncond;
Ben Cheng4238ec22009-08-24 16:32:22 -07003259 branchToBody->generic.target = (LIR *) bodyLabel;
Ben Chengdcf3e5d2009-09-11 13:42:05 -07003260 setupResourceMasks(branchToBody);
Ben Cheng4238ec22009-08-24 16:32:22 -07003261 cUnit->loopAnalysis->branchToBody = (LIR *) branchToBody;
3262
3263 ArmLIR *branchToPCR = dvmCompilerNew(sizeof(ArmLIR), true);
Bill Buzbee1465db52009-09-23 17:17:35 -07003264 branchToPCR->opCode = kThumbBUncond;
Ben Cheng4238ec22009-08-24 16:32:22 -07003265 branchToPCR->generic.target = (LIR *) pcrLabel;
Ben Chengdcf3e5d2009-09-11 13:42:05 -07003266 setupResourceMasks(branchToPCR);
Ben Cheng4238ec22009-08-24 16:32:22 -07003267 cUnit->loopAnalysis->branchToPCR = (LIR *) branchToPCR;
3268}
3269
Ben Chengba4fc8b2009-06-01 13:00:29 -07003270void dvmCompilerMIR2LIR(CompilationUnit *cUnit)
3271{
3272 /* Used to hold the labels of each block */
Bill Buzbee89efc3d2009-07-28 11:22:22 -07003273 ArmLIR *labelList =
3274 dvmCompilerNew(sizeof(ArmLIR) * cUnit->numBlocks, true);
Ben Chengcec26f62010-01-15 15:29:33 -08003275 GrowableList chainingListByType[kChainingCellGap];
Ben Chengba4fc8b2009-06-01 13:00:29 -07003276 int i;
3277
3278 /*
Ben Cheng38329f52009-07-07 14:19:20 -07003279 * Initialize various types chaining lists.
Ben Chengba4fc8b2009-06-01 13:00:29 -07003280 */
Ben Chengcec26f62010-01-15 15:29:33 -08003281 for (i = 0; i < kChainingCellGap; i++) {
Ben Chengba4fc8b2009-06-01 13:00:29 -07003282 dvmInitGrowableList(&chainingListByType[i], 2);
3283 }
3284
3285 BasicBlock **blockList = cUnit->blockList;
3286
Bill Buzbee6e963e12009-06-17 16:56:19 -07003287 if (cUnit->executionCount) {
3288 /*
3289 * Reserve 6 bytes at the beginning of the trace
3290 * +----------------------------+
3291 * | execution count (4 bytes) |
3292 * +----------------------------+
3293 * | chain cell offset (2 bytes)|
3294 * +----------------------------+
3295 * ...and then code to increment the execution
3296 * count:
3297 * mov r0, pc @ move adr of "mov r0,pc" + 4 to r0
3298 * sub r0, #10 @ back up to addr of executionCount
3299 * ldr r1, [r0]
3300 * add r1, #1
3301 * str r1, [r0]
3302 */
Bill Buzbee1465db52009-09-23 17:17:35 -07003303 newLIR1(cUnit, kArm16BitData, 0);
3304 newLIR1(cUnit, kArm16BitData, 0);
Ben Chengcc6600c2009-06-22 14:45:16 -07003305 cUnit->chainCellOffsetLIR =
Bill Buzbee1465db52009-09-23 17:17:35 -07003306 (LIR *) newLIR1(cUnit, kArm16BitData, CHAIN_CELL_OFFSET_TAG);
Bill Buzbee6e963e12009-06-17 16:56:19 -07003307 cUnit->headerSize = 6;
Bill Buzbee270c1d62009-08-13 16:58:07 -07003308 /* Thumb instruction used directly here to ensure correct size */
Bill Buzbee1465db52009-09-23 17:17:35 -07003309 newLIR2(cUnit, kThumbMovRR_H2L, r0, rpc);
3310 newLIR2(cUnit, kThumbSubRI8, r0, 10);
3311 newLIR3(cUnit, kThumbLdrRRI5, r1, r0, 0);
3312 newLIR2(cUnit, kThumbAddRI8, r1, 1);
3313 newLIR3(cUnit, kThumbStrRRI5, r1, r0, 0);
Bill Buzbee6e963e12009-06-17 16:56:19 -07003314 } else {
3315 /* Just reserve 2 bytes for the chain cell offset */
Ben Chengcc6600c2009-06-22 14:45:16 -07003316 cUnit->chainCellOffsetLIR =
Bill Buzbee1465db52009-09-23 17:17:35 -07003317 (LIR *) newLIR1(cUnit, kArm16BitData, CHAIN_CELL_OFFSET_TAG);
Bill Buzbee6e963e12009-06-17 16:56:19 -07003318 cUnit->headerSize = 2;
3319 }
Ben Cheng1efc9c52009-06-08 18:25:27 -07003320
Ben Chengba4fc8b2009-06-01 13:00:29 -07003321 /* Handle the content in each basic block */
3322 for (i = 0; i < cUnit->numBlocks; i++) {
3323 blockList[i]->visited = true;
3324 MIR *mir;
3325
3326 labelList[i].operands[0] = blockList[i]->startOffset;
3327
Ben Chengcec26f62010-01-15 15:29:33 -08003328 if (blockList[i]->blockType >= kChainingCellGap) {
Ben Chengba4fc8b2009-06-01 13:00:29 -07003329 /*
3330 * Append the label pseudo LIR first. Chaining cells will be handled
3331 * separately afterwards.
3332 */
3333 dvmCompilerAppendLIR(cUnit, (LIR *) &labelList[i]);
3334 }
3335
Bill Buzbee1465db52009-09-23 17:17:35 -07003336 if (blockList[i]->blockType == kEntryBlock) {
3337 labelList[i].opCode = ARM_PSEUDO_kEntryBlock;
Ben Cheng4238ec22009-08-24 16:32:22 -07003338 if (blockList[i]->firstMIRInsn == NULL) {
3339 continue;
3340 } else {
3341 setupLoopEntryBlock(cUnit, blockList[i],
3342 &labelList[blockList[i]->fallThrough->id]);
3343 }
Bill Buzbee1465db52009-09-23 17:17:35 -07003344 } else if (blockList[i]->blockType == kExitBlock) {
3345 labelList[i].opCode = ARM_PSEUDO_kExitBlock;
Ben Cheng4238ec22009-08-24 16:32:22 -07003346 goto gen_fallthrough;
Bill Buzbee1465db52009-09-23 17:17:35 -07003347 } else if (blockList[i]->blockType == kDalvikByteCode) {
3348 labelList[i].opCode = kArmPseudoNormalBlockLabel;
Ben Chenge9695e52009-06-16 16:11:47 -07003349 /* Reset the register state */
Bill Buzbeec6f10662010-02-09 11:16:15 -08003350 dvmCompilerResetRegPool(cUnit);
3351 dvmCompilerClobberAllRegs(cUnit);
3352 dvmCompilerResetNullCheck(cUnit);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003353 } else {
3354 switch (blockList[i]->blockType) {
Bill Buzbee1465db52009-09-23 17:17:35 -07003355 case kChainingCellNormal:
3356 labelList[i].opCode = ARM_PSEUDO_kChainingCellNormal;
Ben Chengba4fc8b2009-06-01 13:00:29 -07003357 /* handle the codegen later */
3358 dvmInsertGrowableList(
Bill Buzbee1465db52009-09-23 17:17:35 -07003359 &chainingListByType[kChainingCellNormal], (void *) i);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003360 break;
Bill Buzbee1465db52009-09-23 17:17:35 -07003361 case kChainingCellInvokeSingleton:
Ben Cheng38329f52009-07-07 14:19:20 -07003362 labelList[i].opCode =
Bill Buzbee1465db52009-09-23 17:17:35 -07003363 ARM_PSEUDO_kChainingCellInvokeSingleton;
Ben Chengba4fc8b2009-06-01 13:00:29 -07003364 labelList[i].operands[0] =
3365 (int) blockList[i]->containingMethod;
3366 /* handle the codegen later */
3367 dvmInsertGrowableList(
Bill Buzbee1465db52009-09-23 17:17:35 -07003368 &chainingListByType[kChainingCellInvokeSingleton],
Ben Cheng38329f52009-07-07 14:19:20 -07003369 (void *) i);
3370 break;
Bill Buzbee1465db52009-09-23 17:17:35 -07003371 case kChainingCellInvokePredicted:
Ben Cheng38329f52009-07-07 14:19:20 -07003372 labelList[i].opCode =
Bill Buzbee1465db52009-09-23 17:17:35 -07003373 ARM_PSEUDO_kChainingCellInvokePredicted;
Ben Cheng38329f52009-07-07 14:19:20 -07003374 /* handle the codegen later */
3375 dvmInsertGrowableList(
Bill Buzbee1465db52009-09-23 17:17:35 -07003376 &chainingListByType[kChainingCellInvokePredicted],
Ben Cheng38329f52009-07-07 14:19:20 -07003377 (void *) i);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003378 break;
Bill Buzbee1465db52009-09-23 17:17:35 -07003379 case kChainingCellHot:
Ben Chengba4fc8b2009-06-01 13:00:29 -07003380 labelList[i].opCode =
Bill Buzbee1465db52009-09-23 17:17:35 -07003381 ARM_PSEUDO_kChainingCellHot;
Ben Chengba4fc8b2009-06-01 13:00:29 -07003382 /* handle the codegen later */
3383 dvmInsertGrowableList(
Bill Buzbee1465db52009-09-23 17:17:35 -07003384 &chainingListByType[kChainingCellHot],
Ben Chengba4fc8b2009-06-01 13:00:29 -07003385 (void *) i);
3386 break;
Bill Buzbee1465db52009-09-23 17:17:35 -07003387 case kPCReconstruction:
Ben Chengba4fc8b2009-06-01 13:00:29 -07003388 /* Make sure exception handling block is next */
3389 labelList[i].opCode =
Bill Buzbee1465db52009-09-23 17:17:35 -07003390 ARM_PSEUDO_kPCReconstruction_BLOCK_LABEL;
Ben Chengba4fc8b2009-06-01 13:00:29 -07003391 assert (i == cUnit->numBlocks - 2);
3392 handlePCReconstruction(cUnit, &labelList[i+1]);
3393 break;
Bill Buzbee1465db52009-09-23 17:17:35 -07003394 case kExceptionHandling:
3395 labelList[i].opCode = kArmPseudoEHBlockLabel;
Ben Chengba4fc8b2009-06-01 13:00:29 -07003396 if (cUnit->pcReconstructionList.numUsed) {
Bill Buzbee270c1d62009-08-13 16:58:07 -07003397 loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
3398 jitToInterpEntries.dvmJitToInterpPunt),
3399 r1);
Bill Buzbee1465db52009-09-23 17:17:35 -07003400 opReg(cUnit, kOpBlx, r1);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003401 }
3402 break;
Bill Buzbee9c4b7c82009-09-10 10:10:38 -07003403#if defined(WITH_SELF_VERIFICATION) || defined(WITH_JIT_TUNING)
Bill Buzbee1465db52009-09-23 17:17:35 -07003404 case kChainingCellBackwardBranch:
Jeff Hao97319a82009-08-12 16:57:15 -07003405 labelList[i].opCode =
Bill Buzbee1465db52009-09-23 17:17:35 -07003406 ARM_PSEUDO_kChainingCellBackwardBranch;
Jeff Hao97319a82009-08-12 16:57:15 -07003407 /* handle the codegen later */
3408 dvmInsertGrowableList(
Bill Buzbee1465db52009-09-23 17:17:35 -07003409 &chainingListByType[kChainingCellBackwardBranch],
Jeff Hao97319a82009-08-12 16:57:15 -07003410 (void *) i);
3411 break;
3412#endif
Ben Chengba4fc8b2009-06-01 13:00:29 -07003413 default:
3414 break;
3415 }
3416 continue;
3417 }
Ben Chenge9695e52009-06-16 16:11:47 -07003418
Bill Buzbee89efc3d2009-07-28 11:22:22 -07003419 ArmLIR *headLIR = NULL;
Ben Chenge9695e52009-06-16 16:11:47 -07003420
Ben Chengba4fc8b2009-06-01 13:00:29 -07003421 for (mir = blockList[i]->firstMIRInsn; mir; mir = mir->next) {
Bill Buzbee1465db52009-09-23 17:17:35 -07003422
Bill Buzbeec6f10662010-02-09 11:16:15 -08003423 dvmCompilerResetRegPool(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07003424 if (gDvmJit.disableOpt & (1 << kTrackLiveTemps)) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08003425 dvmCompilerClobberAllRegs(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07003426 }
3427
3428 if (gDvmJit.disableOpt & (1 << kSuppressLoads)) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08003429 dvmCompilerResetDefTracking(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -07003430 }
3431
3432 if (mir->dalvikInsn.opCode >= kMirOpFirst) {
Ben Cheng4238ec22009-08-24 16:32:22 -07003433 handleExtendedMIR(cUnit, mir);
3434 continue;
3435 }
3436
Bill Buzbee1465db52009-09-23 17:17:35 -07003437
Ben Chengba4fc8b2009-06-01 13:00:29 -07003438 OpCode dalvikOpCode = mir->dalvikInsn.opCode;
3439 InstructionFormat dalvikFormat =
3440 dexGetInstrFormat(gDvm.instrFormat, dalvikOpCode);
Bill Buzbee89efc3d2009-07-28 11:22:22 -07003441 ArmLIR *boundaryLIR =
Bill Buzbee1465db52009-09-23 17:17:35 -07003442 newLIR2(cUnit, ARM_PSEUDO_kDalvikByteCode_BOUNDARY,
Ben Chengccd6c012009-10-15 14:52:45 -07003443 mir->offset,
3444 (int) dvmCompilerGetDalvikDisassembly(&mir->dalvikInsn)
3445 );
Ben Cheng4238ec22009-08-24 16:32:22 -07003446 if (mir->ssaRep) {
3447 char *ssaString = dvmCompilerGetSSAString(cUnit, mir->ssaRep);
Bill Buzbee1465db52009-09-23 17:17:35 -07003448 newLIR1(cUnit, kArmPseudoSSARep, (int) ssaString);
Ben Cheng4238ec22009-08-24 16:32:22 -07003449 }
3450
Ben Chenge9695e52009-06-16 16:11:47 -07003451 /* Remember the first LIR for this block */
3452 if (headLIR == NULL) {
3453 headLIR = boundaryLIR;
Ben Chengd7d426a2009-09-22 11:23:36 -07003454 /* Set the first boundaryLIR as a scheduling barrier */
3455 headLIR->defMask = ENCODE_ALL;
Ben Chenge9695e52009-06-16 16:11:47 -07003456 }
Ben Cheng4238ec22009-08-24 16:32:22 -07003457
Ben Chengba4fc8b2009-06-01 13:00:29 -07003458 bool notHandled;
3459 /*
3460 * Debugging: screen the opcode first to see if it is in the
3461 * do[-not]-compile list
3462 */
3463 bool singleStepMe =
3464 gDvmJit.includeSelectedOp !=
3465 ((gDvmJit.opList[dalvikOpCode >> 3] &
3466 (1 << (dalvikOpCode & 0x7))) !=
3467 0);
3468 if (singleStepMe || cUnit->allSingleStep) {
3469 notHandled = false;
3470 genInterpSingleStep(cUnit, mir);
3471 } else {
3472 opcodeCoverage[dalvikOpCode]++;
3473 switch (dalvikFormat) {
3474 case kFmt10t:
3475 case kFmt20t:
3476 case kFmt30t:
3477 notHandled = handleFmt10t_Fmt20t_Fmt30t(cUnit,
3478 mir, blockList[i], labelList);
3479 break;
3480 case kFmt10x:
3481 notHandled = handleFmt10x(cUnit, mir);
3482 break;
3483 case kFmt11n:
3484 case kFmt31i:
3485 notHandled = handleFmt11n_Fmt31i(cUnit, mir);
3486 break;
3487 case kFmt11x:
3488 notHandled = handleFmt11x(cUnit, mir);
3489 break;
3490 case kFmt12x:
3491 notHandled = handleFmt12x(cUnit, mir);
3492 break;
3493 case kFmt20bc:
3494 notHandled = handleFmt20bc(cUnit, mir);
3495 break;
3496 case kFmt21c:
3497 case kFmt31c:
3498 notHandled = handleFmt21c_Fmt31c(cUnit, mir);
3499 break;
3500 case kFmt21h:
3501 notHandled = handleFmt21h(cUnit, mir);
3502 break;
3503 case kFmt21s:
3504 notHandled = handleFmt21s(cUnit, mir);
3505 break;
3506 case kFmt21t:
3507 notHandled = handleFmt21t(cUnit, mir, blockList[i],
3508 labelList);
3509 break;
3510 case kFmt22b:
3511 case kFmt22s:
3512 notHandled = handleFmt22b_Fmt22s(cUnit, mir);
3513 break;
3514 case kFmt22c:
3515 notHandled = handleFmt22c(cUnit, mir);
3516 break;
3517 case kFmt22cs:
3518 notHandled = handleFmt22cs(cUnit, mir);
3519 break;
3520 case kFmt22t:
3521 notHandled = handleFmt22t(cUnit, mir, blockList[i],
3522 labelList);
3523 break;
3524 case kFmt22x:
3525 case kFmt32x:
3526 notHandled = handleFmt22x_Fmt32x(cUnit, mir);
3527 break;
3528 case kFmt23x:
3529 notHandled = handleFmt23x(cUnit, mir);
3530 break;
3531 case kFmt31t:
3532 notHandled = handleFmt31t(cUnit, mir);
3533 break;
3534 case kFmt3rc:
3535 case kFmt35c:
3536 notHandled = handleFmt35c_3rc(cUnit, mir, blockList[i],
3537 labelList);
3538 break;
3539 case kFmt3rms:
3540 case kFmt35ms:
3541 notHandled = handleFmt35ms_3rms(cUnit, mir,blockList[i],
3542 labelList);
3543 break;
3544 case kFmt3inline:
Andy McFaddenb0a05412009-11-19 10:23:41 -08003545 case kFmt3rinline:
Bill Buzbeece46c942009-11-20 15:41:34 -08003546 notHandled = handleExecuteInline(cUnit, mir);
Andy McFaddenb0a05412009-11-19 10:23:41 -08003547 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07003548 case kFmt51l:
3549 notHandled = handleFmt51l(cUnit, mir);
3550 break;
3551 default:
3552 notHandled = true;
3553 break;
3554 }
3555 }
3556 if (notHandled) {
3557 LOGE("%#06x: Opcode 0x%x (%s) / Fmt %d not handled\n",
3558 mir->offset,
3559 dalvikOpCode, getOpcodeName(dalvikOpCode),
3560 dalvikFormat);
3561 dvmAbort();
3562 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -07003563 }
3564 }
Ben Cheng4238ec22009-08-24 16:32:22 -07003565
Bill Buzbee1465db52009-09-23 17:17:35 -07003566 if (blockList[i]->blockType == kEntryBlock) {
Ben Cheng4238ec22009-08-24 16:32:22 -07003567 dvmCompilerAppendLIR(cUnit,
3568 (LIR *) cUnit->loopAnalysis->branchToBody);
3569 dvmCompilerAppendLIR(cUnit,
3570 (LIR *) cUnit->loopAnalysis->branchToPCR);
3571 }
3572
3573 if (headLIR) {
3574 /*
3575 * Eliminate redundant loads/stores and delay stores into later
3576 * slots
3577 */
3578 dvmCompilerApplyLocalOptimizations(cUnit, (LIR *) headLIR,
3579 cUnit->lastLIRInsn);
3580 }
3581
3582gen_fallthrough:
Ben Cheng1efc9c52009-06-08 18:25:27 -07003583 /*
3584 * Check if the block is terminated due to trace length constraint -
3585 * insert an unconditional branch to the chaining cell.
3586 */
3587 if (blockList[i]->needFallThroughBranch) {
3588 genUnconditionalBranch(cUnit,
3589 &labelList[blockList[i]->fallThrough->id]);
3590 }
3591
Ben Chengba4fc8b2009-06-01 13:00:29 -07003592 }
3593
Ben Chenge9695e52009-06-16 16:11:47 -07003594 /* Handle the chaining cells in predefined order */
Ben Chengcec26f62010-01-15 15:29:33 -08003595 for (i = 0; i < kChainingCellGap; i++) {
Ben Chengba4fc8b2009-06-01 13:00:29 -07003596 size_t j;
3597 int *blockIdList = (int *) chainingListByType[i].elemList;
3598
3599 cUnit->numChainingCells[i] = chainingListByType[i].numUsed;
3600
3601 /* No chaining cells of this type */
3602 if (cUnit->numChainingCells[i] == 0)
3603 continue;
3604
3605 /* Record the first LIR for a new type of chaining cell */
3606 cUnit->firstChainingLIR[i] = (LIR *) &labelList[blockIdList[0]];
3607
3608 for (j = 0; j < chainingListByType[i].numUsed; j++) {
3609 int blockId = blockIdList[j];
3610
3611 /* Align this chaining cell first */
Bill Buzbee1465db52009-09-23 17:17:35 -07003612 newLIR0(cUnit, kArmPseudoPseudoAlign4);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003613
3614 /* Insert the pseudo chaining instruction */
3615 dvmCompilerAppendLIR(cUnit, (LIR *) &labelList[blockId]);
3616
3617
3618 switch (blockList[blockId]->blockType) {
Bill Buzbee1465db52009-09-23 17:17:35 -07003619 case kChainingCellNormal:
Ben Cheng1efc9c52009-06-08 18:25:27 -07003620 handleNormalChainingCell(cUnit,
Ben Chengba4fc8b2009-06-01 13:00:29 -07003621 blockList[blockId]->startOffset);
3622 break;
Bill Buzbee1465db52009-09-23 17:17:35 -07003623 case kChainingCellInvokeSingleton:
Ben Cheng38329f52009-07-07 14:19:20 -07003624 handleInvokeSingletonChainingCell(cUnit,
Ben Chengba4fc8b2009-06-01 13:00:29 -07003625 blockList[blockId]->containingMethod);
3626 break;
Bill Buzbee1465db52009-09-23 17:17:35 -07003627 case kChainingCellInvokePredicted:
Ben Cheng38329f52009-07-07 14:19:20 -07003628 handleInvokePredictedChainingCell(cUnit);
3629 break;
Bill Buzbee1465db52009-09-23 17:17:35 -07003630 case kChainingCellHot:
Ben Cheng1efc9c52009-06-08 18:25:27 -07003631 handleHotChainingCell(cUnit,
Ben Chengba4fc8b2009-06-01 13:00:29 -07003632 blockList[blockId]->startOffset);
3633 break;
Bill Buzbee9c4b7c82009-09-10 10:10:38 -07003634#if defined(WITH_SELF_VERIFICATION) || defined(WITH_JIT_TUNING)
Bill Buzbee1465db52009-09-23 17:17:35 -07003635 case kChainingCellBackwardBranch:
Jeff Hao97319a82009-08-12 16:57:15 -07003636 handleBackwardBranchChainingCell(cUnit,
3637 blockList[blockId]->startOffset);
3638 break;
3639#endif
Ben Chengba4fc8b2009-06-01 13:00:29 -07003640 default:
Bill Buzbee1465db52009-09-23 17:17:35 -07003641 LOGE("Bad blocktype %d", blockList[blockId]->blockType);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003642 dvmAbort();
3643 break;
3644 }
3645 }
3646 }
Ben Chenge9695e52009-06-16 16:11:47 -07003647
Ben Chengcec26f62010-01-15 15:29:33 -08003648 /* Mark the bottom of chaining cells */
3649 cUnit->chainingCellBottom = (LIR *) newLIR0(cUnit, kArmChainingCellBottom);
3650
Ben Cheng6c10a972009-10-29 14:39:18 -07003651 /*
3652 * Generate the branch to the dvmJitToInterpNoChain entry point at the end
3653 * of all chaining cells for the overflow cases.
3654 */
3655 if (cUnit->switchOverflowPad) {
3656 loadConstant(cUnit, r0, (int) cUnit->switchOverflowPad);
3657 loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
3658 jitToInterpEntries.dvmJitToInterpNoChain), r2);
3659 opRegReg(cUnit, kOpAdd, r1, r1);
3660 opRegRegReg(cUnit, kOpAdd, r4PC, r0, r1);
3661#if defined(EXIT_STATS)
3662 loadConstant(cUnit, r0, kSwitchOverflow);
3663#endif
3664 opReg(cUnit, kOpBlx, r2);
3665 }
3666
Ben Chenge9695e52009-06-16 16:11:47 -07003667 dvmCompilerApplyGlobalOptimizations(cUnit);
jeffhao9e45c0b2010-02-03 10:24:05 -08003668
3669#if defined(WITH_SELF_VERIFICATION)
3670 selfVerificationBranchInsertPass(cUnit);
3671#endif
Ben Chengba4fc8b2009-06-01 13:00:29 -07003672}
3673
3674/* Accept the work and start compiling */
Bill Buzbee716f1202009-07-23 13:22:09 -07003675bool dvmCompilerDoWork(CompilerWorkOrder *work)
Ben Chengba4fc8b2009-06-01 13:00:29 -07003676{
Ben Chengccd6c012009-10-15 14:52:45 -07003677 bool res;
Ben Chengba4fc8b2009-06-01 13:00:29 -07003678
Ben Cheng6999d842010-01-26 16:46:15 -08003679 if (gDvmJit.codeCacheFull) {
Ben Chengccd6c012009-10-15 14:52:45 -07003680 return false;
3681 }
Ben Chengba4fc8b2009-06-01 13:00:29 -07003682
Ben Chengccd6c012009-10-15 14:52:45 -07003683 switch (work->kind) {
3684 case kWorkOrderMethod:
3685 res = dvmCompileMethod(work->info, &work->result);
3686 break;
3687 case kWorkOrderTrace:
3688 /* Start compilation with maximally allowed trace length */
3689 res = dvmCompileTrace(work->info, JIT_MAX_TRACE_LEN, &work->result);
3690 break;
3691 case kWorkOrderTraceDebug: {
3692 bool oldPrintMe = gDvmJit.printMe;
3693 gDvmJit.printMe = true;
3694 /* Start compilation with maximally allowed trace length */
3695 res = dvmCompileTrace(work->info, JIT_MAX_TRACE_LEN, &work->result);
3696 gDvmJit.printMe = oldPrintMe;;
3697 break;
3698 }
3699 default:
3700 res = false;
3701 dvmAbort();
3702 }
3703 return res;
Ben Chengba4fc8b2009-06-01 13:00:29 -07003704}
3705
Ben Chengba4fc8b2009-06-01 13:00:29 -07003706/* Architectural-specific debugging helpers go here */
3707void dvmCompilerArchDump(void)
3708{
3709 /* Print compiled opcode in this VM instance */
3710 int i, start, streak;
3711 char buf[1024];
3712
3713 streak = i = 0;
3714 buf[0] = 0;
3715 while (opcodeCoverage[i] == 0 && i < 256) {
3716 i++;
3717 }
3718 if (i == 256) {
3719 return;
3720 }
3721 for (start = i++, streak = 1; i < 256; i++) {
3722 if (opcodeCoverage[i]) {
3723 streak++;
3724 } else {
3725 if (streak == 1) {
3726 sprintf(buf+strlen(buf), "%x,", start);
3727 } else {
3728 sprintf(buf+strlen(buf), "%x-%x,", start, start + streak - 1);
3729 }
3730 streak = 0;
3731 while (opcodeCoverage[i] == 0 && i < 256) {
3732 i++;
3733 }
3734 if (i < 256) {
3735 streak = 1;
3736 start = i;
3737 }
3738 }
3739 }
3740 if (streak) {
3741 if (streak == 1) {
3742 sprintf(buf+strlen(buf), "%x", start);
3743 } else {
3744 sprintf(buf+strlen(buf), "%x-%x", start, start + streak - 1);
3745 }
3746 }
3747 if (strlen(buf)) {
Ben Cheng8b258bf2009-06-24 17:27:07 -07003748 LOGD("dalvik.vm.jit.op = %s", buf);
Ben Chengba4fc8b2009-06-01 13:00:29 -07003749 }
3750}
Ben Chengd7d426a2009-09-22 11:23:36 -07003751
3752/* Common initialization routine for an architecture family */
3753bool dvmCompilerArchInit()
3754{
3755 int i;
3756
Bill Buzbee1465db52009-09-23 17:17:35 -07003757 for (i = 0; i < kArmLast; i++) {
Ben Chengd7d426a2009-09-22 11:23:36 -07003758 if (EncodingMap[i].opCode != i) {
3759 LOGE("Encoding order for %s is wrong: expecting %d, seeing %d",
3760 EncodingMap[i].name, i, EncodingMap[i].opCode);
3761 dvmAbort();
3762 }
3763 }
3764
Ben Cheng5d90c202009-11-22 23:31:11 -08003765 return dvmCompilerArchVariantInit();
3766}
3767
3768void *dvmCompilerGetInterpretTemplate()
3769{
3770 return (void*) ((int)gDvmJit.codeCache +
3771 templateEntryOffsets[TEMPLATE_INTERPRET]);
3772}
3773
3774/* Needed by the ld/st optmizatons */
3775ArmLIR* dvmCompilerRegCopyNoInsert(CompilationUnit *cUnit, int rDest, int rSrc)
3776{
3777 return genRegCopyNoInsert(cUnit, rDest, rSrc);
3778}
3779
3780/* Needed by the register allocator */
3781ArmLIR* dvmCompilerRegCopy(CompilationUnit *cUnit, int rDest, int rSrc)
3782{
3783 return genRegCopy(cUnit, rDest, rSrc);
3784}
3785
3786/* Needed by the register allocator */
3787void dvmCompilerRegCopyWide(CompilationUnit *cUnit, int destLo, int destHi,
3788 int srcLo, int srcHi)
3789{
3790 genRegCopyWide(cUnit, destLo, destHi, srcLo, srcHi);
3791}
3792
3793void dvmCompilerFlushRegImpl(CompilationUnit *cUnit, int rBase,
3794 int displacement, int rSrc, OpSize size)
3795{
3796 storeBaseDisp(cUnit, rBase, displacement, rSrc, size);
3797}
3798
3799void dvmCompilerFlushRegWideImpl(CompilationUnit *cUnit, int rBase,
3800 int displacement, int rSrcLo, int rSrcHi)
3801{
3802 storeBaseDispWide(cUnit, rBase, displacement, rSrcLo, rSrcHi);
Ben Chengd7d426a2009-09-22 11:23:36 -07003803}