blob: 1707a8992cfcab6cd255e729a9fa7e5623a865bd [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
buzbee15bf9802012-06-12 17:49:27 -070056void genInvoke(CompilationUnit* cUnit, InvokeInfo* 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
buzbee15bf9802012-06-12 17:49:27 -070075 uint32_t dexMethodIdx = info->methodIdx;
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) {
162 RegLocation retLoc = oatGetReturnWide(cUnit, false);
163 storeValueWide(cUnit, info->result, retLoc);
164 } else {
165 RegLocation retLoc = oatGetReturn(cUnit, false);
166 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 */
177InvokeInfo* newInvokeInfo(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir,
178 InvokeType type, bool isRange)
179{
180 InvokeInfo* info = (InvokeInfo*)oatNew(cUnit, sizeof(InvokeInfo), true,
181 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;
198 info->methodIdx = mir->dalvikInsn.vB;
199 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:
279 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:
286 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:
293 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:
buzbee408ad162012-06-06 16:45:18 -0700405 genConstString(cUnit, vB, rlDest, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700406 break;
407
408 case Instruction::CONST_CLASS:
buzbee408ad162012-06-06 16:45:18 -0700409 genConstClass(cUnit, vB, rlDest, rlSrc[0]);
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:
417 genFilledNewArray(cUnit, mir, false /* not range */);
418 break;
419
420 case Instruction::FILLED_NEW_ARRAY_RANGE:
421 genFilledNewArray(cUnit, mir, true /* range */);
422 break;
423
424 case Instruction::NEW_ARRAY:
buzbee408ad162012-06-06 16:45:18 -0700425 genNewArray(cUnit, vC, rlDest, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700426 break;
427
428 case Instruction::GOTO:
429 case Instruction::GOTO_16:
430 case Instruction::GOTO_32:
431 if (bb->taken->startOffset <= mir->offset) {
buzbee408ad162012-06-06 16:45:18 -0700432 genSuspendTestAndBranch(cUnit, optFlags, &labelList[bb->taken->id]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700433 } else {
434 opUnconditionalBranch(cUnit, &labelList[bb->taken->id]);
435 }
436 break;
437
438 case Instruction::PACKED_SWITCH:
buzbee408ad162012-06-06 16:45:18 -0700439 genPackedSwitch(cUnit, vB, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700440 break;
441
442 case Instruction::SPARSE_SWITCH:
buzbee408ad162012-06-06 16:45:18 -0700443 genSparseSwitch(cUnit, vB, rlSrc[0], labelList);
Bill Buzbeea114add2012-05-03 15:00:40 -0700444 break;
445
446 case Instruction::CMPL_FLOAT:
447 case Instruction::CMPG_FLOAT:
448 case Instruction::CMPL_DOUBLE:
449 case Instruction::CMPG_DOUBLE:
buzbee408ad162012-06-06 16:45:18 -0700450 res = genCmpFP(cUnit, opcode, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700451 break;
452
453 case Instruction::CMP_LONG:
buzbee408ad162012-06-06 16:45:18 -0700454 genCmpLong(cUnit, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700455 break;
456
457 case Instruction::IF_EQ:
458 case Instruction::IF_NE:
459 case Instruction::IF_LT:
460 case Instruction::IF_GE:
461 case Instruction::IF_GT:
462 case Instruction::IF_LE: {
463 bool backwardBranch;
464 backwardBranch = (bb->taken->startOffset <= mir->offset);
465 if (backwardBranch) {
buzbee408ad162012-06-06 16:45:18 -0700466 genSuspendTest(cUnit, optFlags);
Bill Buzbeea114add2012-05-03 15:00:40 -0700467 }
buzbee408ad162012-06-06 16:45:18 -0700468 genCompareAndBranch(cUnit, bb, opcode, rlSrc[0], rlSrc[1], labelList);
Bill Buzbeea114add2012-05-03 15:00:40 -0700469 break;
470 }
471
472 case Instruction::IF_EQZ:
473 case Instruction::IF_NEZ:
474 case Instruction::IF_LTZ:
475 case Instruction::IF_GEZ:
476 case Instruction::IF_GTZ:
477 case Instruction::IF_LEZ: {
478 bool backwardBranch;
479 backwardBranch = (bb->taken->startOffset <= mir->offset);
480 if (backwardBranch) {
buzbee408ad162012-06-06 16:45:18 -0700481 genSuspendTest(cUnit, optFlags);
Bill Buzbeea114add2012-05-03 15:00:40 -0700482 }
buzbee408ad162012-06-06 16:45:18 -0700483 genCompareZeroAndBranch(cUnit, bb, opcode, rlSrc[0], labelList);
Bill Buzbeea114add2012-05-03 15:00:40 -0700484 break;
485 }
486
487 case Instruction::AGET_WIDE:
buzbee408ad162012-06-06 16:45:18 -0700488 genArrayGet(cUnit, optFlags, kLong, rlSrc[0], rlSrc[1], rlDest, 3);
Bill Buzbeea114add2012-05-03 15:00:40 -0700489 break;
490 case Instruction::AGET:
491 case Instruction::AGET_OBJECT:
buzbee408ad162012-06-06 16:45:18 -0700492 genArrayGet(cUnit, optFlags, kWord, rlSrc[0], rlSrc[1], rlDest, 2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700493 break;
494 case Instruction::AGET_BOOLEAN:
buzbee408ad162012-06-06 16:45:18 -0700495 genArrayGet(cUnit, optFlags, kUnsignedByte, rlSrc[0], rlSrc[1], rlDest, 0);
Bill Buzbeea114add2012-05-03 15:00:40 -0700496 break;
497 case Instruction::AGET_BYTE:
buzbee408ad162012-06-06 16:45:18 -0700498 genArrayGet(cUnit, optFlags, kSignedByte, rlSrc[0], rlSrc[1], rlDest, 0);
Bill Buzbeea114add2012-05-03 15:00:40 -0700499 break;
500 case Instruction::AGET_CHAR:
buzbee408ad162012-06-06 16:45:18 -0700501 genArrayGet(cUnit, optFlags, kUnsignedHalf, rlSrc[0], rlSrc[1], rlDest, 1);
Bill Buzbeea114add2012-05-03 15:00:40 -0700502 break;
503 case Instruction::AGET_SHORT:
buzbee408ad162012-06-06 16:45:18 -0700504 genArrayGet(cUnit, optFlags, kSignedHalf, rlSrc[0], rlSrc[1], rlDest, 1);
Bill Buzbeea114add2012-05-03 15:00:40 -0700505 break;
506 case Instruction::APUT_WIDE:
buzbee408ad162012-06-06 16:45:18 -0700507 genArrayPut(cUnit, optFlags, kLong, rlSrc[1], rlSrc[2], rlSrc[0], 3);
Bill Buzbeea114add2012-05-03 15:00:40 -0700508 break;
509 case Instruction::APUT:
buzbee408ad162012-06-06 16:45:18 -0700510 genArrayPut(cUnit, optFlags, kWord, rlSrc[1], rlSrc[2], rlSrc[0], 2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700511 break;
512 case Instruction::APUT_OBJECT:
buzbee408ad162012-06-06 16:45:18 -0700513 genArrayObjPut(cUnit, optFlags, rlSrc[1], rlSrc[2], rlSrc[0], 2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700514 break;
515 case Instruction::APUT_SHORT:
516 case Instruction::APUT_CHAR:
buzbee408ad162012-06-06 16:45:18 -0700517 genArrayPut(cUnit, optFlags, kUnsignedHalf, rlSrc[1], rlSrc[2], rlSrc[0], 1);
Bill Buzbeea114add2012-05-03 15:00:40 -0700518 break;
519 case Instruction::APUT_BYTE:
520 case Instruction::APUT_BOOLEAN:
buzbee408ad162012-06-06 16:45:18 -0700521 genArrayPut(cUnit, optFlags, kUnsignedByte, rlSrc[1], rlSrc[2],
Bill Buzbeea114add2012-05-03 15:00:40 -0700522 rlSrc[0], 0);
523 break;
524
525 case Instruction::IGET_OBJECT:
526 //case Instruction::IGET_OBJECT_VOLATILE:
buzbee408ad162012-06-06 16:45:18 -0700527 genIGet(cUnit, vC, optFlags, kWord, rlDest, rlSrc[0], false, true);
Bill Buzbeea114add2012-05-03 15:00:40 -0700528 break;
529
530 case Instruction::IGET_WIDE:
531 //case Instruction::IGET_WIDE_VOLATILE:
buzbee408ad162012-06-06 16:45:18 -0700532 genIGet(cUnit, vC, optFlags, kLong, rlDest, rlSrc[0], true, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700533 break;
534
535 case Instruction::IGET:
536 //case Instruction::IGET_VOLATILE:
buzbee408ad162012-06-06 16:45:18 -0700537 genIGet(cUnit, vC, optFlags, kWord, rlDest, rlSrc[0], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700538 break;
539
540 case Instruction::IGET_CHAR:
buzbee408ad162012-06-06 16:45:18 -0700541 genIGet(cUnit, vC, optFlags, kUnsignedHalf, rlDest, rlSrc[0], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700542 break;
543
544 case Instruction::IGET_SHORT:
buzbee408ad162012-06-06 16:45:18 -0700545 genIGet(cUnit, vC, optFlags, kSignedHalf, rlDest, rlSrc[0], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700546 break;
547
548 case Instruction::IGET_BOOLEAN:
549 case Instruction::IGET_BYTE:
buzbee408ad162012-06-06 16:45:18 -0700550 genIGet(cUnit, vC, optFlags, kUnsignedByte, rlDest, rlSrc[0], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700551 break;
552
553 case Instruction::IPUT_WIDE:
554 //case Instruction::IPUT_WIDE_VOLATILE:
buzbee408ad162012-06-06 16:45:18 -0700555 genIPut(cUnit, vC, optFlags, kLong, rlSrc[0], rlSrc[1], true, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700556 break;
557
558 case Instruction::IPUT_OBJECT:
559 //case Instruction::IPUT_OBJECT_VOLATILE:
buzbee408ad162012-06-06 16:45:18 -0700560 genIPut(cUnit, vC, optFlags, kWord, rlSrc[0], rlSrc[1], false, true);
Bill Buzbeea114add2012-05-03 15:00:40 -0700561 break;
562
563 case Instruction::IPUT:
564 //case Instruction::IPUT_VOLATILE:
buzbee408ad162012-06-06 16:45:18 -0700565 genIPut(cUnit, vC, optFlags, kWord, rlSrc[0], rlSrc[1], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700566 break;
567
568 case Instruction::IPUT_BOOLEAN:
569 case Instruction::IPUT_BYTE:
buzbee408ad162012-06-06 16:45:18 -0700570 genIPut(cUnit, vC, optFlags, kUnsignedByte, rlSrc[0], rlSrc[1], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700571 break;
572
573 case Instruction::IPUT_CHAR:
buzbee408ad162012-06-06 16:45:18 -0700574 genIPut(cUnit, vC, optFlags, kUnsignedHalf, rlSrc[0], rlSrc[1], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700575 break;
576
577 case Instruction::IPUT_SHORT:
buzbee408ad162012-06-06 16:45:18 -0700578 genIPut(cUnit, vC, optFlags, kSignedHalf, rlSrc[0], rlSrc[1], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700579 break;
580
581 case Instruction::SGET_OBJECT:
buzbee408ad162012-06-06 16:45:18 -0700582 genSget(cUnit, vB, rlDest, false, true);
Bill Buzbeea114add2012-05-03 15:00:40 -0700583 break;
584 case Instruction::SGET:
585 case Instruction::SGET_BOOLEAN:
586 case Instruction::SGET_BYTE:
587 case Instruction::SGET_CHAR:
588 case Instruction::SGET_SHORT:
buzbee408ad162012-06-06 16:45:18 -0700589 genSget(cUnit, vB, rlDest, false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700590 break;
591
592 case Instruction::SGET_WIDE:
buzbee408ad162012-06-06 16:45:18 -0700593 genSget(cUnit, vB, rlDest, true, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700594 break;
595
596 case Instruction::SPUT_OBJECT:
buzbee408ad162012-06-06 16:45:18 -0700597 genSput(cUnit, vB, rlSrc[0], false, true);
Bill Buzbeea114add2012-05-03 15:00:40 -0700598 break;
599
600 case Instruction::SPUT:
601 case Instruction::SPUT_BOOLEAN:
602 case Instruction::SPUT_BYTE:
603 case Instruction::SPUT_CHAR:
604 case Instruction::SPUT_SHORT:
buzbee408ad162012-06-06 16:45:18 -0700605 genSput(cUnit, vB, rlSrc[0], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700606 break;
607
608 case Instruction::SPUT_WIDE:
buzbee408ad162012-06-06 16:45:18 -0700609 genSput(cUnit, vB, rlSrc[0], true, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700610 break;
611
612 case Instruction::INVOKE_STATIC_RANGE:
buzbee15bf9802012-06-12 17:49:27 -0700613 genInvoke(cUnit, newInvokeInfo(cUnit, bb, mir, kStatic, true));
Bill Buzbeea114add2012-05-03 15:00:40 -0700614 break;
615 case Instruction::INVOKE_STATIC:
buzbee15bf9802012-06-12 17:49:27 -0700616 genInvoke(cUnit, newInvokeInfo(cUnit, bb, mir, kStatic, false));
Bill Buzbeea114add2012-05-03 15:00:40 -0700617 break;
618
619 case Instruction::INVOKE_DIRECT:
buzbee15bf9802012-06-12 17:49:27 -0700620 genInvoke(cUnit, newInvokeInfo(cUnit, bb, mir, kDirect, false));
Bill Buzbeea114add2012-05-03 15:00:40 -0700621 break;
622 case Instruction::INVOKE_DIRECT_RANGE:
buzbee15bf9802012-06-12 17:49:27 -0700623 genInvoke(cUnit, newInvokeInfo(cUnit, bb, mir, kDirect, true));
Bill Buzbeea114add2012-05-03 15:00:40 -0700624 break;
625
626 case Instruction::INVOKE_VIRTUAL:
buzbee15bf9802012-06-12 17:49:27 -0700627 genInvoke(cUnit, newInvokeInfo(cUnit, bb, mir, kVirtual, false));
Bill Buzbeea114add2012-05-03 15:00:40 -0700628 break;
629 case Instruction::INVOKE_VIRTUAL_RANGE:
buzbee15bf9802012-06-12 17:49:27 -0700630 genInvoke(cUnit, newInvokeInfo(cUnit, bb, mir, kVirtual, true));
Bill Buzbeea114add2012-05-03 15:00:40 -0700631 break;
632
633 case Instruction::INVOKE_SUPER:
buzbee15bf9802012-06-12 17:49:27 -0700634 genInvoke(cUnit, newInvokeInfo(cUnit, bb, mir, kSuper, false));
Bill Buzbeea114add2012-05-03 15:00:40 -0700635 break;
636 case Instruction::INVOKE_SUPER_RANGE:
buzbee15bf9802012-06-12 17:49:27 -0700637 genInvoke(cUnit, newInvokeInfo(cUnit, bb, mir, kSuper, true));
Bill Buzbeea114add2012-05-03 15:00:40 -0700638 break;
639
640 case Instruction::INVOKE_INTERFACE:
buzbee15bf9802012-06-12 17:49:27 -0700641 genInvoke(cUnit, newInvokeInfo(cUnit, bb, mir, kInterface, false));
Bill Buzbeea114add2012-05-03 15:00:40 -0700642 break;
643 case Instruction::INVOKE_INTERFACE_RANGE:
buzbee15bf9802012-06-12 17:49:27 -0700644 genInvoke(cUnit, newInvokeInfo(cUnit, bb, mir, kInterface, true));
Bill Buzbeea114add2012-05-03 15:00:40 -0700645 break;
646
647 case Instruction::NEG_INT:
648 case Instruction::NOT_INT:
buzbee408ad162012-06-06 16:45:18 -0700649 res = genArithOpInt(cUnit, opcode, rlDest, rlSrc[0], rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700650 break;
651
652 case Instruction::NEG_LONG:
653 case Instruction::NOT_LONG:
buzbee408ad162012-06-06 16:45:18 -0700654 res = genArithOpLong(cUnit, opcode, rlDest, rlSrc[0], rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700655 break;
656
657 case Instruction::NEG_FLOAT:
buzbee408ad162012-06-06 16:45:18 -0700658 res = genArithOpFloat(cUnit, opcode, rlDest, rlSrc[0], rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700659 break;
660
661 case Instruction::NEG_DOUBLE:
buzbee408ad162012-06-06 16:45:18 -0700662 res = genArithOpDouble(cUnit, opcode, rlDest, rlSrc[0], rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700663 break;
664
665 case Instruction::INT_TO_LONG:
buzbee408ad162012-06-06 16:45:18 -0700666 genIntToLong(cUnit, rlDest, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700667 break;
668
669 case Instruction::LONG_TO_INT:
670 rlSrc[0] = oatUpdateLocWide(cUnit, rlSrc[0]);
671 rlSrc[0] = oatWideToNarrow(cUnit, rlSrc[0]);
672 storeValue(cUnit, rlDest, rlSrc[0]);
673 break;
674
675 case Instruction::INT_TO_BYTE:
676 case Instruction::INT_TO_SHORT:
677 case Instruction::INT_TO_CHAR:
buzbee408ad162012-06-06 16:45:18 -0700678 genIntNarrowing(cUnit, opcode, rlDest, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700679 break;
680
681 case Instruction::INT_TO_FLOAT:
682 case Instruction::INT_TO_DOUBLE:
683 case Instruction::LONG_TO_FLOAT:
684 case Instruction::LONG_TO_DOUBLE:
685 case Instruction::FLOAT_TO_INT:
686 case Instruction::FLOAT_TO_LONG:
687 case Instruction::FLOAT_TO_DOUBLE:
688 case Instruction::DOUBLE_TO_INT:
689 case Instruction::DOUBLE_TO_LONG:
690 case Instruction::DOUBLE_TO_FLOAT:
buzbee408ad162012-06-06 16:45:18 -0700691 genConversion(cUnit, opcode, rlDest, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700692 break;
693
694 case Instruction::ADD_INT:
695 case Instruction::SUB_INT:
696 case Instruction::MUL_INT:
697 case Instruction::DIV_INT:
698 case Instruction::REM_INT:
699 case Instruction::AND_INT:
700 case Instruction::OR_INT:
701 case Instruction::XOR_INT:
702 case Instruction::SHL_INT:
703 case Instruction::SHR_INT:
704 case Instruction::USHR_INT:
705 case Instruction::ADD_INT_2ADDR:
706 case Instruction::SUB_INT_2ADDR:
707 case Instruction::MUL_INT_2ADDR:
708 case Instruction::DIV_INT_2ADDR:
709 case Instruction::REM_INT_2ADDR:
710 case Instruction::AND_INT_2ADDR:
711 case Instruction::OR_INT_2ADDR:
712 case Instruction::XOR_INT_2ADDR:
713 case Instruction::SHL_INT_2ADDR:
714 case Instruction::SHR_INT_2ADDR:
715 case Instruction::USHR_INT_2ADDR:
buzbee408ad162012-06-06 16:45:18 -0700716 genArithOpInt(cUnit, opcode, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700717 break;
718
719 case Instruction::ADD_LONG:
720 case Instruction::SUB_LONG:
721 case Instruction::MUL_LONG:
722 case Instruction::DIV_LONG:
723 case Instruction::REM_LONG:
724 case Instruction::AND_LONG:
725 case Instruction::OR_LONG:
726 case Instruction::XOR_LONG:
727 case Instruction::ADD_LONG_2ADDR:
728 case Instruction::SUB_LONG_2ADDR:
729 case Instruction::MUL_LONG_2ADDR:
730 case Instruction::DIV_LONG_2ADDR:
731 case Instruction::REM_LONG_2ADDR:
732 case Instruction::AND_LONG_2ADDR:
733 case Instruction::OR_LONG_2ADDR:
734 case Instruction::XOR_LONG_2ADDR:
buzbee408ad162012-06-06 16:45:18 -0700735 genArithOpLong(cUnit, opcode, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700736 break;
737
738 case Instruction::SHL_LONG:
739 case Instruction::SHR_LONG:
740 case Instruction::USHR_LONG:
741 case Instruction::SHL_LONG_2ADDR:
742 case Instruction::SHR_LONG_2ADDR:
743 case Instruction::USHR_LONG_2ADDR:
buzbee408ad162012-06-06 16:45:18 -0700744 genShiftOpLong(cUnit, opcode, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700745 break;
746
747 case Instruction::ADD_FLOAT:
748 case Instruction::SUB_FLOAT:
749 case Instruction::MUL_FLOAT:
750 case Instruction::DIV_FLOAT:
751 case Instruction::REM_FLOAT:
752 case Instruction::ADD_FLOAT_2ADDR:
753 case Instruction::SUB_FLOAT_2ADDR:
754 case Instruction::MUL_FLOAT_2ADDR:
755 case Instruction::DIV_FLOAT_2ADDR:
756 case Instruction::REM_FLOAT_2ADDR:
buzbee408ad162012-06-06 16:45:18 -0700757 genArithOpFloat(cUnit, opcode, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700758 break;
759
760 case Instruction::ADD_DOUBLE:
761 case Instruction::SUB_DOUBLE:
762 case Instruction::MUL_DOUBLE:
763 case Instruction::DIV_DOUBLE:
764 case Instruction::REM_DOUBLE:
765 case Instruction::ADD_DOUBLE_2ADDR:
766 case Instruction::SUB_DOUBLE_2ADDR:
767 case Instruction::MUL_DOUBLE_2ADDR:
768 case Instruction::DIV_DOUBLE_2ADDR:
769 case Instruction::REM_DOUBLE_2ADDR:
buzbee408ad162012-06-06 16:45:18 -0700770 genArithOpDouble(cUnit, opcode, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700771 break;
772
773 case Instruction::RSUB_INT:
774 case Instruction::ADD_INT_LIT16:
775 case Instruction::MUL_INT_LIT16:
776 case Instruction::DIV_INT_LIT16:
777 case Instruction::REM_INT_LIT16:
778 case Instruction::AND_INT_LIT16:
779 case Instruction::OR_INT_LIT16:
780 case Instruction::XOR_INT_LIT16:
781 case Instruction::ADD_INT_LIT8:
782 case Instruction::RSUB_INT_LIT8:
783 case Instruction::MUL_INT_LIT8:
784 case Instruction::DIV_INT_LIT8:
785 case Instruction::REM_INT_LIT8:
786 case Instruction::AND_INT_LIT8:
787 case Instruction::OR_INT_LIT8:
788 case Instruction::XOR_INT_LIT8:
789 case Instruction::SHL_INT_LIT8:
790 case Instruction::SHR_INT_LIT8:
791 case Instruction::USHR_INT_LIT8:
buzbee408ad162012-06-06 16:45:18 -0700792 genArithOpIntLit(cUnit, opcode, rlDest, rlSrc[0], vC);
Bill Buzbeea114add2012-05-03 15:00:40 -0700793 break;
794
795 default:
796 res = true;
797 }
798 return res;
buzbeee3acd072012-02-25 17:03:10 -0800799}
800
buzbee31a4a6f2012-02-28 15:36:15 -0800801const char* extendedMIROpNames[kMirOpLast - kMirOpFirst] = {
Bill Buzbeea114add2012-05-03 15:00:40 -0700802 "kMirOpPhi",
803 "kMirOpCopy",
804 "kMirFusedCmplFloat",
805 "kMirFusedCmpgFloat",
806 "kMirFusedCmplDouble",
807 "kMirFusedCmpgDouble",
808 "kMirFusedCmpLong",
809 "kMirNop",
810 "kMirOpNullNRangeUpCheck",
811 "kMirOpNullNRangeDownCheck",
812 "kMirOpLowerBound",
buzbeee3acd072012-02-25 17:03:10 -0800813};
814
815/* Extended MIR instructions like PHI */
buzbee84fd6932012-03-29 16:44:16 -0700816void handleExtendedMethodMIR(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir)
buzbeee3acd072012-02-25 17:03:10 -0800817{
Bill Buzbeea114add2012-05-03 15:00:40 -0700818 int opOffset = mir->dalvikInsn.opcode - kMirOpFirst;
819 char* msg = NULL;
820 if (cUnit->printMe) {
821 msg = (char*)oatNew(cUnit, strlen(extendedMIROpNames[opOffset]) + 1,
822 false, kAllocDebugInfo);
823 strcpy(msg, extendedMIROpNames[opOffset]);
824 }
825 LIR* op = newLIR1(cUnit, kPseudoExtended, (int) msg);
buzbeee3acd072012-02-25 17:03:10 -0800826
Bill Buzbeea114add2012-05-03 15:00:40 -0700827 switch ((ExtendedMIROpcode)mir->dalvikInsn.opcode) {
828 case kMirOpPhi: {
829 char* ssaString = NULL;
830 if (cUnit->printMe) {
831 ssaString = oatGetSSAString(cUnit, mir->ssaRep);
832 }
833 op->flags.isNop = true;
834 newLIR1(cUnit, kPseudoSSARep, (int) ssaString);
835 break;
buzbeee3acd072012-02-25 17:03:10 -0800836 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700837 case kMirOpCopy: {
838 RegLocation rlSrc = oatGetSrc(cUnit, mir, 0);
buzbee15bf9802012-06-12 17:49:27 -0700839 RegLocation rlDest = oatGetDest(cUnit, mir);
Bill Buzbeea114add2012-05-03 15:00:40 -0700840 storeValue(cUnit, rlDest, rlSrc);
841 break;
842 }
843#if defined(TARGET_ARM)
844 case kMirOpFusedCmplFloat:
845 genFusedFPCmpBranch(cUnit, bb, mir, false /*gt bias*/, false /*double*/);
846 break;
847 case kMirOpFusedCmpgFloat:
848 genFusedFPCmpBranch(cUnit, bb, mir, true /*gt bias*/, false /*double*/);
849 break;
850 case kMirOpFusedCmplDouble:
851 genFusedFPCmpBranch(cUnit, bb, mir, false /*gt bias*/, true /*double*/);
852 break;
853 case kMirOpFusedCmpgDouble:
854 genFusedFPCmpBranch(cUnit, bb, mir, true /*gt bias*/, true /*double*/);
855 break;
856 case kMirOpFusedCmpLong:
857 genFusedLongCmpBranch(cUnit, bb, mir);
858 break;
859#endif
860 default:
861 break;
862 }
buzbeee3acd072012-02-25 17:03:10 -0800863}
864
865/* Handle the content in each basic block */
buzbee31a4a6f2012-02-28 15:36:15 -0800866bool methodBlockCodeGen(CompilationUnit* cUnit, BasicBlock* bb)
buzbeee3acd072012-02-25 17:03:10 -0800867{
Bill Buzbeea114add2012-05-03 15:00:40 -0700868 MIR* mir;
869 LIR* labelList = (LIR*) cUnit->blockLabelList;
870 int blockId = bb->id;
buzbeee3acd072012-02-25 17:03:10 -0800871
Bill Buzbeea114add2012-05-03 15:00:40 -0700872 cUnit->curBlock = bb;
873 labelList[blockId].operands[0] = bb->startOffset;
buzbeee3acd072012-02-25 17:03:10 -0800874
Bill Buzbeea114add2012-05-03 15:00:40 -0700875 /* Insert the block label */
876 labelList[blockId].opcode = kPseudoNormalBlockLabel;
877 oatAppendLIR(cUnit, (LIR*) &labelList[blockId]);
buzbeee3acd072012-02-25 17:03:10 -0800878
Bill Buzbeea114add2012-05-03 15:00:40 -0700879 /* Free temp registers and reset redundant store tracking */
880 oatResetRegPool(cUnit);
881 oatResetDefTracking(cUnit);
882
883 /*
884 * If control reached us from our immediate predecessor via
885 * fallthrough and we have no other incoming arcs we can
886 * reuse existing liveness. Otherwise, reset.
887 */
888 if (!bb->fallThroughTarget || bb->predecessors->numUsed != 1) {
889 oatClobberAllRegs(cUnit);
890 }
891
892 LIR* headLIR = NULL;
893
894 if (bb->blockType == kEntryBlock) {
buzbee2cfc6392012-05-07 14:51:40 -0700895 genEntrySequence(cUnit);
Bill Buzbeea114add2012-05-03 15:00:40 -0700896 } else if (bb->blockType == kExitBlock) {
buzbee2cfc6392012-05-07 14:51:40 -0700897 genExitSequence(cUnit);
Bill Buzbeea114add2012-05-03 15:00:40 -0700898 }
899
900 for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
901
buzbeee3acd072012-02-25 17:03:10 -0800902 oatResetRegPool(cUnit);
Bill Buzbeea114add2012-05-03 15:00:40 -0700903 if (cUnit->disableOpt & (1 << kTrackLiveTemps)) {
904 oatClobberAllRegs(cUnit);
buzbeee1965672012-03-11 18:39:19 -0700905 }
906
Bill Buzbeea114add2012-05-03 15:00:40 -0700907 if (cUnit->disableOpt & (1 << kSuppressLoads)) {
908 oatResetDefTracking(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800909 }
910
buzbee3d661942012-03-14 17:37:27 -0700911#ifndef NDEBUG
Bill Buzbeea114add2012-05-03 15:00:40 -0700912 /* Reset temp tracking sanity check */
913 cUnit->liveSReg = INVALID_SREG;
buzbee3d661942012-03-14 17:37:27 -0700914#endif
915
Bill Buzbeea114add2012-05-03 15:00:40 -0700916 cUnit->currentDalvikOffset = mir->offset;
buzbeee3acd072012-02-25 17:03:10 -0800917
Bill Buzbeea114add2012-05-03 15:00:40 -0700918 Instruction::Code dalvikOpcode = mir->dalvikInsn.opcode;
919 Instruction::Format dalvikFormat = Instruction::FormatOf(dalvikOpcode);
buzbeee3acd072012-02-25 17:03:10 -0800920
Bill Buzbeea114add2012-05-03 15:00:40 -0700921 LIR* boundaryLIR;
buzbeee3acd072012-02-25 17:03:10 -0800922
Bill Buzbeea114add2012-05-03 15:00:40 -0700923 /* Mark the beginning of a Dalvik instruction for line tracking */
924 char* instStr = cUnit->printMe ?
925 oatGetDalvikDisassembly(cUnit, mir->dalvikInsn, "") : NULL;
926 boundaryLIR = newLIR1(cUnit, kPseudoDalvikByteCodeBoundary,
927 (intptr_t) instStr);
928 cUnit->boundaryMap.Overwrite(mir->offset, boundaryLIR);
929 /* Remember the first LIR for this block */
930 if (headLIR == NULL) {
931 headLIR = boundaryLIR;
932 /* Set the first boundaryLIR as a scheduling barrier */
933 headLIR->defMask = ENCODE_ALL;
buzbeee3acd072012-02-25 17:03:10 -0800934 }
935
Bill Buzbeea114add2012-05-03 15:00:40 -0700936 /* If we're compiling for the debugger, generate an update callout */
937 if (cUnit->genDebugger) {
938 genDebuggerUpdate(cUnit, mir->offset);
buzbeee3acd072012-02-25 17:03:10 -0800939 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700940
941 /* Don't generate the SSA annotation unless verbose mode is on */
942 if (cUnit->printMe && mir->ssaRep) {
943 char* ssaString = oatGetSSAString(cUnit, mir->ssaRep);
944 newLIR1(cUnit, kPseudoSSARep, (int) ssaString);
945 }
946
947 if ((int)mir->dalvikInsn.opcode >= (int)kMirOpFirst) {
948 handleExtendedMethodMIR(cUnit, bb, mir);
949 continue;
950 }
951
952 bool notHandled = compileDalvikInstruction(cUnit, mir, bb, labelList);
953 if (notHandled) {
954 LOG(FATAL) << StringPrintf("%#06x: Opcode %#x (%s) / Fmt %d not handled",
955 mir->offset, dalvikOpcode,
956 Instruction::Name(dalvikOpcode), dalvikFormat);
957
958 }
959 }
960
961 if (headLIR) {
962 /*
963 * Eliminate redundant loads/stores and delay stores into later
964 * slots
965 */
966 oatApplyLocalOptimizations(cUnit, (LIR*) headLIR, cUnit->lastLIRInsn);
967
968 /*
969 * Generate an unconditional branch to the fallthrough block.
970 */
971 if (bb->fallThrough) {
972 opUnconditionalBranch(cUnit, &labelList[bb->fallThrough->id]);
973 }
974 }
975 return false;
buzbeee3acd072012-02-25 17:03:10 -0800976}
977
buzbee16da88c2012-03-20 10:38:17 -0700978/* Set basic block labels */
979bool labelBlocks(CompilationUnit* cUnit, BasicBlock* bb)
980{
Bill Buzbeea114add2012-05-03 15:00:40 -0700981 LIR* labelList = (LIR*) cUnit->blockLabelList;
982 int blockId = bb->id;
buzbee16da88c2012-03-20 10:38:17 -0700983
Bill Buzbeea114add2012-05-03 15:00:40 -0700984 cUnit->curBlock = bb;
985 labelList[blockId].operands[0] = bb->startOffset;
buzbee16da88c2012-03-20 10:38:17 -0700986
Bill Buzbeea114add2012-05-03 15:00:40 -0700987 /* Insert the block label */
988 labelList[blockId].opcode = kPseudoNormalBlockLabel;
989 return false;
buzbee16da88c2012-03-20 10:38:17 -0700990}
991
992void oatSpecialMIR2LIR(CompilationUnit* cUnit, SpecialCaseHandler specialCase)
993{
Bill Buzbeea114add2012-05-03 15:00:40 -0700994 /* Find the first DalvikByteCode block */
995 int numReachableBlocks = cUnit->numReachableBlocks;
996 const GrowableList *blockList = &cUnit->blockList;
997 BasicBlock*bb = NULL;
998 for (int idx = 0; idx < numReachableBlocks; idx++) {
999 int dfsIndex = cUnit->dfsOrder.elemList[idx];
1000 bb = (BasicBlock*)oatGrowableListGetElement(blockList, dfsIndex);
1001 if (bb->blockType == kDalvikByteCode) {
1002 break;
buzbee16da88c2012-03-20 10:38:17 -07001003 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001004 }
1005 if (bb == NULL) {
1006 return;
1007 }
1008 DCHECK_EQ(bb->startOffset, 0);
1009 DCHECK(bb->firstMIRInsn != 0);
buzbee16da88c2012-03-20 10:38:17 -07001010
Bill Buzbeea114add2012-05-03 15:00:40 -07001011 /* Get the first instruction */
1012 MIR* mir = bb->firstMIRInsn;
buzbee16da88c2012-03-20 10:38:17 -07001013
Bill Buzbeea114add2012-05-03 15:00:40 -07001014 /* Free temp registers and reset redundant store tracking */
1015 oatResetRegPool(cUnit);
1016 oatResetDefTracking(cUnit);
1017 oatClobberAllRegs(cUnit);
buzbee16da88c2012-03-20 10:38:17 -07001018
Bill Buzbeea114add2012-05-03 15:00:40 -07001019 genSpecialCase(cUnit, bb, mir, specialCase);
buzbee16da88c2012-03-20 10:38:17 -07001020}
1021
buzbeee3acd072012-02-25 17:03:10 -08001022void oatMethodMIR2LIR(CompilationUnit* cUnit)
1023{
Bill Buzbeea114add2012-05-03 15:00:40 -07001024 /* Used to hold the labels of each block */
1025 cUnit->blockLabelList =
1026 (void *) oatNew(cUnit, sizeof(LIR) * cUnit->numBlocks, true, kAllocLIR);
buzbeee3acd072012-02-25 17:03:10 -08001027
Bill Buzbeea114add2012-05-03 15:00:40 -07001028 oatDataFlowAnalysisDispatcher(cUnit, methodBlockCodeGen,
1029 kPreOrderDFSTraversal, false /* Iterative */);
Ian Rogersab2b55d2012-03-18 00:06:11 -07001030
Bill Buzbeea114add2012-05-03 15:00:40 -07001031 handleSuspendLaunchpads(cUnit);
buzbeee3acd072012-02-25 17:03:10 -08001032
Bill Buzbeea114add2012-05-03 15:00:40 -07001033 handleThrowLaunchpads(cUnit);
buzbeee3acd072012-02-25 17:03:10 -08001034
Bill Buzbeea114add2012-05-03 15:00:40 -07001035 handleIntrinsicLaunchpads(cUnit);
buzbeefc9e6fa2012-03-23 15:14:29 -07001036
Bill Buzbeea114add2012-05-03 15:00:40 -07001037 if (!(cUnit->disableOpt & (1 << kSafeOptimizations))) {
1038 removeRedundantBranches(cUnit);
1039 }
buzbeee3acd072012-02-25 17:03:10 -08001040}
1041
1042/* Needed by the ld/st optmizatons */
buzbee31a4a6f2012-02-28 15:36:15 -08001043LIR* oatRegCopyNoInsert(CompilationUnit* cUnit, int rDest, int rSrc)
buzbeee3acd072012-02-25 17:03:10 -08001044{
Bill Buzbeea114add2012-05-03 15:00:40 -07001045 return opRegCopyNoInsert(cUnit, rDest, rSrc);
buzbeee3acd072012-02-25 17:03:10 -08001046}
1047
1048/* Needed by the register allocator */
1049void oatRegCopy(CompilationUnit* cUnit, int rDest, int rSrc)
1050{
Bill Buzbeea114add2012-05-03 15:00:40 -07001051 opRegCopy(cUnit, rDest, rSrc);
buzbeee3acd072012-02-25 17:03:10 -08001052}
1053
1054/* Needed by the register allocator */
1055void oatRegCopyWide(CompilationUnit* cUnit, int destLo, int destHi,
Bill Buzbeea114add2012-05-03 15:00:40 -07001056 int srcLo, int srcHi)
buzbeee3acd072012-02-25 17:03:10 -08001057{
Bill Buzbeea114add2012-05-03 15:00:40 -07001058 opRegCopyWide(cUnit, destLo, destHi, srcLo, srcHi);
buzbeee3acd072012-02-25 17:03:10 -08001059}
1060
1061void oatFlushRegImpl(CompilationUnit* cUnit, int rBase,
Bill Buzbeea114add2012-05-03 15:00:40 -07001062 int displacement, int rSrc, OpSize size)
buzbeee3acd072012-02-25 17:03:10 -08001063{
Bill Buzbeea114add2012-05-03 15:00:40 -07001064 storeBaseDisp(cUnit, rBase, displacement, rSrc, size);
buzbeee3acd072012-02-25 17:03:10 -08001065}
1066
1067void oatFlushRegWideImpl(CompilationUnit* cUnit, int rBase,
Bill Buzbeea114add2012-05-03 15:00:40 -07001068 int displacement, int rSrcLo, int rSrcHi)
buzbeee3acd072012-02-25 17:03:10 -08001069{
Bill Buzbeea114add2012-05-03 15:00:40 -07001070 storeBaseDispWide(cUnit, rBase, displacement, rSrcLo, rSrcHi);
buzbeee3acd072012-02-25 17:03:10 -08001071}
1072
1073} // namespace art