blob: 53377264b71c79e5d44cf364b960f53296ae091e [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,
Ian Rogers00f7d0e2012-07-19 15:28:27 -070071 *cUnit->dex_file,
Bill Buzbeea114add2012-05-03 15:00:40 -070072 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 */
buzbee6969d502012-06-15 16:40:31 -0700177CallInfo* oatNewCallInfo(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);
182 MIR* moveResultMIR = oatFindMoveResult(cUnit, bb, mir);
183 if (moveResultMIR == NULL) {
184 info->result.location = kLocInvalid;
185 } else {
186 info->result = oatGetRawDest(cUnit, moveResultMIR);
187 moveResultMIR->dalvikInsn.opcode = Instruction::NOP;
188 }
189 info->numArgWords = mir->ssaRep->numUses;
190 info->args = (info->numArgWords == 0) ? NULL : (RegLocation*)
191 oatNew(cUnit, sizeof(RegLocation) * info->numArgWords, false, kAllocMisc);
192 for (int i = 0; i < info->numArgWords; i++) {
193 info->args[i] = oatGetRawSrc(cUnit, mir, i);
194 }
195 info->optFlags = mir->optimizationFlags;
196 info->type = type;
197 info->isRange = isRange;
buzbee3b3dbdd2012-06-13 13:39:34 -0700198 info->index = mir->dalvikInsn.vB;
buzbee15bf9802012-06-12 17:49:27 -0700199 info->offset = mir->offset;
200 return info;
buzbeee3acd072012-02-25 17:03:10 -0800201}
202
203/*
204 * Target-independent code generation. Use only high-level
205 * load/store utilities here, or target-dependent genXX() handlers
206 * when necessary.
207 */
buzbee31a4a6f2012-02-28 15:36:15 -0800208bool compileDalvikInstruction(CompilationUnit* cUnit, MIR* mir,
209 BasicBlock* bb, LIR* labelList)
buzbeee3acd072012-02-25 17:03:10 -0800210{
Bill Buzbeea114add2012-05-03 15:00:40 -0700211 bool res = false; // Assume success
212 RegLocation rlSrc[3];
213 RegLocation rlDest = badLoc;
214 RegLocation rlResult = badLoc;
215 Instruction::Code opcode = mir->dalvikInsn.opcode;
buzbee408ad162012-06-06 16:45:18 -0700216 int optFlags = mir->optimizationFlags;
217 uint32_t vA = mir->dalvikInsn.vA;
218 uint32_t vB = mir->dalvikInsn.vB;
219 uint32_t vC = mir->dalvikInsn.vC;
buzbeee3acd072012-02-25 17:03:10 -0800220
Bill Buzbeea114add2012-05-03 15:00:40 -0700221 /* Prep Src and Dest locations */
222 int nextSreg = 0;
223 int nextLoc = 0;
224 int attrs = oatDataFlowAttributes[opcode];
225 rlSrc[0] = rlSrc[1] = rlSrc[2] = badLoc;
226 if (attrs & DF_UA) {
buzbeebff24652012-05-06 16:22:05 -0700227 if (attrs & DF_A_WIDE) {
buzbee15bf9802012-06-12 17:49:27 -0700228 rlSrc[nextLoc++] = oatGetSrcWide(cUnit, mir, nextSreg);
buzbeebff24652012-05-06 16:22:05 -0700229 nextSreg+= 2;
230 } else {
231 rlSrc[nextLoc++] = oatGetSrc(cUnit, mir, nextSreg);
232 nextSreg++;
233 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700234 }
235 if (attrs & DF_UB) {
buzbeebff24652012-05-06 16:22:05 -0700236 if (attrs & DF_B_WIDE) {
buzbee15bf9802012-06-12 17:49:27 -0700237 rlSrc[nextLoc++] = oatGetSrcWide(cUnit, mir, nextSreg);
buzbeebff24652012-05-06 16:22:05 -0700238 nextSreg+= 2;
239 } else {
240 rlSrc[nextLoc++] = oatGetSrc(cUnit, mir, nextSreg);
241 nextSreg++;
242 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700243 }
244 if (attrs & DF_UC) {
buzbeebff24652012-05-06 16:22:05 -0700245 if (attrs & DF_C_WIDE) {
buzbee15bf9802012-06-12 17:49:27 -0700246 rlSrc[nextLoc++] = oatGetSrcWide(cUnit, mir, nextSreg);
buzbeebff24652012-05-06 16:22:05 -0700247 } else {
248 rlSrc[nextLoc++] = oatGetSrc(cUnit, mir, nextSreg);
249 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700250 }
251 if (attrs & DF_DA) {
buzbeebff24652012-05-06 16:22:05 -0700252 if (attrs & DF_A_WIDE) {
buzbee15bf9802012-06-12 17:49:27 -0700253 rlDest = oatGetDestWide(cUnit, mir);
buzbeebff24652012-05-06 16:22:05 -0700254 } else {
buzbee15bf9802012-06-12 17:49:27 -0700255 rlDest = oatGetDest(cUnit, mir);
buzbeebff24652012-05-06 16:22:05 -0700256 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700257 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700258 switch (opcode) {
259 case Instruction::NOP:
260 break;
buzbeee3acd072012-02-25 17:03:10 -0800261
Bill Buzbeea114add2012-05-03 15:00:40 -0700262 case Instruction::MOVE_EXCEPTION: {
263 int exOffset = Thread::ExceptionOffset().Int32Value();
264 rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
Ian Rogersc6f3bb82012-03-21 20:40:33 -0700265#if defined(TARGET_X86)
Bill Buzbeea114add2012-05-03 15:00:40 -0700266 newLIR2(cUnit, kX86Mov32RT, rlResult.lowReg, exOffset);
267 newLIR2(cUnit, kX86Mov32TI, exOffset, 0);
Ian Rogersc6f3bb82012-03-21 20:40:33 -0700268#else
Bill Buzbeea114add2012-05-03 15:00:40 -0700269 int resetReg = oatAllocTemp(cUnit);
270 loadWordDisp(cUnit, rSELF, exOffset, rlResult.lowReg);
271 loadConstant(cUnit, resetReg, 0);
272 storeWordDisp(cUnit, rSELF, exOffset, resetReg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700273 oatFreeTemp(cUnit, resetReg);
buzbeea7678db2012-03-05 15:35:46 -0800274#endif
jeffhao41005dd2012-05-09 17:58:52 -0700275 storeValue(cUnit, rlDest, rlResult);
Bill Buzbeea114add2012-05-03 15:00:40 -0700276 break;
buzbeee3acd072012-02-25 17:03:10 -0800277 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700278 case Instruction::RETURN_VOID:
TDYa1274f2935e2012-06-22 06:25:03 -0700279 if (!(cUnit->attrs & METHOD_IS_LEAF)) {
buzbee408ad162012-06-06 16:45:18 -0700280 genSuspendTest(cUnit, optFlags);
Bill Buzbeea114add2012-05-03 15:00:40 -0700281 }
282 break;
283
284 case Instruction::RETURN:
285 case Instruction::RETURN_OBJECT:
TDYa1274f2935e2012-06-22 06:25:03 -0700286 if (!(cUnit->attrs & METHOD_IS_LEAF)) {
buzbee408ad162012-06-06 16:45:18 -0700287 genSuspendTest(cUnit, optFlags);
Bill Buzbeea114add2012-05-03 15:00:40 -0700288 }
289 storeValue(cUnit, oatGetReturn(cUnit, cUnit->shorty[0] == 'F'), rlSrc[0]);
290 break;
291
292 case Instruction::RETURN_WIDE:
TDYa1274f2935e2012-06-22 06:25:03 -0700293 if (!(cUnit->attrs & METHOD_IS_LEAF)) {
buzbee408ad162012-06-06 16:45:18 -0700294 genSuspendTest(cUnit, optFlags);
Bill Buzbeea114add2012-05-03 15:00:40 -0700295 }
296 storeValueWide(cUnit, oatGetReturnWide(cUnit,
297 cUnit->shorty[0] == 'D'), rlSrc[0]);
298 break;
299
300 case Instruction::MOVE_RESULT_WIDE:
buzbee408ad162012-06-06 16:45:18 -0700301 if (optFlags & MIR_INLINED)
Bill Buzbeea114add2012-05-03 15:00:40 -0700302 break; // Nop - combined w/ previous invoke
303 storeValueWide(cUnit, rlDest, oatGetReturnWide(cUnit, rlDest.fp));
304 break;
305
306 case Instruction::MOVE_RESULT:
307 case Instruction::MOVE_RESULT_OBJECT:
buzbee408ad162012-06-06 16:45:18 -0700308 if (optFlags & MIR_INLINED)
Bill Buzbeea114add2012-05-03 15:00:40 -0700309 break; // Nop - combined w/ previous invoke
310 storeValue(cUnit, rlDest, oatGetReturn(cUnit, rlDest.fp));
311 break;
312
313 case Instruction::MOVE:
314 case Instruction::MOVE_OBJECT:
315 case Instruction::MOVE_16:
316 case Instruction::MOVE_OBJECT_16:
317 case Instruction::MOVE_FROM16:
318 case Instruction::MOVE_OBJECT_FROM16:
319 storeValue(cUnit, rlDest, rlSrc[0]);
320 break;
321
322 case Instruction::MOVE_WIDE:
323 case Instruction::MOVE_WIDE_16:
324 case Instruction::MOVE_WIDE_FROM16:
325 storeValueWide(cUnit, rlDest, rlSrc[0]);
326 break;
327
328 case Instruction::CONST:
329 case Instruction::CONST_4:
330 case Instruction::CONST_16:
331 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
buzbee408ad162012-06-06 16:45:18 -0700332 loadConstantNoClobber(cUnit, rlResult.lowReg, vB);
Bill Buzbeea114add2012-05-03 15:00:40 -0700333 storeValue(cUnit, rlDest, rlResult);
334 break;
335
336 case Instruction::CONST_HIGH16:
337 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
buzbee408ad162012-06-06 16:45:18 -0700338 loadConstantNoClobber(cUnit, rlResult.lowReg, vB << 16);
Bill Buzbeea114add2012-05-03 15:00:40 -0700339 storeValue(cUnit, rlDest, rlResult);
340 break;
341
342 case Instruction::CONST_WIDE_16:
343 case Instruction::CONST_WIDE_32:
344 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
buzbee408ad162012-06-06 16:45:18 -0700345 loadConstantValueWide(cUnit, rlResult.lowReg, rlResult.highReg, vB,
346 (vB & 0x80000000) ? -1 : 0);
Bill Buzbeea114add2012-05-03 15:00:40 -0700347 storeValueWide(cUnit, rlDest, rlResult);
348 break;
349
350 case Instruction::CONST_WIDE:
351 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
352 loadConstantValueWide(cUnit, rlResult.lowReg, rlResult.highReg,
353 mir->dalvikInsn.vB_wide & 0xffffffff,
354 (mir->dalvikInsn.vB_wide >> 32) & 0xffffffff);
355 storeValueWide(cUnit, rlDest, rlResult);
356 break;
357
358 case Instruction::CONST_WIDE_HIGH16:
359 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
360 loadConstantValueWide(cUnit, rlResult.lowReg, rlResult.highReg,
buzbee408ad162012-06-06 16:45:18 -0700361 0, vB << 16);
Bill Buzbeea114add2012-05-03 15:00:40 -0700362 storeValueWide(cUnit, rlDest, rlResult);
363 break;
364
365 case Instruction::MONITOR_ENTER:
buzbee408ad162012-06-06 16:45:18 -0700366 genMonitorEnter(cUnit, optFlags, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700367 break;
368
369 case Instruction::MONITOR_EXIT:
buzbee408ad162012-06-06 16:45:18 -0700370 genMonitorExit(cUnit, optFlags, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700371 break;
372
373 case Instruction::CHECK_CAST:
buzbee408ad162012-06-06 16:45:18 -0700374 genCheckCast(cUnit, vB, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700375 break;
376
377 case Instruction::INSTANCE_OF:
buzbee408ad162012-06-06 16:45:18 -0700378 genInstanceof(cUnit, vC, rlDest, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700379 break;
380
381 case Instruction::NEW_INSTANCE:
buzbee408ad162012-06-06 16:45:18 -0700382 genNewInstance(cUnit, vB, rlDest);
Bill Buzbeea114add2012-05-03 15:00:40 -0700383 break;
384
385 case Instruction::THROW:
buzbee408ad162012-06-06 16:45:18 -0700386 genThrow(cUnit, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700387 break;
388
389 case Instruction::THROW_VERIFICATION_ERROR:
buzbee408ad162012-06-06 16:45:18 -0700390 genThrowVerificationError(cUnit, vA, vB);
Bill Buzbeea114add2012-05-03 15:00:40 -0700391 break;
392
393 case Instruction::ARRAY_LENGTH:
394 int lenOffset;
395 lenOffset = Array::LengthOffset().Int32Value();
396 rlSrc[0] = loadValue(cUnit, rlSrc[0], kCoreReg);
buzbee408ad162012-06-06 16:45:18 -0700397 genNullCheck(cUnit, rlSrc[0].sRegLow, rlSrc[0].lowReg, optFlags);
Bill Buzbeea114add2012-05-03 15:00:40 -0700398 rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
399 loadWordDisp(cUnit, rlSrc[0].lowReg, lenOffset, rlResult.lowReg);
400 storeValue(cUnit, rlDest, rlResult);
401 break;
402
403 case Instruction::CONST_STRING:
404 case Instruction::CONST_STRING_JUMBO:
buzbee6969d502012-06-15 16:40:31 -0700405 genConstString(cUnit, vB, rlDest);
Bill Buzbeea114add2012-05-03 15:00:40 -0700406 break;
407
408 case Instruction::CONST_CLASS:
buzbee6969d502012-06-15 16:40:31 -0700409 genConstClass(cUnit, vB, rlDest);
Bill Buzbeea114add2012-05-03 15:00:40 -0700410 break;
411
412 case Instruction::FILL_ARRAY_DATA:
buzbee408ad162012-06-06 16:45:18 -0700413 genFillArrayData(cUnit, vB, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700414 break;
415
416 case Instruction::FILLED_NEW_ARRAY:
buzbee6969d502012-06-15 16:40:31 -0700417 genFilledNewArray(cUnit, oatNewCallInfo(cUnit, bb, mir, kStatic,
buzbee3b3dbdd2012-06-13 13:39:34 -0700418 false /* not range */));
Bill Buzbeea114add2012-05-03 15:00:40 -0700419 break;
420
421 case Instruction::FILLED_NEW_ARRAY_RANGE:
buzbee6969d502012-06-15 16:40:31 -0700422 genFilledNewArray(cUnit, oatNewCallInfo(cUnit, bb, mir, kStatic,
buzbee3b3dbdd2012-06-13 13:39:34 -0700423 true /* range */));
Bill Buzbeea114add2012-05-03 15:00:40 -0700424 break;
425
426 case Instruction::NEW_ARRAY:
buzbee408ad162012-06-06 16:45:18 -0700427 genNewArray(cUnit, vC, rlDest, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700428 break;
429
430 case Instruction::GOTO:
431 case Instruction::GOTO_16:
432 case Instruction::GOTO_32:
433 if (bb->taken->startOffset <= mir->offset) {
buzbee408ad162012-06-06 16:45:18 -0700434 genSuspendTestAndBranch(cUnit, optFlags, &labelList[bb->taken->id]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700435 } else {
436 opUnconditionalBranch(cUnit, &labelList[bb->taken->id]);
437 }
438 break;
439
440 case Instruction::PACKED_SWITCH:
buzbee408ad162012-06-06 16:45:18 -0700441 genPackedSwitch(cUnit, vB, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700442 break;
443
444 case Instruction::SPARSE_SWITCH:
buzbeea1da8a52012-07-09 14:00:21 -0700445 genSparseSwitch(cUnit, vB, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700446 break;
447
448 case Instruction::CMPL_FLOAT:
449 case Instruction::CMPG_FLOAT:
450 case Instruction::CMPL_DOUBLE:
451 case Instruction::CMPG_DOUBLE:
buzbee408ad162012-06-06 16:45:18 -0700452 res = genCmpFP(cUnit, opcode, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700453 break;
454
455 case Instruction::CMP_LONG:
buzbee408ad162012-06-06 16:45:18 -0700456 genCmpLong(cUnit, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700457 break;
458
459 case Instruction::IF_EQ:
460 case Instruction::IF_NE:
461 case Instruction::IF_LT:
462 case Instruction::IF_GE:
463 case Instruction::IF_GT:
464 case Instruction::IF_LE: {
buzbee3b3dbdd2012-06-13 13:39:34 -0700465 LIR* taken = &labelList[bb->taken->id];
466 LIR* fallThrough = &labelList[bb->fallThrough->id];
Bill Buzbeea114add2012-05-03 15:00:40 -0700467 bool backwardBranch;
468 backwardBranch = (bb->taken->startOffset <= mir->offset);
469 if (backwardBranch) {
buzbee408ad162012-06-06 16:45:18 -0700470 genSuspendTest(cUnit, optFlags);
Bill Buzbeea114add2012-05-03 15:00:40 -0700471 }
buzbee3b3dbdd2012-06-13 13:39:34 -0700472 genCompareAndBranch(cUnit, opcode, rlSrc[0], rlSrc[1], taken,
473 fallThrough);
Bill Buzbeea114add2012-05-03 15:00:40 -0700474 break;
475 }
476
477 case Instruction::IF_EQZ:
478 case Instruction::IF_NEZ:
479 case Instruction::IF_LTZ:
480 case Instruction::IF_GEZ:
481 case Instruction::IF_GTZ:
482 case Instruction::IF_LEZ: {
buzbee3b3dbdd2012-06-13 13:39:34 -0700483 LIR* taken = &labelList[bb->taken->id];
484 LIR* fallThrough = &labelList[bb->fallThrough->id];
Bill Buzbeea114add2012-05-03 15:00:40 -0700485 bool backwardBranch;
486 backwardBranch = (bb->taken->startOffset <= mir->offset);
487 if (backwardBranch) {
buzbee408ad162012-06-06 16:45:18 -0700488 genSuspendTest(cUnit, optFlags);
Bill Buzbeea114add2012-05-03 15:00:40 -0700489 }
buzbee3b3dbdd2012-06-13 13:39:34 -0700490 genCompareZeroAndBranch(cUnit, opcode, rlSrc[0], taken, fallThrough);
Bill Buzbeea114add2012-05-03 15:00:40 -0700491 break;
492 }
493
494 case Instruction::AGET_WIDE:
buzbee408ad162012-06-06 16:45:18 -0700495 genArrayGet(cUnit, optFlags, kLong, rlSrc[0], rlSrc[1], rlDest, 3);
Bill Buzbeea114add2012-05-03 15:00:40 -0700496 break;
497 case Instruction::AGET:
498 case Instruction::AGET_OBJECT:
buzbee408ad162012-06-06 16:45:18 -0700499 genArrayGet(cUnit, optFlags, kWord, rlSrc[0], rlSrc[1], rlDest, 2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700500 break;
501 case Instruction::AGET_BOOLEAN:
buzbee408ad162012-06-06 16:45:18 -0700502 genArrayGet(cUnit, optFlags, kUnsignedByte, rlSrc[0], rlSrc[1], rlDest, 0);
Bill Buzbeea114add2012-05-03 15:00:40 -0700503 break;
504 case Instruction::AGET_BYTE:
buzbee408ad162012-06-06 16:45:18 -0700505 genArrayGet(cUnit, optFlags, kSignedByte, rlSrc[0], rlSrc[1], rlDest, 0);
Bill Buzbeea114add2012-05-03 15:00:40 -0700506 break;
507 case Instruction::AGET_CHAR:
buzbee408ad162012-06-06 16:45:18 -0700508 genArrayGet(cUnit, optFlags, kUnsignedHalf, rlSrc[0], rlSrc[1], rlDest, 1);
Bill Buzbeea114add2012-05-03 15:00:40 -0700509 break;
510 case Instruction::AGET_SHORT:
buzbee408ad162012-06-06 16:45:18 -0700511 genArrayGet(cUnit, optFlags, kSignedHalf, rlSrc[0], rlSrc[1], rlDest, 1);
Bill Buzbeea114add2012-05-03 15:00:40 -0700512 break;
513 case Instruction::APUT_WIDE:
buzbee408ad162012-06-06 16:45:18 -0700514 genArrayPut(cUnit, optFlags, kLong, rlSrc[1], rlSrc[2], rlSrc[0], 3);
Bill Buzbeea114add2012-05-03 15:00:40 -0700515 break;
516 case Instruction::APUT:
buzbee408ad162012-06-06 16:45:18 -0700517 genArrayPut(cUnit, optFlags, kWord, rlSrc[1], rlSrc[2], rlSrc[0], 2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700518 break;
519 case Instruction::APUT_OBJECT:
buzbee408ad162012-06-06 16:45:18 -0700520 genArrayObjPut(cUnit, optFlags, rlSrc[1], rlSrc[2], rlSrc[0], 2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700521 break;
522 case Instruction::APUT_SHORT:
523 case Instruction::APUT_CHAR:
buzbee408ad162012-06-06 16:45:18 -0700524 genArrayPut(cUnit, optFlags, kUnsignedHalf, rlSrc[1], rlSrc[2], rlSrc[0], 1);
Bill Buzbeea114add2012-05-03 15:00:40 -0700525 break;
526 case Instruction::APUT_BYTE:
527 case Instruction::APUT_BOOLEAN:
buzbee408ad162012-06-06 16:45:18 -0700528 genArrayPut(cUnit, optFlags, kUnsignedByte, rlSrc[1], rlSrc[2],
Bill Buzbeea114add2012-05-03 15:00:40 -0700529 rlSrc[0], 0);
530 break;
531
532 case Instruction::IGET_OBJECT:
533 //case Instruction::IGET_OBJECT_VOLATILE:
buzbee408ad162012-06-06 16:45:18 -0700534 genIGet(cUnit, vC, optFlags, kWord, rlDest, rlSrc[0], false, true);
Bill Buzbeea114add2012-05-03 15:00:40 -0700535 break;
536
537 case Instruction::IGET_WIDE:
538 //case Instruction::IGET_WIDE_VOLATILE:
buzbee408ad162012-06-06 16:45:18 -0700539 genIGet(cUnit, vC, optFlags, kLong, rlDest, rlSrc[0], true, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700540 break;
541
542 case Instruction::IGET:
543 //case Instruction::IGET_VOLATILE:
buzbee408ad162012-06-06 16:45:18 -0700544 genIGet(cUnit, vC, optFlags, kWord, rlDest, rlSrc[0], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700545 break;
546
547 case Instruction::IGET_CHAR:
buzbee408ad162012-06-06 16:45:18 -0700548 genIGet(cUnit, vC, optFlags, kUnsignedHalf, rlDest, rlSrc[0], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700549 break;
550
551 case Instruction::IGET_SHORT:
buzbee408ad162012-06-06 16:45:18 -0700552 genIGet(cUnit, vC, optFlags, kSignedHalf, rlDest, rlSrc[0], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700553 break;
554
555 case Instruction::IGET_BOOLEAN:
556 case Instruction::IGET_BYTE:
buzbee408ad162012-06-06 16:45:18 -0700557 genIGet(cUnit, vC, optFlags, kUnsignedByte, rlDest, rlSrc[0], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700558 break;
559
560 case Instruction::IPUT_WIDE:
561 //case Instruction::IPUT_WIDE_VOLATILE:
buzbee408ad162012-06-06 16:45:18 -0700562 genIPut(cUnit, vC, optFlags, kLong, rlSrc[0], rlSrc[1], true, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700563 break;
564
565 case Instruction::IPUT_OBJECT:
566 //case Instruction::IPUT_OBJECT_VOLATILE:
buzbee408ad162012-06-06 16:45:18 -0700567 genIPut(cUnit, vC, optFlags, kWord, rlSrc[0], rlSrc[1], false, true);
Bill Buzbeea114add2012-05-03 15:00:40 -0700568 break;
569
570 case Instruction::IPUT:
571 //case Instruction::IPUT_VOLATILE:
buzbee408ad162012-06-06 16:45:18 -0700572 genIPut(cUnit, vC, optFlags, kWord, rlSrc[0], rlSrc[1], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700573 break;
574
575 case Instruction::IPUT_BOOLEAN:
576 case Instruction::IPUT_BYTE:
buzbee408ad162012-06-06 16:45:18 -0700577 genIPut(cUnit, vC, optFlags, kUnsignedByte, rlSrc[0], rlSrc[1], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700578 break;
579
580 case Instruction::IPUT_CHAR:
buzbee408ad162012-06-06 16:45:18 -0700581 genIPut(cUnit, vC, optFlags, kUnsignedHalf, rlSrc[0], rlSrc[1], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700582 break;
583
584 case Instruction::IPUT_SHORT:
buzbee408ad162012-06-06 16:45:18 -0700585 genIPut(cUnit, vC, optFlags, kSignedHalf, rlSrc[0], rlSrc[1], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700586 break;
587
588 case Instruction::SGET_OBJECT:
buzbee408ad162012-06-06 16:45:18 -0700589 genSget(cUnit, vB, rlDest, false, true);
Bill Buzbeea114add2012-05-03 15:00:40 -0700590 break;
591 case Instruction::SGET:
592 case Instruction::SGET_BOOLEAN:
593 case Instruction::SGET_BYTE:
594 case Instruction::SGET_CHAR:
595 case Instruction::SGET_SHORT:
buzbee408ad162012-06-06 16:45:18 -0700596 genSget(cUnit, vB, rlDest, false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700597 break;
598
599 case Instruction::SGET_WIDE:
buzbee408ad162012-06-06 16:45:18 -0700600 genSget(cUnit, vB, rlDest, true, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700601 break;
602
603 case Instruction::SPUT_OBJECT:
buzbee408ad162012-06-06 16:45:18 -0700604 genSput(cUnit, vB, rlSrc[0], false, true);
Bill Buzbeea114add2012-05-03 15:00:40 -0700605 break;
606
607 case Instruction::SPUT:
608 case Instruction::SPUT_BOOLEAN:
609 case Instruction::SPUT_BYTE:
610 case Instruction::SPUT_CHAR:
611 case Instruction::SPUT_SHORT:
buzbee408ad162012-06-06 16:45:18 -0700612 genSput(cUnit, vB, rlSrc[0], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700613 break;
614
615 case Instruction::SPUT_WIDE:
buzbee408ad162012-06-06 16:45:18 -0700616 genSput(cUnit, vB, rlSrc[0], true, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700617 break;
618
619 case Instruction::INVOKE_STATIC_RANGE:
buzbee6969d502012-06-15 16:40:31 -0700620 genInvoke(cUnit, oatNewCallInfo(cUnit, bb, mir, kStatic, true));
Bill Buzbeea114add2012-05-03 15:00:40 -0700621 break;
622 case Instruction::INVOKE_STATIC:
buzbee6969d502012-06-15 16:40:31 -0700623 genInvoke(cUnit, oatNewCallInfo(cUnit, bb, mir, kStatic, false));
Bill Buzbeea114add2012-05-03 15:00:40 -0700624 break;
625
626 case Instruction::INVOKE_DIRECT:
buzbee6969d502012-06-15 16:40:31 -0700627 genInvoke(cUnit, oatNewCallInfo(cUnit, bb, mir, kDirect, false));
Bill Buzbeea114add2012-05-03 15:00:40 -0700628 break;
629 case Instruction::INVOKE_DIRECT_RANGE:
buzbee6969d502012-06-15 16:40:31 -0700630 genInvoke(cUnit, oatNewCallInfo(cUnit, bb, mir, kDirect, true));
Bill Buzbeea114add2012-05-03 15:00:40 -0700631 break;
632
633 case Instruction::INVOKE_VIRTUAL:
buzbee6969d502012-06-15 16:40:31 -0700634 genInvoke(cUnit, oatNewCallInfo(cUnit, bb, mir, kVirtual, false));
Bill Buzbeea114add2012-05-03 15:00:40 -0700635 break;
636 case Instruction::INVOKE_VIRTUAL_RANGE:
buzbee6969d502012-06-15 16:40:31 -0700637 genInvoke(cUnit, oatNewCallInfo(cUnit, bb, mir, kVirtual, true));
Bill Buzbeea114add2012-05-03 15:00:40 -0700638 break;
639
640 case Instruction::INVOKE_SUPER:
buzbee6969d502012-06-15 16:40:31 -0700641 genInvoke(cUnit, oatNewCallInfo(cUnit, bb, mir, kSuper, false));
Bill Buzbeea114add2012-05-03 15:00:40 -0700642 break;
643 case Instruction::INVOKE_SUPER_RANGE:
buzbee6969d502012-06-15 16:40:31 -0700644 genInvoke(cUnit, oatNewCallInfo(cUnit, bb, mir, kSuper, true));
Bill Buzbeea114add2012-05-03 15:00:40 -0700645 break;
646
647 case Instruction::INVOKE_INTERFACE:
buzbee6969d502012-06-15 16:40:31 -0700648 genInvoke(cUnit, oatNewCallInfo(cUnit, bb, mir, kInterface, false));
Bill Buzbeea114add2012-05-03 15:00:40 -0700649 break;
650 case Instruction::INVOKE_INTERFACE_RANGE:
buzbee6969d502012-06-15 16:40:31 -0700651 genInvoke(cUnit, oatNewCallInfo(cUnit, bb, mir, kInterface, true));
Bill Buzbeea114add2012-05-03 15:00:40 -0700652 break;
653
654 case Instruction::NEG_INT:
655 case Instruction::NOT_INT:
buzbee408ad162012-06-06 16:45:18 -0700656 res = genArithOpInt(cUnit, opcode, rlDest, rlSrc[0], rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700657 break;
658
659 case Instruction::NEG_LONG:
660 case Instruction::NOT_LONG:
buzbee408ad162012-06-06 16:45:18 -0700661 res = genArithOpLong(cUnit, opcode, rlDest, rlSrc[0], rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700662 break;
663
664 case Instruction::NEG_FLOAT:
buzbee408ad162012-06-06 16:45:18 -0700665 res = genArithOpFloat(cUnit, opcode, rlDest, rlSrc[0], rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700666 break;
667
668 case Instruction::NEG_DOUBLE:
buzbee408ad162012-06-06 16:45:18 -0700669 res = genArithOpDouble(cUnit, opcode, rlDest, rlSrc[0], rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700670 break;
671
672 case Instruction::INT_TO_LONG:
buzbee408ad162012-06-06 16:45:18 -0700673 genIntToLong(cUnit, rlDest, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700674 break;
675
676 case Instruction::LONG_TO_INT:
677 rlSrc[0] = oatUpdateLocWide(cUnit, rlSrc[0]);
678 rlSrc[0] = oatWideToNarrow(cUnit, rlSrc[0]);
679 storeValue(cUnit, rlDest, rlSrc[0]);
680 break;
681
682 case Instruction::INT_TO_BYTE:
683 case Instruction::INT_TO_SHORT:
684 case Instruction::INT_TO_CHAR:
buzbee408ad162012-06-06 16:45:18 -0700685 genIntNarrowing(cUnit, opcode, rlDest, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700686 break;
687
688 case Instruction::INT_TO_FLOAT:
689 case Instruction::INT_TO_DOUBLE:
690 case Instruction::LONG_TO_FLOAT:
691 case Instruction::LONG_TO_DOUBLE:
692 case Instruction::FLOAT_TO_INT:
693 case Instruction::FLOAT_TO_LONG:
694 case Instruction::FLOAT_TO_DOUBLE:
695 case Instruction::DOUBLE_TO_INT:
696 case Instruction::DOUBLE_TO_LONG:
697 case Instruction::DOUBLE_TO_FLOAT:
buzbee408ad162012-06-06 16:45:18 -0700698 genConversion(cUnit, opcode, rlDest, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700699 break;
700
701 case Instruction::ADD_INT:
702 case Instruction::SUB_INT:
703 case Instruction::MUL_INT:
704 case Instruction::DIV_INT:
705 case Instruction::REM_INT:
706 case Instruction::AND_INT:
707 case Instruction::OR_INT:
708 case Instruction::XOR_INT:
709 case Instruction::SHL_INT:
710 case Instruction::SHR_INT:
711 case Instruction::USHR_INT:
712 case Instruction::ADD_INT_2ADDR:
713 case Instruction::SUB_INT_2ADDR:
714 case Instruction::MUL_INT_2ADDR:
715 case Instruction::DIV_INT_2ADDR:
716 case Instruction::REM_INT_2ADDR:
717 case Instruction::AND_INT_2ADDR:
718 case Instruction::OR_INT_2ADDR:
719 case Instruction::XOR_INT_2ADDR:
720 case Instruction::SHL_INT_2ADDR:
721 case Instruction::SHR_INT_2ADDR:
722 case Instruction::USHR_INT_2ADDR:
buzbee408ad162012-06-06 16:45:18 -0700723 genArithOpInt(cUnit, opcode, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700724 break;
725
726 case Instruction::ADD_LONG:
727 case Instruction::SUB_LONG:
728 case Instruction::MUL_LONG:
729 case Instruction::DIV_LONG:
730 case Instruction::REM_LONG:
731 case Instruction::AND_LONG:
732 case Instruction::OR_LONG:
733 case Instruction::XOR_LONG:
734 case Instruction::ADD_LONG_2ADDR:
735 case Instruction::SUB_LONG_2ADDR:
736 case Instruction::MUL_LONG_2ADDR:
737 case Instruction::DIV_LONG_2ADDR:
738 case Instruction::REM_LONG_2ADDR:
739 case Instruction::AND_LONG_2ADDR:
740 case Instruction::OR_LONG_2ADDR:
741 case Instruction::XOR_LONG_2ADDR:
buzbee408ad162012-06-06 16:45:18 -0700742 genArithOpLong(cUnit, opcode, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700743 break;
744
745 case Instruction::SHL_LONG:
746 case Instruction::SHR_LONG:
747 case Instruction::USHR_LONG:
748 case Instruction::SHL_LONG_2ADDR:
749 case Instruction::SHR_LONG_2ADDR:
750 case Instruction::USHR_LONG_2ADDR:
buzbee408ad162012-06-06 16:45:18 -0700751 genShiftOpLong(cUnit, opcode, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700752 break;
753
754 case Instruction::ADD_FLOAT:
755 case Instruction::SUB_FLOAT:
756 case Instruction::MUL_FLOAT:
757 case Instruction::DIV_FLOAT:
758 case Instruction::REM_FLOAT:
759 case Instruction::ADD_FLOAT_2ADDR:
760 case Instruction::SUB_FLOAT_2ADDR:
761 case Instruction::MUL_FLOAT_2ADDR:
762 case Instruction::DIV_FLOAT_2ADDR:
763 case Instruction::REM_FLOAT_2ADDR:
buzbee408ad162012-06-06 16:45:18 -0700764 genArithOpFloat(cUnit, opcode, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700765 break;
766
767 case Instruction::ADD_DOUBLE:
768 case Instruction::SUB_DOUBLE:
769 case Instruction::MUL_DOUBLE:
770 case Instruction::DIV_DOUBLE:
771 case Instruction::REM_DOUBLE:
772 case Instruction::ADD_DOUBLE_2ADDR:
773 case Instruction::SUB_DOUBLE_2ADDR:
774 case Instruction::MUL_DOUBLE_2ADDR:
775 case Instruction::DIV_DOUBLE_2ADDR:
776 case Instruction::REM_DOUBLE_2ADDR:
buzbee408ad162012-06-06 16:45:18 -0700777 genArithOpDouble(cUnit, opcode, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700778 break;
779
780 case Instruction::RSUB_INT:
781 case Instruction::ADD_INT_LIT16:
782 case Instruction::MUL_INT_LIT16:
783 case Instruction::DIV_INT_LIT16:
784 case Instruction::REM_INT_LIT16:
785 case Instruction::AND_INT_LIT16:
786 case Instruction::OR_INT_LIT16:
787 case Instruction::XOR_INT_LIT16:
788 case Instruction::ADD_INT_LIT8:
789 case Instruction::RSUB_INT_LIT8:
790 case Instruction::MUL_INT_LIT8:
791 case Instruction::DIV_INT_LIT8:
792 case Instruction::REM_INT_LIT8:
793 case Instruction::AND_INT_LIT8:
794 case Instruction::OR_INT_LIT8:
795 case Instruction::XOR_INT_LIT8:
796 case Instruction::SHL_INT_LIT8:
797 case Instruction::SHR_INT_LIT8:
798 case Instruction::USHR_INT_LIT8:
buzbee408ad162012-06-06 16:45:18 -0700799 genArithOpIntLit(cUnit, opcode, rlDest, rlSrc[0], vC);
Bill Buzbeea114add2012-05-03 15:00:40 -0700800 break;
801
802 default:
803 res = true;
804 }
805 return res;
buzbeee3acd072012-02-25 17:03:10 -0800806}
807
buzbee31a4a6f2012-02-28 15:36:15 -0800808const char* extendedMIROpNames[kMirOpLast - kMirOpFirst] = {
Bill Buzbeea114add2012-05-03 15:00:40 -0700809 "kMirOpPhi",
810 "kMirOpCopy",
811 "kMirFusedCmplFloat",
812 "kMirFusedCmpgFloat",
813 "kMirFusedCmplDouble",
814 "kMirFusedCmpgDouble",
815 "kMirFusedCmpLong",
816 "kMirNop",
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700817 "kMirOpNullCheck",
818 "kMirOpRangeCheck",
819 "kMirOpDivZeroCheck",
820 "kMirOpCheck",
buzbeee3acd072012-02-25 17:03:10 -0800821};
822
823/* Extended MIR instructions like PHI */
buzbee84fd6932012-03-29 16:44:16 -0700824void handleExtendedMethodMIR(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir)
buzbeee3acd072012-02-25 17:03:10 -0800825{
Bill Buzbeea114add2012-05-03 15:00:40 -0700826 int opOffset = mir->dalvikInsn.opcode - kMirOpFirst;
827 char* msg = NULL;
828 if (cUnit->printMe) {
829 msg = (char*)oatNew(cUnit, strlen(extendedMIROpNames[opOffset]) + 1,
830 false, kAllocDebugInfo);
831 strcpy(msg, extendedMIROpNames[opOffset]);
832 }
833 LIR* op = newLIR1(cUnit, kPseudoExtended, (int) msg);
buzbeee3acd072012-02-25 17:03:10 -0800834
Bill Buzbeea114add2012-05-03 15:00:40 -0700835 switch ((ExtendedMIROpcode)mir->dalvikInsn.opcode) {
836 case kMirOpPhi: {
837 char* ssaString = NULL;
838 if (cUnit->printMe) {
839 ssaString = oatGetSSAString(cUnit, mir->ssaRep);
840 }
841 op->flags.isNop = true;
842 newLIR1(cUnit, kPseudoSSARep, (int) ssaString);
843 break;
buzbeee3acd072012-02-25 17:03:10 -0800844 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700845 case kMirOpCopy: {
846 RegLocation rlSrc = oatGetSrc(cUnit, mir, 0);
buzbee15bf9802012-06-12 17:49:27 -0700847 RegLocation rlDest = oatGetDest(cUnit, mir);
Bill Buzbeea114add2012-05-03 15:00:40 -0700848 storeValue(cUnit, rlDest, rlSrc);
849 break;
850 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700851 case kMirOpFusedCmplFloat:
852 genFusedFPCmpBranch(cUnit, bb, mir, false /*gt bias*/, false /*double*/);
853 break;
854 case kMirOpFusedCmpgFloat:
855 genFusedFPCmpBranch(cUnit, bb, mir, true /*gt bias*/, false /*double*/);
856 break;
857 case kMirOpFusedCmplDouble:
858 genFusedFPCmpBranch(cUnit, bb, mir, false /*gt bias*/, true /*double*/);
859 break;
860 case kMirOpFusedCmpgDouble:
861 genFusedFPCmpBranch(cUnit, bb, mir, true /*gt bias*/, true /*double*/);
862 break;
863 case kMirOpFusedCmpLong:
864 genFusedLongCmpBranch(cUnit, bb, mir);
865 break;
Bill Buzbeea114add2012-05-03 15:00:40 -0700866 default:
867 break;
868 }
buzbeee3acd072012-02-25 17:03:10 -0800869}
870
871/* Handle the content in each basic block */
buzbee31a4a6f2012-02-28 15:36:15 -0800872bool methodBlockCodeGen(CompilationUnit* cUnit, BasicBlock* bb)
buzbeee3acd072012-02-25 17:03:10 -0800873{
Bill Buzbeea114add2012-05-03 15:00:40 -0700874 MIR* mir;
buzbeea1da8a52012-07-09 14:00:21 -0700875 LIR* labelList = cUnit->blockLabelList;
Bill Buzbeea114add2012-05-03 15:00:40 -0700876 int blockId = bb->id;
buzbeee3acd072012-02-25 17:03:10 -0800877
Bill Buzbeea114add2012-05-03 15:00:40 -0700878 cUnit->curBlock = bb;
879 labelList[blockId].operands[0] = bb->startOffset;
buzbeee3acd072012-02-25 17:03:10 -0800880
Bill Buzbeea114add2012-05-03 15:00:40 -0700881 /* Insert the block label */
882 labelList[blockId].opcode = kPseudoNormalBlockLabel;
883 oatAppendLIR(cUnit, (LIR*) &labelList[blockId]);
buzbeee3acd072012-02-25 17:03:10 -0800884
Bill Buzbeea114add2012-05-03 15:00:40 -0700885 /* Free temp registers and reset redundant store tracking */
886 oatResetRegPool(cUnit);
887 oatResetDefTracking(cUnit);
888
889 /*
890 * If control reached us from our immediate predecessor via
891 * fallthrough and we have no other incoming arcs we can
892 * reuse existing liveness. Otherwise, reset.
893 */
894 if (!bb->fallThroughTarget || bb->predecessors->numUsed != 1) {
895 oatClobberAllRegs(cUnit);
896 }
897
898 LIR* headLIR = NULL;
899
900 if (bb->blockType == kEntryBlock) {
buzbeead8f15e2012-06-18 14:49:45 -0700901 int startVReg = cUnit->numDalvikRegisters - cUnit->numIns;
902 genEntrySequence(cUnit, &cUnit->regLocation[startVReg],
903 cUnit->regLocation[cUnit->methodSReg]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700904 } else if (bb->blockType == kExitBlock) {
buzbee2cfc6392012-05-07 14:51:40 -0700905 genExitSequence(cUnit);
Bill Buzbeea114add2012-05-03 15:00:40 -0700906 }
907
908 for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
buzbeee3acd072012-02-25 17:03:10 -0800909 oatResetRegPool(cUnit);
Bill Buzbeea114add2012-05-03 15:00:40 -0700910 if (cUnit->disableOpt & (1 << kTrackLiveTemps)) {
911 oatClobberAllRegs(cUnit);
buzbeee1965672012-03-11 18:39:19 -0700912 }
913
Bill Buzbeea114add2012-05-03 15:00:40 -0700914 if (cUnit->disableOpt & (1 << kSuppressLoads)) {
915 oatResetDefTracking(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800916 }
917
buzbee3d661942012-03-14 17:37:27 -0700918#ifndef NDEBUG
Bill Buzbeea114add2012-05-03 15:00:40 -0700919 /* Reset temp tracking sanity check */
920 cUnit->liveSReg = INVALID_SREG;
buzbee3d661942012-03-14 17:37:27 -0700921#endif
922
Bill Buzbeea114add2012-05-03 15:00:40 -0700923 cUnit->currentDalvikOffset = mir->offset;
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700924 int opcode = mir->dalvikInsn.opcode;
Bill Buzbeea114add2012-05-03 15:00:40 -0700925 LIR* boundaryLIR;
buzbeee3acd072012-02-25 17:03:10 -0800926
Bill Buzbeea114add2012-05-03 15:00:40 -0700927 /* Mark the beginning of a Dalvik instruction for line tracking */
928 char* instStr = cUnit->printMe ?
929 oatGetDalvikDisassembly(cUnit, mir->dalvikInsn, "") : NULL;
930 boundaryLIR = newLIR1(cUnit, kPseudoDalvikByteCodeBoundary,
931 (intptr_t) instStr);
932 cUnit->boundaryMap.Overwrite(mir->offset, boundaryLIR);
933 /* Remember the first LIR for this block */
934 if (headLIR == NULL) {
935 headLIR = boundaryLIR;
936 /* Set the first boundaryLIR as a scheduling barrier */
937 headLIR->defMask = ENCODE_ALL;
buzbeee3acd072012-02-25 17:03:10 -0800938 }
939
Bill Buzbeea114add2012-05-03 15:00:40 -0700940 /* If we're compiling for the debugger, generate an update callout */
941 if (cUnit->genDebugger) {
942 genDebuggerUpdate(cUnit, mir->offset);
buzbeee3acd072012-02-25 17:03:10 -0800943 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700944
945 /* Don't generate the SSA annotation unless verbose mode is on */
946 if (cUnit->printMe && mir->ssaRep) {
947 char* ssaString = oatGetSSAString(cUnit, mir->ssaRep);
948 newLIR1(cUnit, kPseudoSSARep, (int) ssaString);
949 }
950
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700951 if (opcode == kMirOpCheck) {
952 // Combine check and work halves of throwing instruction.
953 MIR* workHalf = mir->meta.throwInsn;
954 mir->dalvikInsn.opcode = workHalf->dalvikInsn.opcode;
955 opcode = workHalf->dalvikInsn.opcode;
956 SSARepresentation* ssaRep = workHalf->ssaRep;
957 workHalf->ssaRep = mir->ssaRep;
958 mir->ssaRep = ssaRep;
959 workHalf->dalvikInsn.opcode = static_cast<Instruction::Code>(kMirOpNop);
960 }
961
962 if (opcode >= kMirOpFirst) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700963 handleExtendedMethodMIR(cUnit, bb, mir);
964 continue;
965 }
966
967 bool notHandled = compileDalvikInstruction(cUnit, mir, bb, labelList);
968 if (notHandled) {
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700969 LOG(FATAL) << StringPrintf("%#06x: Opcode %#x (%s)",
970 mir->offset, opcode,
971 Instruction::Name(mir->dalvikInsn.opcode));
Bill Buzbeea114add2012-05-03 15:00:40 -0700972 }
973 }
974
975 if (headLIR) {
976 /*
977 * Eliminate redundant loads/stores and delay stores into later
978 * slots
979 */
980 oatApplyLocalOptimizations(cUnit, (LIR*) headLIR, cUnit->lastLIRInsn);
981
982 /*
983 * Generate an unconditional branch to the fallthrough block.
984 */
985 if (bb->fallThrough) {
986 opUnconditionalBranch(cUnit, &labelList[bb->fallThrough->id]);
987 }
988 }
989 return false;
buzbeee3acd072012-02-25 17:03:10 -0800990}
991
buzbee16da88c2012-03-20 10:38:17 -0700992/* Set basic block labels */
993bool labelBlocks(CompilationUnit* cUnit, BasicBlock* bb)
994{
buzbeea1da8a52012-07-09 14:00:21 -0700995 LIR* labelList = cUnit->blockLabelList;
Bill Buzbeea114add2012-05-03 15:00:40 -0700996 int blockId = bb->id;
buzbee16da88c2012-03-20 10:38:17 -0700997
Bill Buzbeea114add2012-05-03 15:00:40 -0700998 cUnit->curBlock = bb;
999 labelList[blockId].operands[0] = bb->startOffset;
buzbee16da88c2012-03-20 10:38:17 -07001000
Bill Buzbeea114add2012-05-03 15:00:40 -07001001 /* Insert the block label */
1002 labelList[blockId].opcode = kPseudoNormalBlockLabel;
1003 return false;
buzbee16da88c2012-03-20 10:38:17 -07001004}
1005
1006void oatSpecialMIR2LIR(CompilationUnit* cUnit, SpecialCaseHandler specialCase)
1007{
Bill Buzbeea114add2012-05-03 15:00:40 -07001008 /* Find the first DalvikByteCode block */
1009 int numReachableBlocks = cUnit->numReachableBlocks;
1010 const GrowableList *blockList = &cUnit->blockList;
1011 BasicBlock*bb = NULL;
1012 for (int idx = 0; idx < numReachableBlocks; idx++) {
1013 int dfsIndex = cUnit->dfsOrder.elemList[idx];
1014 bb = (BasicBlock*)oatGrowableListGetElement(blockList, dfsIndex);
1015 if (bb->blockType == kDalvikByteCode) {
1016 break;
buzbee16da88c2012-03-20 10:38:17 -07001017 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001018 }
1019 if (bb == NULL) {
1020 return;
1021 }
1022 DCHECK_EQ(bb->startOffset, 0);
Elliott Hughes74847412012-06-20 18:10:21 -07001023 DCHECK(bb->firstMIRInsn != NULL);
buzbee16da88c2012-03-20 10:38:17 -07001024
Bill Buzbeea114add2012-05-03 15:00:40 -07001025 /* Get the first instruction */
1026 MIR* mir = bb->firstMIRInsn;
buzbee16da88c2012-03-20 10:38:17 -07001027
Bill Buzbeea114add2012-05-03 15:00:40 -07001028 /* Free temp registers and reset redundant store tracking */
1029 oatResetRegPool(cUnit);
1030 oatResetDefTracking(cUnit);
1031 oatClobberAllRegs(cUnit);
buzbee16da88c2012-03-20 10:38:17 -07001032
Bill Buzbeea114add2012-05-03 15:00:40 -07001033 genSpecialCase(cUnit, bb, mir, specialCase);
buzbee16da88c2012-03-20 10:38:17 -07001034}
1035
buzbeee3acd072012-02-25 17:03:10 -08001036void oatMethodMIR2LIR(CompilationUnit* cUnit)
1037{
Bill Buzbeea114add2012-05-03 15:00:40 -07001038 /* Used to hold the labels of each block */
1039 cUnit->blockLabelList =
buzbeea1da8a52012-07-09 14:00:21 -07001040 (LIR*) oatNew(cUnit, sizeof(LIR) * cUnit->numBlocks, true, kAllocLIR);
buzbeee3acd072012-02-25 17:03:10 -08001041
Bill Buzbeea114add2012-05-03 15:00:40 -07001042 oatDataFlowAnalysisDispatcher(cUnit, methodBlockCodeGen,
1043 kPreOrderDFSTraversal, false /* Iterative */);
Ian Rogersab2b55d2012-03-18 00:06:11 -07001044
Bill Buzbeea114add2012-05-03 15:00:40 -07001045 handleSuspendLaunchpads(cUnit);
buzbeee3acd072012-02-25 17:03:10 -08001046
Bill Buzbeea114add2012-05-03 15:00:40 -07001047 handleThrowLaunchpads(cUnit);
buzbeee3acd072012-02-25 17:03:10 -08001048
Bill Buzbeea114add2012-05-03 15:00:40 -07001049 handleIntrinsicLaunchpads(cUnit);
buzbeefc9e6fa2012-03-23 15:14:29 -07001050
Bill Buzbeea114add2012-05-03 15:00:40 -07001051 if (!(cUnit->disableOpt & (1 << kSafeOptimizations))) {
1052 removeRedundantBranches(cUnit);
1053 }
buzbeee3acd072012-02-25 17:03:10 -08001054}
1055
1056/* Needed by the ld/st optmizatons */
buzbee31a4a6f2012-02-28 15:36:15 -08001057LIR* oatRegCopyNoInsert(CompilationUnit* cUnit, int rDest, int rSrc)
buzbeee3acd072012-02-25 17:03:10 -08001058{
Bill Buzbeea114add2012-05-03 15:00:40 -07001059 return opRegCopyNoInsert(cUnit, rDest, rSrc);
buzbeee3acd072012-02-25 17:03:10 -08001060}
1061
1062/* Needed by the register allocator */
1063void oatRegCopy(CompilationUnit* cUnit, int rDest, int rSrc)
1064{
Bill Buzbeea114add2012-05-03 15:00:40 -07001065 opRegCopy(cUnit, rDest, rSrc);
buzbeee3acd072012-02-25 17:03:10 -08001066}
1067
1068/* Needed by the register allocator */
1069void oatRegCopyWide(CompilationUnit* cUnit, int destLo, int destHi,
Bill Buzbeea114add2012-05-03 15:00:40 -07001070 int srcLo, int srcHi)
buzbeee3acd072012-02-25 17:03:10 -08001071{
Bill Buzbeea114add2012-05-03 15:00:40 -07001072 opRegCopyWide(cUnit, destLo, destHi, srcLo, srcHi);
buzbeee3acd072012-02-25 17:03:10 -08001073}
1074
1075void oatFlushRegImpl(CompilationUnit* cUnit, int rBase,
Bill Buzbeea114add2012-05-03 15:00:40 -07001076 int displacement, int rSrc, OpSize size)
buzbeee3acd072012-02-25 17:03:10 -08001077{
Bill Buzbeea114add2012-05-03 15:00:40 -07001078 storeBaseDisp(cUnit, rBase, displacement, rSrc, size);
buzbeee3acd072012-02-25 17:03:10 -08001079}
1080
1081void oatFlushRegWideImpl(CompilationUnit* cUnit, int rBase,
Bill Buzbeea114add2012-05-03 15:00:40 -07001082 int displacement, int rSrcLo, int rSrcHi)
buzbeee3acd072012-02-25 17:03:10 -08001083{
Bill Buzbeea114add2012-05-03 15:00:40 -07001084 storeBaseDispWide(cUnit, rBase, displacement, rSrcLo, rSrcHi);
buzbeee3acd072012-02-25 17:03:10 -08001085}
1086
1087} // namespace art