blob: edf880b503b00474287ba950b0dd7f8956365dea [file] [log] [blame]
buzbeee3acd072012-02-25 17:03:10 -08001/*
2 * Copyright (C) 2011 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
17#include "object_utils.h"
18
19namespace art {
20
21#define DISPLAY_MISSING_TARGETS (cUnit->enableDebug & \
Bill Buzbeea114add2012-05-03 15:00:40 -070022 (1 << kDebugDisplayMissingTargets))
buzbeee3acd072012-02-25 17:03:10 -080023
buzbee2cfc6392012-05-07 14:51:40 -070024const RegLocation badLoc = {kLocDalvikFrame, 0, 0, 0, 0, 0, 0, 0, 0,
25 INVALID_REG, INVALID_REG, INVALID_SREG,
26 INVALID_SREG};
buzbeee3acd072012-02-25 17:03:10 -080027
28/* Mark register usage state and return long retloc */
Ian Rogersf7d9ad32012-03-13 18:45:39 -070029RegLocation oatGetReturnWide(CompilationUnit* cUnit, bool isDouble)
buzbeee3acd072012-02-25 17:03:10 -080030{
Bill Buzbeea114add2012-05-03 15:00:40 -070031 RegLocation gpr_res = LOC_C_RETURN_WIDE;
32 RegLocation fpr_res = LOC_C_RETURN_WIDE_DOUBLE;
33 RegLocation res = isDouble ? fpr_res : gpr_res;
34 oatClobber(cUnit, res.lowReg);
35 oatClobber(cUnit, res.highReg);
36 oatLockTemp(cUnit, res.lowReg);
37 oatLockTemp(cUnit, res.highReg);
38 oatMarkPair(cUnit, res.lowReg, res.highReg);
39 return res;
buzbeee3acd072012-02-25 17:03:10 -080040}
41
Ian Rogersf7d9ad32012-03-13 18:45:39 -070042RegLocation oatGetReturn(CompilationUnit* cUnit, bool isFloat)
buzbeee3acd072012-02-25 17:03:10 -080043{
Ian Rogersf7d9ad32012-03-13 18:45:39 -070044 RegLocation gpr_res = LOC_C_RETURN;
45 RegLocation fpr_res = LOC_C_RETURN_FLOAT;
46 RegLocation res = isFloat ? fpr_res : gpr_res;
Bill Buzbeea114add2012-05-03 15:00:40 -070047 oatClobber(cUnit, res.lowReg);
48 if (cUnit->instructionSet == kMips) {
49 oatMarkInUse(cUnit, res.lowReg);
50 } else {
51 oatLockTemp(cUnit, res.lowReg);
52 }
53 return res;
buzbeee3acd072012-02-25 17:03:10 -080054}
55
buzbee3b3dbdd2012-06-13 13:39:34 -070056void genInvoke(CompilationUnit* cUnit, CallInfo* info)
buzbeee3acd072012-02-25 17:03:10 -080057{
buzbee15bf9802012-06-12 17:49:27 -070058 if (genIntrinsic(cUnit, info)) {
Bill Buzbeea114add2012-05-03 15:00:40 -070059 return;
60 }
buzbee15bf9802012-06-12 17:49:27 -070061 InvokeType originalType = info->type; // avoiding mutation by ComputeInvokeInfo
Bill Buzbeea114add2012-05-03 15:00:40 -070062 int callState = 0;
63 LIR* nullCk;
64 LIR** pNullCk = NULL;
65 NextCallInsn nextCallInsn;
66 oatFlushAllRegs(cUnit); /* Everything to home location */
67 // Explicit register usage
68 oatLockCallTemps(cUnit);
buzbeee3acd072012-02-25 17:03:10 -080069
Bill Buzbeea114add2012-05-03 15:00:40 -070070 OatCompilationUnit mUnit(cUnit->class_loader, cUnit->class_linker,
71 *cUnit->dex_file, *cUnit->dex_cache,
72 cUnit->code_item, cUnit->method_idx,
73 cUnit->access_flags);
Logan Chien4dd96f52012-02-29 01:26:58 +080074
buzbee3b3dbdd2012-06-13 13:39:34 -070075 uint32_t dexMethodIdx = info->index;
Bill Buzbeea114add2012-05-03 15:00:40 -070076 int vtableIdx;
77 uintptr_t directCode;
78 uintptr_t directMethod;
79 bool skipThis;
80 bool fastPath =
buzbee15bf9802012-06-12 17:49:27 -070081 cUnit->compiler->ComputeInvokeInfo(dexMethodIdx, &mUnit, info->type,
Bill Buzbeea114add2012-05-03 15:00:40 -070082 vtableIdx, directCode,
83 directMethod)
84 && !SLOW_INVOKE_PATH;
buzbee15bf9802012-06-12 17:49:27 -070085 if (info->type == kInterface) {
Bill Buzbeea114add2012-05-03 15:00:40 -070086 nextCallInsn = fastPath ? nextInterfaceCallInsn
87 : nextInterfaceCallInsnWithAccessCheck;
88 skipThis = false;
buzbee15bf9802012-06-12 17:49:27 -070089 } else if (info->type == kDirect) {
Bill Buzbeea114add2012-05-03 15:00:40 -070090 if (fastPath) {
91 pNullCk = &nullCk;
buzbeee3acd072012-02-25 17:03:10 -080092 }
Bill Buzbeea114add2012-05-03 15:00:40 -070093 nextCallInsn = fastPath ? nextSDCallInsn : nextDirectCallInsnSP;
94 skipThis = false;
buzbee15bf9802012-06-12 17:49:27 -070095 } else if (info->type == kStatic) {
Bill Buzbeea114add2012-05-03 15:00:40 -070096 nextCallInsn = fastPath ? nextSDCallInsn : nextStaticCallInsnSP;
97 skipThis = false;
buzbee15bf9802012-06-12 17:49:27 -070098 } else if (info->type == kSuper) {
Bill Buzbeea114add2012-05-03 15:00:40 -070099 DCHECK(!fastPath); // Fast path is a direct call.
100 nextCallInsn = nextSuperCallInsnSP;
101 skipThis = false;
102 } else {
buzbee15bf9802012-06-12 17:49:27 -0700103 DCHECK_EQ(info->type, kVirtual);
Bill Buzbeea114add2012-05-03 15:00:40 -0700104 nextCallInsn = fastPath ? nextVCallInsn : nextVCallInsnSP;
105 skipThis = fastPath;
106 }
buzbee15bf9802012-06-12 17:49:27 -0700107 if (!info->isRange) {
108 callState = genDalvikArgsNoRange(cUnit, info, callState, pNullCk,
Bill Buzbeea114add2012-05-03 15:00:40 -0700109 nextCallInsn, dexMethodIdx,
110 vtableIdx, directCode, directMethod,
111 originalType, skipThis);
112 } else {
buzbee15bf9802012-06-12 17:49:27 -0700113 callState = genDalvikArgsRange(cUnit, info, callState, pNullCk,
Bill Buzbeea114add2012-05-03 15:00:40 -0700114 nextCallInsn, dexMethodIdx, vtableIdx,
115 directCode, directMethod, originalType,
116 skipThis);
117 }
118 // Finish up any of the call sequence not interleaved in arg loading
119 while (callState >= 0) {
buzbee15bf9802012-06-12 17:49:27 -0700120 callState = nextCallInsn(cUnit, info, callState, dexMethodIdx,
Bill Buzbeea114add2012-05-03 15:00:40 -0700121 vtableIdx, directCode, directMethod,
122 originalType);
123 }
124 if (DISPLAY_MISSING_TARGETS) {
125 genShowTarget(cUnit);
126 }
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700127#if !defined(TARGET_X86)
Bill Buzbeea114add2012-05-03 15:00:40 -0700128 opReg(cUnit, kOpBlx, rINVOKE_TGT);
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700129#else
buzbee15bf9802012-06-12 17:49:27 -0700130 if (fastPath && info->type != kInterface) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700131 opMem(cUnit, kOpBlx, rARG0, Method::GetCodeOffset().Int32Value());
132 } else {
133 int trampoline = 0;
buzbee15bf9802012-06-12 17:49:27 -0700134 switch (info->type) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700135 case kInterface:
136 trampoline = fastPath ? ENTRYPOINT_OFFSET(pInvokeInterfaceTrampoline)
137 : ENTRYPOINT_OFFSET(pInvokeInterfaceTrampolineWithAccessCheck);
138 break;
139 case kDirect:
140 trampoline = ENTRYPOINT_OFFSET(pInvokeDirectTrampolineWithAccessCheck);
141 break;
142 case kStatic:
143 trampoline = ENTRYPOINT_OFFSET(pInvokeStaticTrampolineWithAccessCheck);
144 break;
145 case kSuper:
146 trampoline = ENTRYPOINT_OFFSET(pInvokeSuperTrampolineWithAccessCheck);
147 break;
148 case kVirtual:
149 trampoline = ENTRYPOINT_OFFSET(pInvokeVirtualTrampolineWithAccessCheck);
150 break;
151 default:
152 LOG(FATAL) << "Unexpected invoke type";
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700153 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700154 opThreadMem(cUnit, kOpBlx, trampoline);
155 }
buzbeea7678db2012-03-05 15:35:46 -0800156#endif
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700157
Bill Buzbeea114add2012-05-03 15:00:40 -0700158 oatClobberCalleeSave(cUnit);
buzbee15bf9802012-06-12 17:49:27 -0700159 if (info->result.location != kLocInvalid) {
160 // We have a following MOVE_RESULT - do it now.
161 if (info->result.wide) {
buzbee52ed7762012-06-13 23:43:14 -0700162 RegLocation retLoc = oatGetReturnWide(cUnit, info->result.fp);
buzbee15bf9802012-06-12 17:49:27 -0700163 storeValueWide(cUnit, info->result, retLoc);
164 } else {
buzbee52ed7762012-06-13 23:43:14 -0700165 RegLocation retLoc = oatGetReturn(cUnit, info->result.fp);
buzbee15bf9802012-06-12 17:49:27 -0700166 storeValue(cUnit, info->result, retLoc);
167 }
168 }
169}
170
171/*
172 * Build an array of location records for the incoming arguments.
173 * Note: one location record per word of arguments, with dummy
174 * high-word loc for wide arguments. Also pull up any following
175 * MOVE_RESULT and incorporate it into the invoke.
176 */
buzbee3b3dbdd2012-06-13 13:39:34 -0700177CallInfo* newCallInfo(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir,
178 InvokeType type, bool isRange)
buzbee15bf9802012-06-12 17:49:27 -0700179{
buzbee3b3dbdd2012-06-13 13:39:34 -0700180 CallInfo* info = (CallInfo*)oatNew(cUnit, sizeof(CallInfo), true,
buzbee15bf9802012-06-12 17:49:27 -0700181 kAllocMisc);
buzbee52ed7762012-06-13 23:43:14 -0700182#if defined(TARGET_X86)
183 info->result.location = kLocInvalid;
184#else
buzbee15bf9802012-06-12 17:49:27 -0700185 MIR* moveResultMIR = oatFindMoveResult(cUnit, bb, mir);
186 if (moveResultMIR == NULL) {
187 info->result.location = kLocInvalid;
188 } else {
189 info->result = oatGetRawDest(cUnit, moveResultMIR);
190 moveResultMIR->dalvikInsn.opcode = Instruction::NOP;
191 }
buzbee52ed7762012-06-13 23:43:14 -0700192#endif
buzbee15bf9802012-06-12 17:49:27 -0700193 info->numArgWords = mir->ssaRep->numUses;
194 info->args = (info->numArgWords == 0) ? NULL : (RegLocation*)
195 oatNew(cUnit, sizeof(RegLocation) * info->numArgWords, false, kAllocMisc);
196 for (int i = 0; i < info->numArgWords; i++) {
197 info->args[i] = oatGetRawSrc(cUnit, mir, i);
198 }
199 info->optFlags = mir->optimizationFlags;
200 info->type = type;
201 info->isRange = isRange;
buzbee3b3dbdd2012-06-13 13:39:34 -0700202 info->index = mir->dalvikInsn.vB;
buzbee15bf9802012-06-12 17:49:27 -0700203 info->offset = mir->offset;
204 return info;
buzbeee3acd072012-02-25 17:03:10 -0800205}
206
207/*
208 * Target-independent code generation. Use only high-level
209 * load/store utilities here, or target-dependent genXX() handlers
210 * when necessary.
211 */
buzbee31a4a6f2012-02-28 15:36:15 -0800212bool compileDalvikInstruction(CompilationUnit* cUnit, MIR* mir,
213 BasicBlock* bb, LIR* labelList)
buzbeee3acd072012-02-25 17:03:10 -0800214{
Bill Buzbeea114add2012-05-03 15:00:40 -0700215 bool res = false; // Assume success
216 RegLocation rlSrc[3];
217 RegLocation rlDest = badLoc;
218 RegLocation rlResult = badLoc;
219 Instruction::Code opcode = mir->dalvikInsn.opcode;
buzbee408ad162012-06-06 16:45:18 -0700220 int optFlags = mir->optimizationFlags;
221 uint32_t vA = mir->dalvikInsn.vA;
222 uint32_t vB = mir->dalvikInsn.vB;
223 uint32_t vC = mir->dalvikInsn.vC;
buzbeee3acd072012-02-25 17:03:10 -0800224
Bill Buzbeea114add2012-05-03 15:00:40 -0700225 /* Prep Src and Dest locations */
226 int nextSreg = 0;
227 int nextLoc = 0;
228 int attrs = oatDataFlowAttributes[opcode];
229 rlSrc[0] = rlSrc[1] = rlSrc[2] = badLoc;
230 if (attrs & DF_UA) {
buzbeebff24652012-05-06 16:22:05 -0700231 if (attrs & DF_A_WIDE) {
buzbee15bf9802012-06-12 17:49:27 -0700232 rlSrc[nextLoc++] = oatGetSrcWide(cUnit, mir, nextSreg);
buzbeebff24652012-05-06 16:22:05 -0700233 nextSreg+= 2;
234 } else {
235 rlSrc[nextLoc++] = oatGetSrc(cUnit, mir, nextSreg);
236 nextSreg++;
237 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700238 }
239 if (attrs & DF_UB) {
buzbeebff24652012-05-06 16:22:05 -0700240 if (attrs & DF_B_WIDE) {
buzbee15bf9802012-06-12 17:49:27 -0700241 rlSrc[nextLoc++] = oatGetSrcWide(cUnit, mir, nextSreg);
buzbeebff24652012-05-06 16:22:05 -0700242 nextSreg+= 2;
243 } else {
244 rlSrc[nextLoc++] = oatGetSrc(cUnit, mir, nextSreg);
245 nextSreg++;
246 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700247 }
248 if (attrs & DF_UC) {
buzbeebff24652012-05-06 16:22:05 -0700249 if (attrs & DF_C_WIDE) {
buzbee15bf9802012-06-12 17:49:27 -0700250 rlSrc[nextLoc++] = oatGetSrcWide(cUnit, mir, nextSreg);
buzbeebff24652012-05-06 16:22:05 -0700251 } else {
252 rlSrc[nextLoc++] = oatGetSrc(cUnit, mir, nextSreg);
253 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700254 }
255 if (attrs & DF_DA) {
buzbeebff24652012-05-06 16:22:05 -0700256 if (attrs & DF_A_WIDE) {
buzbee15bf9802012-06-12 17:49:27 -0700257 rlDest = oatGetDestWide(cUnit, mir);
buzbeebff24652012-05-06 16:22:05 -0700258 } else {
buzbee15bf9802012-06-12 17:49:27 -0700259 rlDest = oatGetDest(cUnit, mir);
buzbeebff24652012-05-06 16:22:05 -0700260 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700261 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700262 switch (opcode) {
263 case Instruction::NOP:
264 break;
buzbeee3acd072012-02-25 17:03:10 -0800265
Bill Buzbeea114add2012-05-03 15:00:40 -0700266 case Instruction::MOVE_EXCEPTION: {
267 int exOffset = Thread::ExceptionOffset().Int32Value();
268 rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
Ian Rogersc6f3bb82012-03-21 20:40:33 -0700269#if defined(TARGET_X86)
Bill Buzbeea114add2012-05-03 15:00:40 -0700270 newLIR2(cUnit, kX86Mov32RT, rlResult.lowReg, exOffset);
271 newLIR2(cUnit, kX86Mov32TI, exOffset, 0);
Ian Rogersc6f3bb82012-03-21 20:40:33 -0700272#else
Bill Buzbeea114add2012-05-03 15:00:40 -0700273 int resetReg = oatAllocTemp(cUnit);
274 loadWordDisp(cUnit, rSELF, exOffset, rlResult.lowReg);
275 loadConstant(cUnit, resetReg, 0);
276 storeWordDisp(cUnit, rSELF, exOffset, resetReg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700277 oatFreeTemp(cUnit, resetReg);
buzbeea7678db2012-03-05 15:35:46 -0800278#endif
jeffhao41005dd2012-05-09 17:58:52 -0700279 storeValue(cUnit, rlDest, rlResult);
Bill Buzbeea114add2012-05-03 15:00:40 -0700280 break;
buzbeee3acd072012-02-25 17:03:10 -0800281 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700282 case Instruction::RETURN_VOID:
283 if (!cUnit->attrs & METHOD_IS_LEAF) {
buzbee408ad162012-06-06 16:45:18 -0700284 genSuspendTest(cUnit, optFlags);
Bill Buzbeea114add2012-05-03 15:00:40 -0700285 }
286 break;
287
288 case Instruction::RETURN:
289 case Instruction::RETURN_OBJECT:
290 if (!cUnit->attrs & METHOD_IS_LEAF) {
buzbee408ad162012-06-06 16:45:18 -0700291 genSuspendTest(cUnit, optFlags);
Bill Buzbeea114add2012-05-03 15:00:40 -0700292 }
293 storeValue(cUnit, oatGetReturn(cUnit, cUnit->shorty[0] == 'F'), rlSrc[0]);
294 break;
295
296 case Instruction::RETURN_WIDE:
297 if (!cUnit->attrs & METHOD_IS_LEAF) {
buzbee408ad162012-06-06 16:45:18 -0700298 genSuspendTest(cUnit, optFlags);
Bill Buzbeea114add2012-05-03 15:00:40 -0700299 }
300 storeValueWide(cUnit, oatGetReturnWide(cUnit,
301 cUnit->shorty[0] == 'D'), rlSrc[0]);
302 break;
303
304 case Instruction::MOVE_RESULT_WIDE:
buzbee408ad162012-06-06 16:45:18 -0700305 if (optFlags & MIR_INLINED)
Bill Buzbeea114add2012-05-03 15:00:40 -0700306 break; // Nop - combined w/ previous invoke
307 storeValueWide(cUnit, rlDest, oatGetReturnWide(cUnit, rlDest.fp));
308 break;
309
310 case Instruction::MOVE_RESULT:
311 case Instruction::MOVE_RESULT_OBJECT:
buzbee408ad162012-06-06 16:45:18 -0700312 if (optFlags & MIR_INLINED)
Bill Buzbeea114add2012-05-03 15:00:40 -0700313 break; // Nop - combined w/ previous invoke
314 storeValue(cUnit, rlDest, oatGetReturn(cUnit, rlDest.fp));
315 break;
316
317 case Instruction::MOVE:
318 case Instruction::MOVE_OBJECT:
319 case Instruction::MOVE_16:
320 case Instruction::MOVE_OBJECT_16:
321 case Instruction::MOVE_FROM16:
322 case Instruction::MOVE_OBJECT_FROM16:
323 storeValue(cUnit, rlDest, rlSrc[0]);
324 break;
325
326 case Instruction::MOVE_WIDE:
327 case Instruction::MOVE_WIDE_16:
328 case Instruction::MOVE_WIDE_FROM16:
329 storeValueWide(cUnit, rlDest, rlSrc[0]);
330 break;
331
332 case Instruction::CONST:
333 case Instruction::CONST_4:
334 case Instruction::CONST_16:
335 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
buzbee408ad162012-06-06 16:45:18 -0700336 loadConstantNoClobber(cUnit, rlResult.lowReg, vB);
Bill Buzbeea114add2012-05-03 15:00:40 -0700337 storeValue(cUnit, rlDest, rlResult);
338 break;
339
340 case Instruction::CONST_HIGH16:
341 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
buzbee408ad162012-06-06 16:45:18 -0700342 loadConstantNoClobber(cUnit, rlResult.lowReg, vB << 16);
Bill Buzbeea114add2012-05-03 15:00:40 -0700343 storeValue(cUnit, rlDest, rlResult);
344 break;
345
346 case Instruction::CONST_WIDE_16:
347 case Instruction::CONST_WIDE_32:
348 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
buzbee408ad162012-06-06 16:45:18 -0700349 loadConstantValueWide(cUnit, rlResult.lowReg, rlResult.highReg, vB,
350 (vB & 0x80000000) ? -1 : 0);
Bill Buzbeea114add2012-05-03 15:00:40 -0700351 storeValueWide(cUnit, rlDest, rlResult);
352 break;
353
354 case Instruction::CONST_WIDE:
355 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
356 loadConstantValueWide(cUnit, rlResult.lowReg, rlResult.highReg,
357 mir->dalvikInsn.vB_wide & 0xffffffff,
358 (mir->dalvikInsn.vB_wide >> 32) & 0xffffffff);
359 storeValueWide(cUnit, rlDest, rlResult);
360 break;
361
362 case Instruction::CONST_WIDE_HIGH16:
363 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
364 loadConstantValueWide(cUnit, rlResult.lowReg, rlResult.highReg,
buzbee408ad162012-06-06 16:45:18 -0700365 0, vB << 16);
Bill Buzbeea114add2012-05-03 15:00:40 -0700366 storeValueWide(cUnit, rlDest, rlResult);
367 break;
368
369 case Instruction::MONITOR_ENTER:
buzbee408ad162012-06-06 16:45:18 -0700370 genMonitorEnter(cUnit, optFlags, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700371 break;
372
373 case Instruction::MONITOR_EXIT:
buzbee408ad162012-06-06 16:45:18 -0700374 genMonitorExit(cUnit, optFlags, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700375 break;
376
377 case Instruction::CHECK_CAST:
buzbee408ad162012-06-06 16:45:18 -0700378 genCheckCast(cUnit, vB, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700379 break;
380
381 case Instruction::INSTANCE_OF:
buzbee408ad162012-06-06 16:45:18 -0700382 genInstanceof(cUnit, vC, rlDest, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700383 break;
384
385 case Instruction::NEW_INSTANCE:
buzbee408ad162012-06-06 16:45:18 -0700386 genNewInstance(cUnit, vB, rlDest);
Bill Buzbeea114add2012-05-03 15:00:40 -0700387 break;
388
389 case Instruction::THROW:
buzbee408ad162012-06-06 16:45:18 -0700390 genThrow(cUnit, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700391 break;
392
393 case Instruction::THROW_VERIFICATION_ERROR:
buzbee408ad162012-06-06 16:45:18 -0700394 genThrowVerificationError(cUnit, vA, vB);
Bill Buzbeea114add2012-05-03 15:00:40 -0700395 break;
396
397 case Instruction::ARRAY_LENGTH:
398 int lenOffset;
399 lenOffset = Array::LengthOffset().Int32Value();
400 rlSrc[0] = loadValue(cUnit, rlSrc[0], kCoreReg);
buzbee408ad162012-06-06 16:45:18 -0700401 genNullCheck(cUnit, rlSrc[0].sRegLow, rlSrc[0].lowReg, optFlags);
Bill Buzbeea114add2012-05-03 15:00:40 -0700402 rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
403 loadWordDisp(cUnit, rlSrc[0].lowReg, lenOffset, rlResult.lowReg);
404 storeValue(cUnit, rlDest, rlResult);
405 break;
406
407 case Instruction::CONST_STRING:
408 case Instruction::CONST_STRING_JUMBO:
buzbee408ad162012-06-06 16:45:18 -0700409 genConstString(cUnit, vB, rlDest, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700410 break;
411
412 case Instruction::CONST_CLASS:
buzbee408ad162012-06-06 16:45:18 -0700413 genConstClass(cUnit, vB, rlDest, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700414 break;
415
416 case Instruction::FILL_ARRAY_DATA:
buzbee408ad162012-06-06 16:45:18 -0700417 genFillArrayData(cUnit, vB, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700418 break;
419
420 case Instruction::FILLED_NEW_ARRAY:
buzbee3b3dbdd2012-06-13 13:39:34 -0700421 genFilledNewArray(cUnit, newCallInfo(cUnit, bb, mir, kStatic,
422 false /* not range */));
Bill Buzbeea114add2012-05-03 15:00:40 -0700423 break;
424
425 case Instruction::FILLED_NEW_ARRAY_RANGE:
buzbee3b3dbdd2012-06-13 13:39:34 -0700426 genFilledNewArray(cUnit, newCallInfo(cUnit, bb, mir, kStatic,
427 true /* range */));
Bill Buzbeea114add2012-05-03 15:00:40 -0700428 break;
429
430 case Instruction::NEW_ARRAY:
buzbee408ad162012-06-06 16:45:18 -0700431 genNewArray(cUnit, vC, rlDest, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700432 break;
433
434 case Instruction::GOTO:
435 case Instruction::GOTO_16:
436 case Instruction::GOTO_32:
437 if (bb->taken->startOffset <= mir->offset) {
buzbee408ad162012-06-06 16:45:18 -0700438 genSuspendTestAndBranch(cUnit, optFlags, &labelList[bb->taken->id]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700439 } else {
440 opUnconditionalBranch(cUnit, &labelList[bb->taken->id]);
441 }
442 break;
443
444 case Instruction::PACKED_SWITCH:
buzbee408ad162012-06-06 16:45:18 -0700445 genPackedSwitch(cUnit, vB, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700446 break;
447
448 case Instruction::SPARSE_SWITCH:
buzbee408ad162012-06-06 16:45:18 -0700449 genSparseSwitch(cUnit, vB, rlSrc[0], labelList);
Bill Buzbeea114add2012-05-03 15:00:40 -0700450 break;
451
452 case Instruction::CMPL_FLOAT:
453 case Instruction::CMPG_FLOAT:
454 case Instruction::CMPL_DOUBLE:
455 case Instruction::CMPG_DOUBLE:
buzbee408ad162012-06-06 16:45:18 -0700456 res = genCmpFP(cUnit, opcode, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700457 break;
458
459 case Instruction::CMP_LONG:
buzbee408ad162012-06-06 16:45:18 -0700460 genCmpLong(cUnit, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700461 break;
462
463 case Instruction::IF_EQ:
464 case Instruction::IF_NE:
465 case Instruction::IF_LT:
466 case Instruction::IF_GE:
467 case Instruction::IF_GT:
468 case Instruction::IF_LE: {
buzbee3b3dbdd2012-06-13 13:39:34 -0700469 LIR* taken = &labelList[bb->taken->id];
470 LIR* fallThrough = &labelList[bb->fallThrough->id];
Bill Buzbeea114add2012-05-03 15:00:40 -0700471 bool backwardBranch;
472 backwardBranch = (bb->taken->startOffset <= mir->offset);
473 if (backwardBranch) {
buzbee408ad162012-06-06 16:45:18 -0700474 genSuspendTest(cUnit, optFlags);
Bill Buzbeea114add2012-05-03 15:00:40 -0700475 }
buzbee3b3dbdd2012-06-13 13:39:34 -0700476 genCompareAndBranch(cUnit, opcode, rlSrc[0], rlSrc[1], taken,
477 fallThrough);
Bill Buzbeea114add2012-05-03 15:00:40 -0700478 break;
479 }
480
481 case Instruction::IF_EQZ:
482 case Instruction::IF_NEZ:
483 case Instruction::IF_LTZ:
484 case Instruction::IF_GEZ:
485 case Instruction::IF_GTZ:
486 case Instruction::IF_LEZ: {
buzbee3b3dbdd2012-06-13 13:39:34 -0700487 LIR* taken = &labelList[bb->taken->id];
488 LIR* fallThrough = &labelList[bb->fallThrough->id];
Bill Buzbeea114add2012-05-03 15:00:40 -0700489 bool backwardBranch;
490 backwardBranch = (bb->taken->startOffset <= mir->offset);
491 if (backwardBranch) {
buzbee408ad162012-06-06 16:45:18 -0700492 genSuspendTest(cUnit, optFlags);
Bill Buzbeea114add2012-05-03 15:00:40 -0700493 }
buzbee3b3dbdd2012-06-13 13:39:34 -0700494 genCompareZeroAndBranch(cUnit, opcode, rlSrc[0], taken, fallThrough);
Bill Buzbeea114add2012-05-03 15:00:40 -0700495 break;
496 }
497
498 case Instruction::AGET_WIDE:
buzbee408ad162012-06-06 16:45:18 -0700499 genArrayGet(cUnit, optFlags, kLong, rlSrc[0], rlSrc[1], rlDest, 3);
Bill Buzbeea114add2012-05-03 15:00:40 -0700500 break;
501 case Instruction::AGET:
502 case Instruction::AGET_OBJECT:
buzbee408ad162012-06-06 16:45:18 -0700503 genArrayGet(cUnit, optFlags, kWord, rlSrc[0], rlSrc[1], rlDest, 2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700504 break;
505 case Instruction::AGET_BOOLEAN:
buzbee408ad162012-06-06 16:45:18 -0700506 genArrayGet(cUnit, optFlags, kUnsignedByte, rlSrc[0], rlSrc[1], rlDest, 0);
Bill Buzbeea114add2012-05-03 15:00:40 -0700507 break;
508 case Instruction::AGET_BYTE:
buzbee408ad162012-06-06 16:45:18 -0700509 genArrayGet(cUnit, optFlags, kSignedByte, rlSrc[0], rlSrc[1], rlDest, 0);
Bill Buzbeea114add2012-05-03 15:00:40 -0700510 break;
511 case Instruction::AGET_CHAR:
buzbee408ad162012-06-06 16:45:18 -0700512 genArrayGet(cUnit, optFlags, kUnsignedHalf, rlSrc[0], rlSrc[1], rlDest, 1);
Bill Buzbeea114add2012-05-03 15:00:40 -0700513 break;
514 case Instruction::AGET_SHORT:
buzbee408ad162012-06-06 16:45:18 -0700515 genArrayGet(cUnit, optFlags, kSignedHalf, rlSrc[0], rlSrc[1], rlDest, 1);
Bill Buzbeea114add2012-05-03 15:00:40 -0700516 break;
517 case Instruction::APUT_WIDE:
buzbee408ad162012-06-06 16:45:18 -0700518 genArrayPut(cUnit, optFlags, kLong, rlSrc[1], rlSrc[2], rlSrc[0], 3);
Bill Buzbeea114add2012-05-03 15:00:40 -0700519 break;
520 case Instruction::APUT:
buzbee408ad162012-06-06 16:45:18 -0700521 genArrayPut(cUnit, optFlags, kWord, rlSrc[1], rlSrc[2], rlSrc[0], 2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700522 break;
523 case Instruction::APUT_OBJECT:
buzbee408ad162012-06-06 16:45:18 -0700524 genArrayObjPut(cUnit, optFlags, rlSrc[1], rlSrc[2], rlSrc[0], 2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700525 break;
526 case Instruction::APUT_SHORT:
527 case Instruction::APUT_CHAR:
buzbee408ad162012-06-06 16:45:18 -0700528 genArrayPut(cUnit, optFlags, kUnsignedHalf, rlSrc[1], rlSrc[2], rlSrc[0], 1);
Bill Buzbeea114add2012-05-03 15:00:40 -0700529 break;
530 case Instruction::APUT_BYTE:
531 case Instruction::APUT_BOOLEAN:
buzbee408ad162012-06-06 16:45:18 -0700532 genArrayPut(cUnit, optFlags, kUnsignedByte, rlSrc[1], rlSrc[2],
Bill Buzbeea114add2012-05-03 15:00:40 -0700533 rlSrc[0], 0);
534 break;
535
536 case Instruction::IGET_OBJECT:
537 //case Instruction::IGET_OBJECT_VOLATILE:
buzbee408ad162012-06-06 16:45:18 -0700538 genIGet(cUnit, vC, optFlags, kWord, rlDest, rlSrc[0], false, true);
Bill Buzbeea114add2012-05-03 15:00:40 -0700539 break;
540
541 case Instruction::IGET_WIDE:
542 //case Instruction::IGET_WIDE_VOLATILE:
buzbee408ad162012-06-06 16:45:18 -0700543 genIGet(cUnit, vC, optFlags, kLong, rlDest, rlSrc[0], true, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700544 break;
545
546 case Instruction::IGET:
547 //case Instruction::IGET_VOLATILE:
buzbee408ad162012-06-06 16:45:18 -0700548 genIGet(cUnit, vC, optFlags, kWord, rlDest, rlSrc[0], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700549 break;
550
551 case Instruction::IGET_CHAR:
buzbee408ad162012-06-06 16:45:18 -0700552 genIGet(cUnit, vC, optFlags, kUnsignedHalf, rlDest, rlSrc[0], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700553 break;
554
555 case Instruction::IGET_SHORT:
buzbee408ad162012-06-06 16:45:18 -0700556 genIGet(cUnit, vC, optFlags, kSignedHalf, rlDest, rlSrc[0], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700557 break;
558
559 case Instruction::IGET_BOOLEAN:
560 case Instruction::IGET_BYTE:
buzbee408ad162012-06-06 16:45:18 -0700561 genIGet(cUnit, vC, optFlags, kUnsignedByte, rlDest, rlSrc[0], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700562 break;
563
564 case Instruction::IPUT_WIDE:
565 //case Instruction::IPUT_WIDE_VOLATILE:
buzbee408ad162012-06-06 16:45:18 -0700566 genIPut(cUnit, vC, optFlags, kLong, rlSrc[0], rlSrc[1], true, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700567 break;
568
569 case Instruction::IPUT_OBJECT:
570 //case Instruction::IPUT_OBJECT_VOLATILE:
buzbee408ad162012-06-06 16:45:18 -0700571 genIPut(cUnit, vC, optFlags, kWord, rlSrc[0], rlSrc[1], false, true);
Bill Buzbeea114add2012-05-03 15:00:40 -0700572 break;
573
574 case Instruction::IPUT:
575 //case Instruction::IPUT_VOLATILE:
buzbee408ad162012-06-06 16:45:18 -0700576 genIPut(cUnit, vC, optFlags, kWord, rlSrc[0], rlSrc[1], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700577 break;
578
579 case Instruction::IPUT_BOOLEAN:
580 case Instruction::IPUT_BYTE:
buzbee408ad162012-06-06 16:45:18 -0700581 genIPut(cUnit, vC, optFlags, kUnsignedByte, rlSrc[0], rlSrc[1], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700582 break;
583
584 case Instruction::IPUT_CHAR:
buzbee408ad162012-06-06 16:45:18 -0700585 genIPut(cUnit, vC, optFlags, kUnsignedHalf, rlSrc[0], rlSrc[1], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700586 break;
587
588 case Instruction::IPUT_SHORT:
buzbee408ad162012-06-06 16:45:18 -0700589 genIPut(cUnit, vC, optFlags, kSignedHalf, rlSrc[0], rlSrc[1], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700590 break;
591
592 case Instruction::SGET_OBJECT:
buzbee408ad162012-06-06 16:45:18 -0700593 genSget(cUnit, vB, rlDest, false, true);
Bill Buzbeea114add2012-05-03 15:00:40 -0700594 break;
595 case Instruction::SGET:
596 case Instruction::SGET_BOOLEAN:
597 case Instruction::SGET_BYTE:
598 case Instruction::SGET_CHAR:
599 case Instruction::SGET_SHORT:
buzbee408ad162012-06-06 16:45:18 -0700600 genSget(cUnit, vB, rlDest, false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700601 break;
602
603 case Instruction::SGET_WIDE:
buzbee408ad162012-06-06 16:45:18 -0700604 genSget(cUnit, vB, rlDest, true, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700605 break;
606
607 case Instruction::SPUT_OBJECT:
buzbee408ad162012-06-06 16:45:18 -0700608 genSput(cUnit, vB, rlSrc[0], false, true);
Bill Buzbeea114add2012-05-03 15:00:40 -0700609 break;
610
611 case Instruction::SPUT:
612 case Instruction::SPUT_BOOLEAN:
613 case Instruction::SPUT_BYTE:
614 case Instruction::SPUT_CHAR:
615 case Instruction::SPUT_SHORT:
buzbee408ad162012-06-06 16:45:18 -0700616 genSput(cUnit, vB, rlSrc[0], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700617 break;
618
619 case Instruction::SPUT_WIDE:
buzbee408ad162012-06-06 16:45:18 -0700620 genSput(cUnit, vB, rlSrc[0], true, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700621 break;
622
623 case Instruction::INVOKE_STATIC_RANGE:
buzbee3b3dbdd2012-06-13 13:39:34 -0700624 genInvoke(cUnit, newCallInfo(cUnit, bb, mir, kStatic, true));
Bill Buzbeea114add2012-05-03 15:00:40 -0700625 break;
626 case Instruction::INVOKE_STATIC:
buzbee3b3dbdd2012-06-13 13:39:34 -0700627 genInvoke(cUnit, newCallInfo(cUnit, bb, mir, kStatic, false));
Bill Buzbeea114add2012-05-03 15:00:40 -0700628 break;
629
630 case Instruction::INVOKE_DIRECT:
buzbee3b3dbdd2012-06-13 13:39:34 -0700631 genInvoke(cUnit, newCallInfo(cUnit, bb, mir, kDirect, false));
Bill Buzbeea114add2012-05-03 15:00:40 -0700632 break;
633 case Instruction::INVOKE_DIRECT_RANGE:
buzbee3b3dbdd2012-06-13 13:39:34 -0700634 genInvoke(cUnit, newCallInfo(cUnit, bb, mir, kDirect, true));
Bill Buzbeea114add2012-05-03 15:00:40 -0700635 break;
636
637 case Instruction::INVOKE_VIRTUAL:
buzbee3b3dbdd2012-06-13 13:39:34 -0700638 genInvoke(cUnit, newCallInfo(cUnit, bb, mir, kVirtual, false));
Bill Buzbeea114add2012-05-03 15:00:40 -0700639 break;
640 case Instruction::INVOKE_VIRTUAL_RANGE:
buzbee3b3dbdd2012-06-13 13:39:34 -0700641 genInvoke(cUnit, newCallInfo(cUnit, bb, mir, kVirtual, true));
Bill Buzbeea114add2012-05-03 15:00:40 -0700642 break;
643
644 case Instruction::INVOKE_SUPER:
buzbee3b3dbdd2012-06-13 13:39:34 -0700645 genInvoke(cUnit, newCallInfo(cUnit, bb, mir, kSuper, false));
Bill Buzbeea114add2012-05-03 15:00:40 -0700646 break;
647 case Instruction::INVOKE_SUPER_RANGE:
buzbee3b3dbdd2012-06-13 13:39:34 -0700648 genInvoke(cUnit, newCallInfo(cUnit, bb, mir, kSuper, true));
Bill Buzbeea114add2012-05-03 15:00:40 -0700649 break;
650
651 case Instruction::INVOKE_INTERFACE:
buzbee3b3dbdd2012-06-13 13:39:34 -0700652 genInvoke(cUnit, newCallInfo(cUnit, bb, mir, kInterface, false));
Bill Buzbeea114add2012-05-03 15:00:40 -0700653 break;
654 case Instruction::INVOKE_INTERFACE_RANGE:
buzbee3b3dbdd2012-06-13 13:39:34 -0700655 genInvoke(cUnit, newCallInfo(cUnit, bb, mir, kInterface, true));
Bill Buzbeea114add2012-05-03 15:00:40 -0700656 break;
657
658 case Instruction::NEG_INT:
659 case Instruction::NOT_INT:
buzbee408ad162012-06-06 16:45:18 -0700660 res = genArithOpInt(cUnit, opcode, rlDest, rlSrc[0], rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700661 break;
662
663 case Instruction::NEG_LONG:
664 case Instruction::NOT_LONG:
buzbee408ad162012-06-06 16:45:18 -0700665 res = genArithOpLong(cUnit, opcode, rlDest, rlSrc[0], rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700666 break;
667
668 case Instruction::NEG_FLOAT:
buzbee408ad162012-06-06 16:45:18 -0700669 res = genArithOpFloat(cUnit, opcode, rlDest, rlSrc[0], rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700670 break;
671
672 case Instruction::NEG_DOUBLE:
buzbee408ad162012-06-06 16:45:18 -0700673 res = genArithOpDouble(cUnit, opcode, rlDest, rlSrc[0], rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700674 break;
675
676 case Instruction::INT_TO_LONG:
buzbee408ad162012-06-06 16:45:18 -0700677 genIntToLong(cUnit, rlDest, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700678 break;
679
680 case Instruction::LONG_TO_INT:
681 rlSrc[0] = oatUpdateLocWide(cUnit, rlSrc[0]);
682 rlSrc[0] = oatWideToNarrow(cUnit, rlSrc[0]);
683 storeValue(cUnit, rlDest, rlSrc[0]);
684 break;
685
686 case Instruction::INT_TO_BYTE:
687 case Instruction::INT_TO_SHORT:
688 case Instruction::INT_TO_CHAR:
buzbee408ad162012-06-06 16:45:18 -0700689 genIntNarrowing(cUnit, opcode, rlDest, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700690 break;
691
692 case Instruction::INT_TO_FLOAT:
693 case Instruction::INT_TO_DOUBLE:
694 case Instruction::LONG_TO_FLOAT:
695 case Instruction::LONG_TO_DOUBLE:
696 case Instruction::FLOAT_TO_INT:
697 case Instruction::FLOAT_TO_LONG:
698 case Instruction::FLOAT_TO_DOUBLE:
699 case Instruction::DOUBLE_TO_INT:
700 case Instruction::DOUBLE_TO_LONG:
701 case Instruction::DOUBLE_TO_FLOAT:
buzbee408ad162012-06-06 16:45:18 -0700702 genConversion(cUnit, opcode, rlDest, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700703 break;
704
705 case Instruction::ADD_INT:
706 case Instruction::SUB_INT:
707 case Instruction::MUL_INT:
708 case Instruction::DIV_INT:
709 case Instruction::REM_INT:
710 case Instruction::AND_INT:
711 case Instruction::OR_INT:
712 case Instruction::XOR_INT:
713 case Instruction::SHL_INT:
714 case Instruction::SHR_INT:
715 case Instruction::USHR_INT:
716 case Instruction::ADD_INT_2ADDR:
717 case Instruction::SUB_INT_2ADDR:
718 case Instruction::MUL_INT_2ADDR:
719 case Instruction::DIV_INT_2ADDR:
720 case Instruction::REM_INT_2ADDR:
721 case Instruction::AND_INT_2ADDR:
722 case Instruction::OR_INT_2ADDR:
723 case Instruction::XOR_INT_2ADDR:
724 case Instruction::SHL_INT_2ADDR:
725 case Instruction::SHR_INT_2ADDR:
726 case Instruction::USHR_INT_2ADDR:
buzbee408ad162012-06-06 16:45:18 -0700727 genArithOpInt(cUnit, opcode, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700728 break;
729
730 case Instruction::ADD_LONG:
731 case Instruction::SUB_LONG:
732 case Instruction::MUL_LONG:
733 case Instruction::DIV_LONG:
734 case Instruction::REM_LONG:
735 case Instruction::AND_LONG:
736 case Instruction::OR_LONG:
737 case Instruction::XOR_LONG:
738 case Instruction::ADD_LONG_2ADDR:
739 case Instruction::SUB_LONG_2ADDR:
740 case Instruction::MUL_LONG_2ADDR:
741 case Instruction::DIV_LONG_2ADDR:
742 case Instruction::REM_LONG_2ADDR:
743 case Instruction::AND_LONG_2ADDR:
744 case Instruction::OR_LONG_2ADDR:
745 case Instruction::XOR_LONG_2ADDR:
buzbee408ad162012-06-06 16:45:18 -0700746 genArithOpLong(cUnit, opcode, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700747 break;
748
749 case Instruction::SHL_LONG:
750 case Instruction::SHR_LONG:
751 case Instruction::USHR_LONG:
752 case Instruction::SHL_LONG_2ADDR:
753 case Instruction::SHR_LONG_2ADDR:
754 case Instruction::USHR_LONG_2ADDR:
buzbee408ad162012-06-06 16:45:18 -0700755 genShiftOpLong(cUnit, opcode, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700756 break;
757
758 case Instruction::ADD_FLOAT:
759 case Instruction::SUB_FLOAT:
760 case Instruction::MUL_FLOAT:
761 case Instruction::DIV_FLOAT:
762 case Instruction::REM_FLOAT:
763 case Instruction::ADD_FLOAT_2ADDR:
764 case Instruction::SUB_FLOAT_2ADDR:
765 case Instruction::MUL_FLOAT_2ADDR:
766 case Instruction::DIV_FLOAT_2ADDR:
767 case Instruction::REM_FLOAT_2ADDR:
buzbee408ad162012-06-06 16:45:18 -0700768 genArithOpFloat(cUnit, opcode, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700769 break;
770
771 case Instruction::ADD_DOUBLE:
772 case Instruction::SUB_DOUBLE:
773 case Instruction::MUL_DOUBLE:
774 case Instruction::DIV_DOUBLE:
775 case Instruction::REM_DOUBLE:
776 case Instruction::ADD_DOUBLE_2ADDR:
777 case Instruction::SUB_DOUBLE_2ADDR:
778 case Instruction::MUL_DOUBLE_2ADDR:
779 case Instruction::DIV_DOUBLE_2ADDR:
780 case Instruction::REM_DOUBLE_2ADDR:
buzbee408ad162012-06-06 16:45:18 -0700781 genArithOpDouble(cUnit, opcode, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700782 break;
783
784 case Instruction::RSUB_INT:
785 case Instruction::ADD_INT_LIT16:
786 case Instruction::MUL_INT_LIT16:
787 case Instruction::DIV_INT_LIT16:
788 case Instruction::REM_INT_LIT16:
789 case Instruction::AND_INT_LIT16:
790 case Instruction::OR_INT_LIT16:
791 case Instruction::XOR_INT_LIT16:
792 case Instruction::ADD_INT_LIT8:
793 case Instruction::RSUB_INT_LIT8:
794 case Instruction::MUL_INT_LIT8:
795 case Instruction::DIV_INT_LIT8:
796 case Instruction::REM_INT_LIT8:
797 case Instruction::AND_INT_LIT8:
798 case Instruction::OR_INT_LIT8:
799 case Instruction::XOR_INT_LIT8:
800 case Instruction::SHL_INT_LIT8:
801 case Instruction::SHR_INT_LIT8:
802 case Instruction::USHR_INT_LIT8:
buzbee408ad162012-06-06 16:45:18 -0700803 genArithOpIntLit(cUnit, opcode, rlDest, rlSrc[0], vC);
Bill Buzbeea114add2012-05-03 15:00:40 -0700804 break;
805
806 default:
807 res = true;
808 }
809 return res;
buzbeee3acd072012-02-25 17:03:10 -0800810}
811
buzbee31a4a6f2012-02-28 15:36:15 -0800812const char* extendedMIROpNames[kMirOpLast - kMirOpFirst] = {
Bill Buzbeea114add2012-05-03 15:00:40 -0700813 "kMirOpPhi",
814 "kMirOpCopy",
815 "kMirFusedCmplFloat",
816 "kMirFusedCmpgFloat",
817 "kMirFusedCmplDouble",
818 "kMirFusedCmpgDouble",
819 "kMirFusedCmpLong",
820 "kMirNop",
821 "kMirOpNullNRangeUpCheck",
822 "kMirOpNullNRangeDownCheck",
823 "kMirOpLowerBound",
buzbeee3acd072012-02-25 17:03:10 -0800824};
825
826/* Extended MIR instructions like PHI */
buzbee84fd6932012-03-29 16:44:16 -0700827void handleExtendedMethodMIR(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir)
buzbeee3acd072012-02-25 17:03:10 -0800828{
Bill Buzbeea114add2012-05-03 15:00:40 -0700829 int opOffset = mir->dalvikInsn.opcode - kMirOpFirst;
830 char* msg = NULL;
831 if (cUnit->printMe) {
832 msg = (char*)oatNew(cUnit, strlen(extendedMIROpNames[opOffset]) + 1,
833 false, kAllocDebugInfo);
834 strcpy(msg, extendedMIROpNames[opOffset]);
835 }
836 LIR* op = newLIR1(cUnit, kPseudoExtended, (int) msg);
buzbeee3acd072012-02-25 17:03:10 -0800837
Bill Buzbeea114add2012-05-03 15:00:40 -0700838 switch ((ExtendedMIROpcode)mir->dalvikInsn.opcode) {
839 case kMirOpPhi: {
840 char* ssaString = NULL;
841 if (cUnit->printMe) {
842 ssaString = oatGetSSAString(cUnit, mir->ssaRep);
843 }
844 op->flags.isNop = true;
845 newLIR1(cUnit, kPseudoSSARep, (int) ssaString);
846 break;
buzbeee3acd072012-02-25 17:03:10 -0800847 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700848 case kMirOpCopy: {
849 RegLocation rlSrc = oatGetSrc(cUnit, mir, 0);
buzbee15bf9802012-06-12 17:49:27 -0700850 RegLocation rlDest = oatGetDest(cUnit, mir);
Bill Buzbeea114add2012-05-03 15:00:40 -0700851 storeValue(cUnit, rlDest, rlSrc);
852 break;
853 }
854#if defined(TARGET_ARM)
855 case kMirOpFusedCmplFloat:
856 genFusedFPCmpBranch(cUnit, bb, mir, false /*gt bias*/, false /*double*/);
857 break;
858 case kMirOpFusedCmpgFloat:
859 genFusedFPCmpBranch(cUnit, bb, mir, true /*gt bias*/, false /*double*/);
860 break;
861 case kMirOpFusedCmplDouble:
862 genFusedFPCmpBranch(cUnit, bb, mir, false /*gt bias*/, true /*double*/);
863 break;
864 case kMirOpFusedCmpgDouble:
865 genFusedFPCmpBranch(cUnit, bb, mir, true /*gt bias*/, true /*double*/);
866 break;
867 case kMirOpFusedCmpLong:
868 genFusedLongCmpBranch(cUnit, bb, mir);
869 break;
870#endif
871 default:
872 break;
873 }
buzbeee3acd072012-02-25 17:03:10 -0800874}
875
876/* Handle the content in each basic block */
buzbee31a4a6f2012-02-28 15:36:15 -0800877bool methodBlockCodeGen(CompilationUnit* cUnit, BasicBlock* bb)
buzbeee3acd072012-02-25 17:03:10 -0800878{
Bill Buzbeea114add2012-05-03 15:00:40 -0700879 MIR* mir;
880 LIR* labelList = (LIR*) cUnit->blockLabelList;
881 int blockId = bb->id;
buzbeee3acd072012-02-25 17:03:10 -0800882
Bill Buzbeea114add2012-05-03 15:00:40 -0700883 cUnit->curBlock = bb;
884 labelList[blockId].operands[0] = bb->startOffset;
buzbeee3acd072012-02-25 17:03:10 -0800885
Bill Buzbeea114add2012-05-03 15:00:40 -0700886 /* Insert the block label */
887 labelList[blockId].opcode = kPseudoNormalBlockLabel;
888 oatAppendLIR(cUnit, (LIR*) &labelList[blockId]);
buzbeee3acd072012-02-25 17:03:10 -0800889
Bill Buzbeea114add2012-05-03 15:00:40 -0700890 /* Free temp registers and reset redundant store tracking */
891 oatResetRegPool(cUnit);
892 oatResetDefTracking(cUnit);
893
894 /*
895 * If control reached us from our immediate predecessor via
896 * fallthrough and we have no other incoming arcs we can
897 * reuse existing liveness. Otherwise, reset.
898 */
899 if (!bb->fallThroughTarget || bb->predecessors->numUsed != 1) {
900 oatClobberAllRegs(cUnit);
901 }
902
903 LIR* headLIR = NULL;
904
905 if (bb->blockType == kEntryBlock) {
buzbee2cfc6392012-05-07 14:51:40 -0700906 genEntrySequence(cUnit);
Bill Buzbeea114add2012-05-03 15:00:40 -0700907 } else if (bb->blockType == kExitBlock) {
buzbee2cfc6392012-05-07 14:51:40 -0700908 genExitSequence(cUnit);
Bill Buzbeea114add2012-05-03 15:00:40 -0700909 }
910
911 for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
912
buzbeee3acd072012-02-25 17:03:10 -0800913 oatResetRegPool(cUnit);
Bill Buzbeea114add2012-05-03 15:00:40 -0700914 if (cUnit->disableOpt & (1 << kTrackLiveTemps)) {
915 oatClobberAllRegs(cUnit);
buzbeee1965672012-03-11 18:39:19 -0700916 }
917
Bill Buzbeea114add2012-05-03 15:00:40 -0700918 if (cUnit->disableOpt & (1 << kSuppressLoads)) {
919 oatResetDefTracking(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800920 }
921
buzbee3d661942012-03-14 17:37:27 -0700922#ifndef NDEBUG
Bill Buzbeea114add2012-05-03 15:00:40 -0700923 /* Reset temp tracking sanity check */
924 cUnit->liveSReg = INVALID_SREG;
buzbee3d661942012-03-14 17:37:27 -0700925#endif
926
Bill Buzbeea114add2012-05-03 15:00:40 -0700927 cUnit->currentDalvikOffset = mir->offset;
buzbeee3acd072012-02-25 17:03:10 -0800928
Bill Buzbeea114add2012-05-03 15:00:40 -0700929 Instruction::Code dalvikOpcode = mir->dalvikInsn.opcode;
930 Instruction::Format dalvikFormat = Instruction::FormatOf(dalvikOpcode);
buzbeee3acd072012-02-25 17:03:10 -0800931
Bill Buzbeea114add2012-05-03 15:00:40 -0700932 LIR* boundaryLIR;
buzbeee3acd072012-02-25 17:03:10 -0800933
Bill Buzbeea114add2012-05-03 15:00:40 -0700934 /* Mark the beginning of a Dalvik instruction for line tracking */
935 char* instStr = cUnit->printMe ?
936 oatGetDalvikDisassembly(cUnit, mir->dalvikInsn, "") : NULL;
937 boundaryLIR = newLIR1(cUnit, kPseudoDalvikByteCodeBoundary,
938 (intptr_t) instStr);
939 cUnit->boundaryMap.Overwrite(mir->offset, boundaryLIR);
940 /* Remember the first LIR for this block */
941 if (headLIR == NULL) {
942 headLIR = boundaryLIR;
943 /* Set the first boundaryLIR as a scheduling barrier */
944 headLIR->defMask = ENCODE_ALL;
buzbeee3acd072012-02-25 17:03:10 -0800945 }
946
Bill Buzbeea114add2012-05-03 15:00:40 -0700947 /* If we're compiling for the debugger, generate an update callout */
948 if (cUnit->genDebugger) {
949 genDebuggerUpdate(cUnit, mir->offset);
buzbeee3acd072012-02-25 17:03:10 -0800950 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700951
952 /* Don't generate the SSA annotation unless verbose mode is on */
953 if (cUnit->printMe && mir->ssaRep) {
954 char* ssaString = oatGetSSAString(cUnit, mir->ssaRep);
955 newLIR1(cUnit, kPseudoSSARep, (int) ssaString);
956 }
957
958 if ((int)mir->dalvikInsn.opcode >= (int)kMirOpFirst) {
959 handleExtendedMethodMIR(cUnit, bb, mir);
960 continue;
961 }
962
963 bool notHandled = compileDalvikInstruction(cUnit, mir, bb, labelList);
964 if (notHandled) {
965 LOG(FATAL) << StringPrintf("%#06x: Opcode %#x (%s) / Fmt %d not handled",
966 mir->offset, dalvikOpcode,
967 Instruction::Name(dalvikOpcode), dalvikFormat);
968
969 }
970 }
971
972 if (headLIR) {
973 /*
974 * Eliminate redundant loads/stores and delay stores into later
975 * slots
976 */
977 oatApplyLocalOptimizations(cUnit, (LIR*) headLIR, cUnit->lastLIRInsn);
978
979 /*
980 * Generate an unconditional branch to the fallthrough block.
981 */
982 if (bb->fallThrough) {
983 opUnconditionalBranch(cUnit, &labelList[bb->fallThrough->id]);
984 }
985 }
986 return false;
buzbeee3acd072012-02-25 17:03:10 -0800987}
988
buzbee16da88c2012-03-20 10:38:17 -0700989/* Set basic block labels */
990bool labelBlocks(CompilationUnit* cUnit, BasicBlock* bb)
991{
Bill Buzbeea114add2012-05-03 15:00:40 -0700992 LIR* labelList = (LIR*) cUnit->blockLabelList;
993 int blockId = bb->id;
buzbee16da88c2012-03-20 10:38:17 -0700994
Bill Buzbeea114add2012-05-03 15:00:40 -0700995 cUnit->curBlock = bb;
996 labelList[blockId].operands[0] = bb->startOffset;
buzbee16da88c2012-03-20 10:38:17 -0700997
Bill Buzbeea114add2012-05-03 15:00:40 -0700998 /* Insert the block label */
999 labelList[blockId].opcode = kPseudoNormalBlockLabel;
1000 return false;
buzbee16da88c2012-03-20 10:38:17 -07001001}
1002
1003void oatSpecialMIR2LIR(CompilationUnit* cUnit, SpecialCaseHandler specialCase)
1004{
Bill Buzbeea114add2012-05-03 15:00:40 -07001005 /* Find the first DalvikByteCode block */
1006 int numReachableBlocks = cUnit->numReachableBlocks;
1007 const GrowableList *blockList = &cUnit->blockList;
1008 BasicBlock*bb = NULL;
1009 for (int idx = 0; idx < numReachableBlocks; idx++) {
1010 int dfsIndex = cUnit->dfsOrder.elemList[idx];
1011 bb = (BasicBlock*)oatGrowableListGetElement(blockList, dfsIndex);
1012 if (bb->blockType == kDalvikByteCode) {
1013 break;
buzbee16da88c2012-03-20 10:38:17 -07001014 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001015 }
1016 if (bb == NULL) {
1017 return;
1018 }
1019 DCHECK_EQ(bb->startOffset, 0);
1020 DCHECK(bb->firstMIRInsn != 0);
buzbee16da88c2012-03-20 10:38:17 -07001021
Bill Buzbeea114add2012-05-03 15:00:40 -07001022 /* Get the first instruction */
1023 MIR* mir = bb->firstMIRInsn;
buzbee16da88c2012-03-20 10:38:17 -07001024
Bill Buzbeea114add2012-05-03 15:00:40 -07001025 /* Free temp registers and reset redundant store tracking */
1026 oatResetRegPool(cUnit);
1027 oatResetDefTracking(cUnit);
1028 oatClobberAllRegs(cUnit);
buzbee16da88c2012-03-20 10:38:17 -07001029
Bill Buzbeea114add2012-05-03 15:00:40 -07001030 genSpecialCase(cUnit, bb, mir, specialCase);
buzbee16da88c2012-03-20 10:38:17 -07001031}
1032
buzbeee3acd072012-02-25 17:03:10 -08001033void oatMethodMIR2LIR(CompilationUnit* cUnit)
1034{
Bill Buzbeea114add2012-05-03 15:00:40 -07001035 /* Used to hold the labels of each block */
1036 cUnit->blockLabelList =
1037 (void *) oatNew(cUnit, sizeof(LIR) * cUnit->numBlocks, true, kAllocLIR);
buzbeee3acd072012-02-25 17:03:10 -08001038
Bill Buzbeea114add2012-05-03 15:00:40 -07001039 oatDataFlowAnalysisDispatcher(cUnit, methodBlockCodeGen,
1040 kPreOrderDFSTraversal, false /* Iterative */);
Ian Rogersab2b55d2012-03-18 00:06:11 -07001041
Bill Buzbeea114add2012-05-03 15:00:40 -07001042 handleSuspendLaunchpads(cUnit);
buzbeee3acd072012-02-25 17:03:10 -08001043
Bill Buzbeea114add2012-05-03 15:00:40 -07001044 handleThrowLaunchpads(cUnit);
buzbeee3acd072012-02-25 17:03:10 -08001045
Bill Buzbeea114add2012-05-03 15:00:40 -07001046 handleIntrinsicLaunchpads(cUnit);
buzbeefc9e6fa2012-03-23 15:14:29 -07001047
Bill Buzbeea114add2012-05-03 15:00:40 -07001048 if (!(cUnit->disableOpt & (1 << kSafeOptimizations))) {
1049 removeRedundantBranches(cUnit);
1050 }
buzbeee3acd072012-02-25 17:03:10 -08001051}
1052
1053/* Needed by the ld/st optmizatons */
buzbee31a4a6f2012-02-28 15:36:15 -08001054LIR* oatRegCopyNoInsert(CompilationUnit* cUnit, int rDest, int rSrc)
buzbeee3acd072012-02-25 17:03:10 -08001055{
Bill Buzbeea114add2012-05-03 15:00:40 -07001056 return opRegCopyNoInsert(cUnit, rDest, rSrc);
buzbeee3acd072012-02-25 17:03:10 -08001057}
1058
1059/* Needed by the register allocator */
1060void oatRegCopy(CompilationUnit* cUnit, int rDest, int rSrc)
1061{
Bill Buzbeea114add2012-05-03 15:00:40 -07001062 opRegCopy(cUnit, rDest, rSrc);
buzbeee3acd072012-02-25 17:03:10 -08001063}
1064
1065/* Needed by the register allocator */
1066void oatRegCopyWide(CompilationUnit* cUnit, int destLo, int destHi,
Bill Buzbeea114add2012-05-03 15:00:40 -07001067 int srcLo, int srcHi)
buzbeee3acd072012-02-25 17:03:10 -08001068{
Bill Buzbeea114add2012-05-03 15:00:40 -07001069 opRegCopyWide(cUnit, destLo, destHi, srcLo, srcHi);
buzbeee3acd072012-02-25 17:03:10 -08001070}
1071
1072void oatFlushRegImpl(CompilationUnit* cUnit, int rBase,
Bill Buzbeea114add2012-05-03 15:00:40 -07001073 int displacement, int rSrc, OpSize size)
buzbeee3acd072012-02-25 17:03:10 -08001074{
Bill Buzbeea114add2012-05-03 15:00:40 -07001075 storeBaseDisp(cUnit, rBase, displacement, rSrc, size);
buzbeee3acd072012-02-25 17:03:10 -08001076}
1077
1078void oatFlushRegWideImpl(CompilationUnit* cUnit, int rBase,
Bill Buzbeea114add2012-05-03 15:00:40 -07001079 int displacement, int rSrcLo, int rSrcHi)
buzbeee3acd072012-02-25 17:03:10 -08001080{
Bill Buzbeea114add2012-05-03 15:00:40 -07001081 storeBaseDispWide(cUnit, rBase, displacement, rSrcLo, rSrcHi);
buzbeee3acd072012-02-25 17:03:10 -08001082}
1083
1084} // namespace art