blob: 4ca06b70da1fc479c30dded1d8a30d373c31be33 [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
buzbeeeaf09bc2012-11-15 14:51:41 -080019#include "local_optimizations.h"
20
buzbeee3acd072012-02-25 17:03:10 -080021namespace art {
22
buzbee2cfc6392012-05-07 14:51:40 -070023const RegLocation badLoc = {kLocDalvikFrame, 0, 0, 0, 0, 0, 0, 0, 0,
24 INVALID_REG, INVALID_REG, INVALID_SREG,
25 INVALID_SREG};
buzbeee3acd072012-02-25 17:03:10 -080026
27/* Mark register usage state and return long retloc */
Ian Rogersf7d9ad32012-03-13 18:45:39 -070028RegLocation oatGetReturnWide(CompilationUnit* cUnit, bool isDouble)
buzbeee3acd072012-02-25 17:03:10 -080029{
buzbeef0504cd2012-11-13 16:31:10 -080030 RegLocation gpr_res = locCReturnWide();
31 RegLocation fpr_res = locCReturnDouble();
Bill Buzbeea114add2012-05-03 15:00:40 -070032 RegLocation res = isDouble ? fpr_res : gpr_res;
33 oatClobber(cUnit, res.lowReg);
34 oatClobber(cUnit, res.highReg);
35 oatLockTemp(cUnit, res.lowReg);
36 oatLockTemp(cUnit, res.highReg);
37 oatMarkPair(cUnit, res.lowReg, res.highReg);
38 return res;
buzbeee3acd072012-02-25 17:03:10 -080039}
40
Ian Rogersf7d9ad32012-03-13 18:45:39 -070041RegLocation oatGetReturn(CompilationUnit* cUnit, bool isFloat)
buzbeee3acd072012-02-25 17:03:10 -080042{
buzbeef0504cd2012-11-13 16:31:10 -080043 RegLocation gpr_res = locCReturn();
44 RegLocation fpr_res = locCReturnFloat();
Ian Rogersf7d9ad32012-03-13 18:45:39 -070045 RegLocation res = isFloat ? fpr_res : gpr_res;
Bill Buzbeea114add2012-05-03 15:00:40 -070046 oatClobber(cUnit, res.lowReg);
47 if (cUnit->instructionSet == kMips) {
48 oatMarkInUse(cUnit, res.lowReg);
49 } else {
50 oatLockTemp(cUnit, res.lowReg);
51 }
52 return res;
buzbeee3acd072012-02-25 17:03:10 -080053}
54
buzbeeeaf09bc2012-11-15 14:51:41 -080055// TODO: move to gen_invoke.cc
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) {
Ian Rogers137e88f2012-10-08 17:46:47 -070086 if (fastPath) {
87 pNullCk = &nullCk;
88 }
Bill Buzbeea114add2012-05-03 15:00:40 -070089 nextCallInsn = fastPath ? nextInterfaceCallInsn
Ian Rogers137e88f2012-10-08 17:46:47 -070090 : nextInterfaceCallInsnWithAccessCheck;
Bill Buzbeea114add2012-05-03 15:00:40 -070091 skipThis = false;
buzbee15bf9802012-06-12 17:49:27 -070092 } else if (info->type == kDirect) {
Bill Buzbeea114add2012-05-03 15:00:40 -070093 if (fastPath) {
94 pNullCk = &nullCk;
buzbeee3acd072012-02-25 17:03:10 -080095 }
Bill Buzbeea114add2012-05-03 15:00:40 -070096 nextCallInsn = fastPath ? nextSDCallInsn : nextDirectCallInsnSP;
97 skipThis = false;
buzbee15bf9802012-06-12 17:49:27 -070098 } else if (info->type == kStatic) {
Bill Buzbeea114add2012-05-03 15:00:40 -070099 nextCallInsn = fastPath ? nextSDCallInsn : nextStaticCallInsnSP;
100 skipThis = false;
buzbee15bf9802012-06-12 17:49:27 -0700101 } else if (info->type == kSuper) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700102 DCHECK(!fastPath); // Fast path is a direct call.
103 nextCallInsn = nextSuperCallInsnSP;
104 skipThis = false;
105 } else {
buzbee15bf9802012-06-12 17:49:27 -0700106 DCHECK_EQ(info->type, kVirtual);
Bill Buzbeea114add2012-05-03 15:00:40 -0700107 nextCallInsn = fastPath ? nextVCallInsn : nextVCallInsnSP;
108 skipThis = fastPath;
109 }
buzbee15bf9802012-06-12 17:49:27 -0700110 if (!info->isRange) {
111 callState = genDalvikArgsNoRange(cUnit, info, callState, pNullCk,
Bill Buzbeea114add2012-05-03 15:00:40 -0700112 nextCallInsn, dexMethodIdx,
113 vtableIdx, directCode, directMethod,
114 originalType, skipThis);
115 } else {
buzbee15bf9802012-06-12 17:49:27 -0700116 callState = genDalvikArgsRange(cUnit, info, callState, pNullCk,
Bill Buzbeea114add2012-05-03 15:00:40 -0700117 nextCallInsn, dexMethodIdx, vtableIdx,
118 directCode, directMethod, originalType,
119 skipThis);
120 }
121 // Finish up any of the call sequence not interleaved in arg loading
122 while (callState >= 0) {
buzbee15bf9802012-06-12 17:49:27 -0700123 callState = nextCallInsn(cUnit, info, callState, dexMethodIdx,
Bill Buzbeea114add2012-05-03 15:00:40 -0700124 vtableIdx, directCode, directMethod,
125 originalType);
126 }
buzbeeb046e162012-10-30 15:48:42 -0700127 if (cUnit->enableDebug & (1 << kDebugDisplayMissingTargets)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700128 genShowTarget(cUnit);
129 }
buzbee8320f382012-09-11 16:29:42 -0700130 LIR* callInst;
buzbeeb046e162012-10-30 15:48:42 -0700131 if (cUnit->instructionSet != kX86) {
buzbeef0504cd2012-11-13 16:31:10 -0800132 callInst = opReg(cUnit, kOpBlx, targetReg(kInvokeTgt));
Bill Buzbeea114add2012-05-03 15:00:40 -0700133 } else {
buzbeeb046e162012-10-30 15:48:42 -0700134 if (fastPath && info->type != kInterface) {
buzbeef0504cd2012-11-13 16:31:10 -0800135 callInst = opMem(cUnit, kOpBlx, targetReg(kArg0),
136 AbstractMethod::GetCodeOffset().Int32Value());
buzbeeb046e162012-10-30 15:48:42 -0700137 } else {
138 int trampoline = 0;
139 switch (info->type) {
140 case kInterface:
141 trampoline = fastPath ? ENTRYPOINT_OFFSET(pInvokeInterfaceTrampoline)
142 : ENTRYPOINT_OFFSET(pInvokeInterfaceTrampolineWithAccessCheck);
143 break;
144 case kDirect:
145 trampoline = ENTRYPOINT_OFFSET(pInvokeDirectTrampolineWithAccessCheck);
146 break;
147 case kStatic:
148 trampoline = ENTRYPOINT_OFFSET(pInvokeStaticTrampolineWithAccessCheck);
149 break;
150 case kSuper:
151 trampoline = ENTRYPOINT_OFFSET(pInvokeSuperTrampolineWithAccessCheck);
152 break;
153 case kVirtual:
154 trampoline = ENTRYPOINT_OFFSET(pInvokeVirtualTrampolineWithAccessCheck);
155 break;
156 default:
157 LOG(FATAL) << "Unexpected invoke type";
158 }
159 callInst = opThreadMem(cUnit, kOpBlx, trampoline);
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700160 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700161 }
buzbee8320f382012-09-11 16:29:42 -0700162 markSafepointPC(cUnit, callInst);
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700163
Bill Buzbeea114add2012-05-03 15:00:40 -0700164 oatClobberCalleeSave(cUnit);
buzbee15bf9802012-06-12 17:49:27 -0700165 if (info->result.location != kLocInvalid) {
166 // We have a following MOVE_RESULT - do it now.
167 if (info->result.wide) {
buzbee52ed7762012-06-13 23:43:14 -0700168 RegLocation retLoc = oatGetReturnWide(cUnit, info->result.fp);
buzbee15bf9802012-06-12 17:49:27 -0700169 storeValueWide(cUnit, info->result, retLoc);
170 } else {
buzbee52ed7762012-06-13 23:43:14 -0700171 RegLocation retLoc = oatGetReturn(cUnit, info->result.fp);
buzbee15bf9802012-06-12 17:49:27 -0700172 storeValue(cUnit, info->result, retLoc);
173 }
174 }
175}
176
177/*
178 * Build an array of location records for the incoming arguments.
179 * Note: one location record per word of arguments, with dummy
180 * high-word loc for wide arguments. Also pull up any following
181 * MOVE_RESULT and incorporate it into the invoke.
182 */
buzbeeeaf09bc2012-11-15 14:51:41 -0800183//TODO: move to gen_invoke.cc or utils
buzbee6969d502012-06-15 16:40:31 -0700184CallInfo* oatNewCallInfo(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir,
185 InvokeType type, bool isRange)
buzbee15bf9802012-06-12 17:49:27 -0700186{
buzbee3b3dbdd2012-06-13 13:39:34 -0700187 CallInfo* info = (CallInfo*)oatNew(cUnit, sizeof(CallInfo), true,
buzbee15bf9802012-06-12 17:49:27 -0700188 kAllocMisc);
189 MIR* moveResultMIR = oatFindMoveResult(cUnit, bb, mir);
190 if (moveResultMIR == NULL) {
191 info->result.location = kLocInvalid;
192 } else {
193 info->result = oatGetRawDest(cUnit, moveResultMIR);
194 moveResultMIR->dalvikInsn.opcode = Instruction::NOP;
195 }
196 info->numArgWords = mir->ssaRep->numUses;
197 info->args = (info->numArgWords == 0) ? NULL : (RegLocation*)
198 oatNew(cUnit, sizeof(RegLocation) * info->numArgWords, false, kAllocMisc);
199 for (int i = 0; i < info->numArgWords; i++) {
200 info->args[i] = oatGetRawSrc(cUnit, mir, i);
201 }
202 info->optFlags = mir->optimizationFlags;
203 info->type = type;
204 info->isRange = isRange;
buzbee3b3dbdd2012-06-13 13:39:34 -0700205 info->index = mir->dalvikInsn.vB;
buzbee15bf9802012-06-12 17:49:27 -0700206 info->offset = mir->offset;
207 return info;
buzbeee3acd072012-02-25 17:03:10 -0800208}
209
210/*
211 * Target-independent code generation. Use only high-level
212 * load/store utilities here, or target-dependent genXX() handlers
213 * when necessary.
214 */
buzbee31a4a6f2012-02-28 15:36:15 -0800215bool compileDalvikInstruction(CompilationUnit* cUnit, MIR* mir,
216 BasicBlock* bb, LIR* labelList)
buzbeee3acd072012-02-25 17:03:10 -0800217{
Bill Buzbeea114add2012-05-03 15:00:40 -0700218 bool res = false; // Assume success
219 RegLocation rlSrc[3];
220 RegLocation rlDest = badLoc;
221 RegLocation rlResult = badLoc;
222 Instruction::Code opcode = mir->dalvikInsn.opcode;
buzbee408ad162012-06-06 16:45:18 -0700223 int optFlags = mir->optimizationFlags;
buzbee408ad162012-06-06 16:45:18 -0700224 uint32_t vB = mir->dalvikInsn.vB;
225 uint32_t vC = mir->dalvikInsn.vC;
buzbeee3acd072012-02-25 17:03:10 -0800226
Bill Buzbeea114add2012-05-03 15:00:40 -0700227 /* Prep Src and Dest locations */
228 int nextSreg = 0;
229 int nextLoc = 0;
230 int attrs = oatDataFlowAttributes[opcode];
231 rlSrc[0] = rlSrc[1] = rlSrc[2] = badLoc;
232 if (attrs & DF_UA) {
buzbeebff24652012-05-06 16:22:05 -0700233 if (attrs & DF_A_WIDE) {
buzbee15bf9802012-06-12 17:49:27 -0700234 rlSrc[nextLoc++] = oatGetSrcWide(cUnit, mir, nextSreg);
buzbeebff24652012-05-06 16:22:05 -0700235 nextSreg+= 2;
236 } else {
237 rlSrc[nextLoc++] = oatGetSrc(cUnit, mir, nextSreg);
238 nextSreg++;
239 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700240 }
241 if (attrs & DF_UB) {
buzbeebff24652012-05-06 16:22:05 -0700242 if (attrs & DF_B_WIDE) {
buzbee15bf9802012-06-12 17:49:27 -0700243 rlSrc[nextLoc++] = oatGetSrcWide(cUnit, mir, nextSreg);
buzbeebff24652012-05-06 16:22:05 -0700244 nextSreg+= 2;
245 } else {
246 rlSrc[nextLoc++] = oatGetSrc(cUnit, mir, nextSreg);
247 nextSreg++;
248 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700249 }
250 if (attrs & DF_UC) {
buzbeebff24652012-05-06 16:22:05 -0700251 if (attrs & DF_C_WIDE) {
buzbee15bf9802012-06-12 17:49:27 -0700252 rlSrc[nextLoc++] = oatGetSrcWide(cUnit, mir, nextSreg);
buzbeebff24652012-05-06 16:22:05 -0700253 } else {
254 rlSrc[nextLoc++] = oatGetSrc(cUnit, mir, nextSreg);
255 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700256 }
257 if (attrs & DF_DA) {
buzbeebff24652012-05-06 16:22:05 -0700258 if (attrs & DF_A_WIDE) {
buzbee15bf9802012-06-12 17:49:27 -0700259 rlDest = oatGetDestWide(cUnit, mir);
buzbeebff24652012-05-06 16:22:05 -0700260 } else {
buzbee15bf9802012-06-12 17:49:27 -0700261 rlDest = oatGetDest(cUnit, mir);
buzbeebff24652012-05-06 16:22:05 -0700262 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700263 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700264 switch (opcode) {
265 case Instruction::NOP:
266 break;
buzbeee3acd072012-02-25 17:03:10 -0800267
Ian Rogers474b6da2012-09-25 00:20:38 -0700268 case Instruction::MOVE_EXCEPTION:
269 genMoveException(cUnit, rlDest);
Bill Buzbeea114add2012-05-03 15:00:40 -0700270 break;
Bill Buzbeea114add2012-05-03 15:00:40 -0700271 case Instruction::RETURN_VOID:
TDYa1274f2935e2012-06-22 06:25:03 -0700272 if (!(cUnit->attrs & METHOD_IS_LEAF)) {
buzbee408ad162012-06-06 16:45:18 -0700273 genSuspendTest(cUnit, optFlags);
Bill Buzbeea114add2012-05-03 15:00:40 -0700274 }
275 break;
276
277 case Instruction::RETURN:
278 case Instruction::RETURN_OBJECT:
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 storeValue(cUnit, oatGetReturn(cUnit, cUnit->shorty[0] == 'F'), rlSrc[0]);
283 break;
284
285 case Instruction::RETURN_WIDE:
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 storeValueWide(cUnit, oatGetReturnWide(cUnit,
290 cUnit->shorty[0] == 'D'), rlSrc[0]);
291 break;
292
293 case Instruction::MOVE_RESULT_WIDE:
buzbee408ad162012-06-06 16:45:18 -0700294 if (optFlags & MIR_INLINED)
Bill Buzbeea114add2012-05-03 15:00:40 -0700295 break; // Nop - combined w/ previous invoke
296 storeValueWide(cUnit, rlDest, oatGetReturnWide(cUnit, rlDest.fp));
297 break;
298
299 case Instruction::MOVE_RESULT:
300 case Instruction::MOVE_RESULT_OBJECT:
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 storeValue(cUnit, rlDest, oatGetReturn(cUnit, rlDest.fp));
304 break;
305
306 case Instruction::MOVE:
307 case Instruction::MOVE_OBJECT:
308 case Instruction::MOVE_16:
309 case Instruction::MOVE_OBJECT_16:
310 case Instruction::MOVE_FROM16:
311 case Instruction::MOVE_OBJECT_FROM16:
312 storeValue(cUnit, rlDest, rlSrc[0]);
313 break;
314
315 case Instruction::MOVE_WIDE:
316 case Instruction::MOVE_WIDE_16:
317 case Instruction::MOVE_WIDE_FROM16:
318 storeValueWide(cUnit, rlDest, rlSrc[0]);
319 break;
320
321 case Instruction::CONST:
322 case Instruction::CONST_4:
323 case Instruction::CONST_16:
324 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
buzbee408ad162012-06-06 16:45:18 -0700325 loadConstantNoClobber(cUnit, rlResult.lowReg, vB);
Bill Buzbeea114add2012-05-03 15:00:40 -0700326 storeValue(cUnit, rlDest, rlResult);
327 break;
328
329 case Instruction::CONST_HIGH16:
330 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
buzbee408ad162012-06-06 16:45:18 -0700331 loadConstantNoClobber(cUnit, rlResult.lowReg, vB << 16);
Bill Buzbeea114add2012-05-03 15:00:40 -0700332 storeValue(cUnit, rlDest, rlResult);
333 break;
334
335 case Instruction::CONST_WIDE_16:
336 case Instruction::CONST_WIDE_32:
337 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
buzbee408ad162012-06-06 16:45:18 -0700338 loadConstantValueWide(cUnit, rlResult.lowReg, rlResult.highReg, vB,
339 (vB & 0x80000000) ? -1 : 0);
Bill Buzbeea114add2012-05-03 15:00:40 -0700340 storeValueWide(cUnit, rlDest, rlResult);
341 break;
342
343 case Instruction::CONST_WIDE:
344 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
345 loadConstantValueWide(cUnit, rlResult.lowReg, rlResult.highReg,
346 mir->dalvikInsn.vB_wide & 0xffffffff,
347 (mir->dalvikInsn.vB_wide >> 32) & 0xffffffff);
348 storeValueWide(cUnit, rlDest, rlResult);
349 break;
350
351 case Instruction::CONST_WIDE_HIGH16:
352 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
353 loadConstantValueWide(cUnit, rlResult.lowReg, rlResult.highReg,
buzbee408ad162012-06-06 16:45:18 -0700354 0, vB << 16);
Bill Buzbeea114add2012-05-03 15:00:40 -0700355 storeValueWide(cUnit, rlDest, rlResult);
356 break;
357
358 case Instruction::MONITOR_ENTER:
buzbee408ad162012-06-06 16:45:18 -0700359 genMonitorEnter(cUnit, optFlags, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700360 break;
361
362 case Instruction::MONITOR_EXIT:
buzbee408ad162012-06-06 16:45:18 -0700363 genMonitorExit(cUnit, optFlags, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700364 break;
365
366 case Instruction::CHECK_CAST:
buzbee408ad162012-06-06 16:45:18 -0700367 genCheckCast(cUnit, vB, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700368 break;
369
370 case Instruction::INSTANCE_OF:
buzbee408ad162012-06-06 16:45:18 -0700371 genInstanceof(cUnit, vC, rlDest, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700372 break;
373
374 case Instruction::NEW_INSTANCE:
buzbee408ad162012-06-06 16:45:18 -0700375 genNewInstance(cUnit, vB, rlDest);
Bill Buzbeea114add2012-05-03 15:00:40 -0700376 break;
377
378 case Instruction::THROW:
buzbee408ad162012-06-06 16:45:18 -0700379 genThrow(cUnit, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700380 break;
381
Bill Buzbeea114add2012-05-03 15:00:40 -0700382 case Instruction::ARRAY_LENGTH:
383 int lenOffset;
384 lenOffset = Array::LengthOffset().Int32Value();
385 rlSrc[0] = loadValue(cUnit, rlSrc[0], kCoreReg);
buzbee408ad162012-06-06 16:45:18 -0700386 genNullCheck(cUnit, rlSrc[0].sRegLow, rlSrc[0].lowReg, optFlags);
Bill Buzbeea114add2012-05-03 15:00:40 -0700387 rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
388 loadWordDisp(cUnit, rlSrc[0].lowReg, lenOffset, rlResult.lowReg);
389 storeValue(cUnit, rlDest, rlResult);
390 break;
391
392 case Instruction::CONST_STRING:
393 case Instruction::CONST_STRING_JUMBO:
buzbee6969d502012-06-15 16:40:31 -0700394 genConstString(cUnit, vB, rlDest);
Bill Buzbeea114add2012-05-03 15:00:40 -0700395 break;
396
397 case Instruction::CONST_CLASS:
buzbee6969d502012-06-15 16:40:31 -0700398 genConstClass(cUnit, vB, rlDest);
Bill Buzbeea114add2012-05-03 15:00:40 -0700399 break;
400
401 case Instruction::FILL_ARRAY_DATA:
buzbee408ad162012-06-06 16:45:18 -0700402 genFillArrayData(cUnit, vB, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700403 break;
404
405 case Instruction::FILLED_NEW_ARRAY:
buzbee6969d502012-06-15 16:40:31 -0700406 genFilledNewArray(cUnit, oatNewCallInfo(cUnit, bb, mir, kStatic,
buzbee3b3dbdd2012-06-13 13:39:34 -0700407 false /* not range */));
Bill Buzbeea114add2012-05-03 15:00:40 -0700408 break;
409
410 case Instruction::FILLED_NEW_ARRAY_RANGE:
buzbee6969d502012-06-15 16:40:31 -0700411 genFilledNewArray(cUnit, oatNewCallInfo(cUnit, bb, mir, kStatic,
buzbee3b3dbdd2012-06-13 13:39:34 -0700412 true /* range */));
Bill Buzbeea114add2012-05-03 15:00:40 -0700413 break;
414
415 case Instruction::NEW_ARRAY:
buzbee408ad162012-06-06 16:45:18 -0700416 genNewArray(cUnit, vC, rlDest, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700417 break;
418
419 case Instruction::GOTO:
420 case Instruction::GOTO_16:
421 case Instruction::GOTO_32:
422 if (bb->taken->startOffset <= mir->offset) {
buzbee408ad162012-06-06 16:45:18 -0700423 genSuspendTestAndBranch(cUnit, optFlags, &labelList[bb->taken->id]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700424 } else {
425 opUnconditionalBranch(cUnit, &labelList[bb->taken->id]);
426 }
427 break;
428
429 case Instruction::PACKED_SWITCH:
buzbee408ad162012-06-06 16:45:18 -0700430 genPackedSwitch(cUnit, vB, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700431 break;
432
433 case Instruction::SPARSE_SWITCH:
buzbeea1da8a52012-07-09 14:00:21 -0700434 genSparseSwitch(cUnit, vB, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700435 break;
436
437 case Instruction::CMPL_FLOAT:
438 case Instruction::CMPG_FLOAT:
439 case Instruction::CMPL_DOUBLE:
440 case Instruction::CMPG_DOUBLE:
buzbee408ad162012-06-06 16:45:18 -0700441 res = genCmpFP(cUnit, opcode, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700442 break;
443
444 case Instruction::CMP_LONG:
buzbee408ad162012-06-06 16:45:18 -0700445 genCmpLong(cUnit, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700446 break;
447
448 case Instruction::IF_EQ:
449 case Instruction::IF_NE:
450 case Instruction::IF_LT:
451 case Instruction::IF_GE:
452 case Instruction::IF_GT:
453 case Instruction::IF_LE: {
buzbee3b3dbdd2012-06-13 13:39:34 -0700454 LIR* taken = &labelList[bb->taken->id];
455 LIR* fallThrough = &labelList[bb->fallThrough->id];
Bill Buzbeea114add2012-05-03 15:00:40 -0700456 bool backwardBranch;
457 backwardBranch = (bb->taken->startOffset <= mir->offset);
458 if (backwardBranch) {
buzbee408ad162012-06-06 16:45:18 -0700459 genSuspendTest(cUnit, optFlags);
Bill Buzbeea114add2012-05-03 15:00:40 -0700460 }
buzbee3b3dbdd2012-06-13 13:39:34 -0700461 genCompareAndBranch(cUnit, opcode, rlSrc[0], rlSrc[1], taken,
462 fallThrough);
Bill Buzbeea114add2012-05-03 15:00:40 -0700463 break;
464 }
465
466 case Instruction::IF_EQZ:
467 case Instruction::IF_NEZ:
468 case Instruction::IF_LTZ:
469 case Instruction::IF_GEZ:
470 case Instruction::IF_GTZ:
471 case Instruction::IF_LEZ: {
buzbee3b3dbdd2012-06-13 13:39:34 -0700472 LIR* taken = &labelList[bb->taken->id];
473 LIR* fallThrough = &labelList[bb->fallThrough->id];
Bill Buzbeea114add2012-05-03 15:00:40 -0700474 bool backwardBranch;
475 backwardBranch = (bb->taken->startOffset <= mir->offset);
476 if (backwardBranch) {
buzbee408ad162012-06-06 16:45:18 -0700477 genSuspendTest(cUnit, optFlags);
Bill Buzbeea114add2012-05-03 15:00:40 -0700478 }
buzbee3b3dbdd2012-06-13 13:39:34 -0700479 genCompareZeroAndBranch(cUnit, opcode, rlSrc[0], taken, fallThrough);
Bill Buzbeea114add2012-05-03 15:00:40 -0700480 break;
481 }
482
483 case Instruction::AGET_WIDE:
buzbee408ad162012-06-06 16:45:18 -0700484 genArrayGet(cUnit, optFlags, kLong, rlSrc[0], rlSrc[1], rlDest, 3);
Bill Buzbeea114add2012-05-03 15:00:40 -0700485 break;
486 case Instruction::AGET:
487 case Instruction::AGET_OBJECT:
buzbee408ad162012-06-06 16:45:18 -0700488 genArrayGet(cUnit, optFlags, kWord, rlSrc[0], rlSrc[1], rlDest, 2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700489 break;
490 case Instruction::AGET_BOOLEAN:
buzbee408ad162012-06-06 16:45:18 -0700491 genArrayGet(cUnit, optFlags, kUnsignedByte, rlSrc[0], rlSrc[1], rlDest, 0);
Bill Buzbeea114add2012-05-03 15:00:40 -0700492 break;
493 case Instruction::AGET_BYTE:
buzbee408ad162012-06-06 16:45:18 -0700494 genArrayGet(cUnit, optFlags, kSignedByte, rlSrc[0], rlSrc[1], rlDest, 0);
Bill Buzbeea114add2012-05-03 15:00:40 -0700495 break;
496 case Instruction::AGET_CHAR:
buzbee408ad162012-06-06 16:45:18 -0700497 genArrayGet(cUnit, optFlags, kUnsignedHalf, rlSrc[0], rlSrc[1], rlDest, 1);
Bill Buzbeea114add2012-05-03 15:00:40 -0700498 break;
499 case Instruction::AGET_SHORT:
buzbee408ad162012-06-06 16:45:18 -0700500 genArrayGet(cUnit, optFlags, kSignedHalf, rlSrc[0], rlSrc[1], rlDest, 1);
Bill Buzbeea114add2012-05-03 15:00:40 -0700501 break;
502 case Instruction::APUT_WIDE:
buzbee408ad162012-06-06 16:45:18 -0700503 genArrayPut(cUnit, optFlags, kLong, rlSrc[1], rlSrc[2], rlSrc[0], 3);
Bill Buzbeea114add2012-05-03 15:00:40 -0700504 break;
505 case Instruction::APUT:
buzbee408ad162012-06-06 16:45:18 -0700506 genArrayPut(cUnit, optFlags, kWord, rlSrc[1], rlSrc[2], rlSrc[0], 2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700507 break;
508 case Instruction::APUT_OBJECT:
buzbee408ad162012-06-06 16:45:18 -0700509 genArrayObjPut(cUnit, optFlags, rlSrc[1], rlSrc[2], rlSrc[0], 2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700510 break;
511 case Instruction::APUT_SHORT:
512 case Instruction::APUT_CHAR:
buzbee408ad162012-06-06 16:45:18 -0700513 genArrayPut(cUnit, optFlags, kUnsignedHalf, rlSrc[1], rlSrc[2], rlSrc[0], 1);
Bill Buzbeea114add2012-05-03 15:00:40 -0700514 break;
515 case Instruction::APUT_BYTE:
516 case Instruction::APUT_BOOLEAN:
buzbee408ad162012-06-06 16:45:18 -0700517 genArrayPut(cUnit, optFlags, kUnsignedByte, rlSrc[1], rlSrc[2],
Bill Buzbeea114add2012-05-03 15:00:40 -0700518 rlSrc[0], 0);
519 break;
520
521 case Instruction::IGET_OBJECT:
522 //case Instruction::IGET_OBJECT_VOLATILE:
buzbee408ad162012-06-06 16:45:18 -0700523 genIGet(cUnit, vC, optFlags, kWord, rlDest, rlSrc[0], false, true);
Bill Buzbeea114add2012-05-03 15:00:40 -0700524 break;
525
526 case Instruction::IGET_WIDE:
527 //case Instruction::IGET_WIDE_VOLATILE:
buzbee408ad162012-06-06 16:45:18 -0700528 genIGet(cUnit, vC, optFlags, kLong, rlDest, rlSrc[0], true, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700529 break;
530
531 case Instruction::IGET:
532 //case Instruction::IGET_VOLATILE:
buzbee408ad162012-06-06 16:45:18 -0700533 genIGet(cUnit, vC, optFlags, kWord, rlDest, rlSrc[0], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700534 break;
535
536 case Instruction::IGET_CHAR:
buzbee408ad162012-06-06 16:45:18 -0700537 genIGet(cUnit, vC, optFlags, kUnsignedHalf, rlDest, rlSrc[0], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700538 break;
539
540 case Instruction::IGET_SHORT:
buzbee408ad162012-06-06 16:45:18 -0700541 genIGet(cUnit, vC, optFlags, kSignedHalf, rlDest, rlSrc[0], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700542 break;
543
544 case Instruction::IGET_BOOLEAN:
545 case Instruction::IGET_BYTE:
buzbee408ad162012-06-06 16:45:18 -0700546 genIGet(cUnit, vC, optFlags, kUnsignedByte, rlDest, rlSrc[0], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700547 break;
548
549 case Instruction::IPUT_WIDE:
550 //case Instruction::IPUT_WIDE_VOLATILE:
buzbee408ad162012-06-06 16:45:18 -0700551 genIPut(cUnit, vC, optFlags, kLong, rlSrc[0], rlSrc[1], true, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700552 break;
553
554 case Instruction::IPUT_OBJECT:
555 //case Instruction::IPUT_OBJECT_VOLATILE:
buzbee408ad162012-06-06 16:45:18 -0700556 genIPut(cUnit, vC, optFlags, kWord, rlSrc[0], rlSrc[1], false, true);
Bill Buzbeea114add2012-05-03 15:00:40 -0700557 break;
558
559 case Instruction::IPUT:
560 //case Instruction::IPUT_VOLATILE:
buzbee408ad162012-06-06 16:45:18 -0700561 genIPut(cUnit, vC, optFlags, kWord, rlSrc[0], rlSrc[1], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700562 break;
563
564 case Instruction::IPUT_BOOLEAN:
565 case Instruction::IPUT_BYTE:
buzbee408ad162012-06-06 16:45:18 -0700566 genIPut(cUnit, vC, optFlags, kUnsignedByte, rlSrc[0], rlSrc[1], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700567 break;
568
569 case Instruction::IPUT_CHAR:
buzbee408ad162012-06-06 16:45:18 -0700570 genIPut(cUnit, vC, optFlags, kUnsignedHalf, rlSrc[0], rlSrc[1], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700571 break;
572
573 case Instruction::IPUT_SHORT:
buzbee408ad162012-06-06 16:45:18 -0700574 genIPut(cUnit, vC, optFlags, kSignedHalf, rlSrc[0], rlSrc[1], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700575 break;
576
577 case Instruction::SGET_OBJECT:
buzbee408ad162012-06-06 16:45:18 -0700578 genSget(cUnit, vB, rlDest, false, true);
Bill Buzbeea114add2012-05-03 15:00:40 -0700579 break;
580 case Instruction::SGET:
581 case Instruction::SGET_BOOLEAN:
582 case Instruction::SGET_BYTE:
583 case Instruction::SGET_CHAR:
584 case Instruction::SGET_SHORT:
buzbee408ad162012-06-06 16:45:18 -0700585 genSget(cUnit, vB, rlDest, false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700586 break;
587
588 case Instruction::SGET_WIDE:
buzbee408ad162012-06-06 16:45:18 -0700589 genSget(cUnit, vB, rlDest, true, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700590 break;
591
592 case Instruction::SPUT_OBJECT:
buzbee408ad162012-06-06 16:45:18 -0700593 genSput(cUnit, vB, rlSrc[0], false, true);
Bill Buzbeea114add2012-05-03 15:00:40 -0700594 break;
595
596 case Instruction::SPUT:
597 case Instruction::SPUT_BOOLEAN:
598 case Instruction::SPUT_BYTE:
599 case Instruction::SPUT_CHAR:
600 case Instruction::SPUT_SHORT:
buzbee408ad162012-06-06 16:45:18 -0700601 genSput(cUnit, vB, rlSrc[0], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700602 break;
603
604 case Instruction::SPUT_WIDE:
buzbee408ad162012-06-06 16:45:18 -0700605 genSput(cUnit, vB, rlSrc[0], true, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700606 break;
607
608 case Instruction::INVOKE_STATIC_RANGE:
buzbee6969d502012-06-15 16:40:31 -0700609 genInvoke(cUnit, oatNewCallInfo(cUnit, bb, mir, kStatic, true));
Bill Buzbeea114add2012-05-03 15:00:40 -0700610 break;
611 case Instruction::INVOKE_STATIC:
buzbee6969d502012-06-15 16:40:31 -0700612 genInvoke(cUnit, oatNewCallInfo(cUnit, bb, mir, kStatic, false));
Bill Buzbeea114add2012-05-03 15:00:40 -0700613 break;
614
615 case Instruction::INVOKE_DIRECT:
buzbee6969d502012-06-15 16:40:31 -0700616 genInvoke(cUnit, oatNewCallInfo(cUnit, bb, mir, kDirect, false));
Bill Buzbeea114add2012-05-03 15:00:40 -0700617 break;
618 case Instruction::INVOKE_DIRECT_RANGE:
buzbee6969d502012-06-15 16:40:31 -0700619 genInvoke(cUnit, oatNewCallInfo(cUnit, bb, mir, kDirect, true));
Bill Buzbeea114add2012-05-03 15:00:40 -0700620 break;
621
622 case Instruction::INVOKE_VIRTUAL:
buzbee6969d502012-06-15 16:40:31 -0700623 genInvoke(cUnit, oatNewCallInfo(cUnit, bb, mir, kVirtual, false));
Bill Buzbeea114add2012-05-03 15:00:40 -0700624 break;
625 case Instruction::INVOKE_VIRTUAL_RANGE:
buzbee6969d502012-06-15 16:40:31 -0700626 genInvoke(cUnit, oatNewCallInfo(cUnit, bb, mir, kVirtual, true));
Bill Buzbeea114add2012-05-03 15:00:40 -0700627 break;
628
629 case Instruction::INVOKE_SUPER:
buzbee6969d502012-06-15 16:40:31 -0700630 genInvoke(cUnit, oatNewCallInfo(cUnit, bb, mir, kSuper, false));
Bill Buzbeea114add2012-05-03 15:00:40 -0700631 break;
632 case Instruction::INVOKE_SUPER_RANGE:
buzbee6969d502012-06-15 16:40:31 -0700633 genInvoke(cUnit, oatNewCallInfo(cUnit, bb, mir, kSuper, true));
Bill Buzbeea114add2012-05-03 15:00:40 -0700634 break;
635
636 case Instruction::INVOKE_INTERFACE:
buzbee6969d502012-06-15 16:40:31 -0700637 genInvoke(cUnit, oatNewCallInfo(cUnit, bb, mir, kInterface, false));
Bill Buzbeea114add2012-05-03 15:00:40 -0700638 break;
639 case Instruction::INVOKE_INTERFACE_RANGE:
buzbee6969d502012-06-15 16:40:31 -0700640 genInvoke(cUnit, oatNewCallInfo(cUnit, bb, mir, kInterface, true));
Bill Buzbeea114add2012-05-03 15:00:40 -0700641 break;
642
643 case Instruction::NEG_INT:
644 case Instruction::NOT_INT:
buzbee408ad162012-06-06 16:45:18 -0700645 res = genArithOpInt(cUnit, opcode, rlDest, rlSrc[0], rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700646 break;
647
648 case Instruction::NEG_LONG:
649 case Instruction::NOT_LONG:
buzbee408ad162012-06-06 16:45:18 -0700650 res = genArithOpLong(cUnit, opcode, rlDest, rlSrc[0], rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700651 break;
652
653 case Instruction::NEG_FLOAT:
buzbee408ad162012-06-06 16:45:18 -0700654 res = genArithOpFloat(cUnit, opcode, rlDest, rlSrc[0], rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700655 break;
656
657 case Instruction::NEG_DOUBLE:
buzbee408ad162012-06-06 16:45:18 -0700658 res = genArithOpDouble(cUnit, opcode, rlDest, rlSrc[0], rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700659 break;
660
661 case Instruction::INT_TO_LONG:
buzbee408ad162012-06-06 16:45:18 -0700662 genIntToLong(cUnit, rlDest, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700663 break;
664
665 case Instruction::LONG_TO_INT:
666 rlSrc[0] = oatUpdateLocWide(cUnit, rlSrc[0]);
667 rlSrc[0] = oatWideToNarrow(cUnit, rlSrc[0]);
668 storeValue(cUnit, rlDest, rlSrc[0]);
669 break;
670
671 case Instruction::INT_TO_BYTE:
672 case Instruction::INT_TO_SHORT:
673 case Instruction::INT_TO_CHAR:
buzbee408ad162012-06-06 16:45:18 -0700674 genIntNarrowing(cUnit, opcode, rlDest, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700675 break;
676
677 case Instruction::INT_TO_FLOAT:
678 case Instruction::INT_TO_DOUBLE:
679 case Instruction::LONG_TO_FLOAT:
680 case Instruction::LONG_TO_DOUBLE:
681 case Instruction::FLOAT_TO_INT:
682 case Instruction::FLOAT_TO_LONG:
683 case Instruction::FLOAT_TO_DOUBLE:
684 case Instruction::DOUBLE_TO_INT:
685 case Instruction::DOUBLE_TO_LONG:
686 case Instruction::DOUBLE_TO_FLOAT:
buzbee408ad162012-06-06 16:45:18 -0700687 genConversion(cUnit, opcode, rlDest, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700688 break;
689
690 case Instruction::ADD_INT:
691 case Instruction::SUB_INT:
692 case Instruction::MUL_INT:
693 case Instruction::DIV_INT:
694 case Instruction::REM_INT:
695 case Instruction::AND_INT:
696 case Instruction::OR_INT:
697 case Instruction::XOR_INT:
698 case Instruction::SHL_INT:
699 case Instruction::SHR_INT:
700 case Instruction::USHR_INT:
701 case Instruction::ADD_INT_2ADDR:
702 case Instruction::SUB_INT_2ADDR:
703 case Instruction::MUL_INT_2ADDR:
704 case Instruction::DIV_INT_2ADDR:
705 case Instruction::REM_INT_2ADDR:
706 case Instruction::AND_INT_2ADDR:
707 case Instruction::OR_INT_2ADDR:
708 case Instruction::XOR_INT_2ADDR:
709 case Instruction::SHL_INT_2ADDR:
710 case Instruction::SHR_INT_2ADDR:
711 case Instruction::USHR_INT_2ADDR:
buzbee408ad162012-06-06 16:45:18 -0700712 genArithOpInt(cUnit, opcode, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700713 break;
714
715 case Instruction::ADD_LONG:
716 case Instruction::SUB_LONG:
717 case Instruction::MUL_LONG:
718 case Instruction::DIV_LONG:
719 case Instruction::REM_LONG:
720 case Instruction::AND_LONG:
721 case Instruction::OR_LONG:
722 case Instruction::XOR_LONG:
723 case Instruction::ADD_LONG_2ADDR:
724 case Instruction::SUB_LONG_2ADDR:
725 case Instruction::MUL_LONG_2ADDR:
726 case Instruction::DIV_LONG_2ADDR:
727 case Instruction::REM_LONG_2ADDR:
728 case Instruction::AND_LONG_2ADDR:
729 case Instruction::OR_LONG_2ADDR:
730 case Instruction::XOR_LONG_2ADDR:
buzbee408ad162012-06-06 16:45:18 -0700731 genArithOpLong(cUnit, opcode, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700732 break;
733
734 case Instruction::SHL_LONG:
735 case Instruction::SHR_LONG:
736 case Instruction::USHR_LONG:
737 case Instruction::SHL_LONG_2ADDR:
738 case Instruction::SHR_LONG_2ADDR:
739 case Instruction::USHR_LONG_2ADDR:
buzbee408ad162012-06-06 16:45:18 -0700740 genShiftOpLong(cUnit, opcode, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700741 break;
742
743 case Instruction::ADD_FLOAT:
744 case Instruction::SUB_FLOAT:
745 case Instruction::MUL_FLOAT:
746 case Instruction::DIV_FLOAT:
747 case Instruction::REM_FLOAT:
748 case Instruction::ADD_FLOAT_2ADDR:
749 case Instruction::SUB_FLOAT_2ADDR:
750 case Instruction::MUL_FLOAT_2ADDR:
751 case Instruction::DIV_FLOAT_2ADDR:
752 case Instruction::REM_FLOAT_2ADDR:
buzbee408ad162012-06-06 16:45:18 -0700753 genArithOpFloat(cUnit, opcode, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700754 break;
755
756 case Instruction::ADD_DOUBLE:
757 case Instruction::SUB_DOUBLE:
758 case Instruction::MUL_DOUBLE:
759 case Instruction::DIV_DOUBLE:
760 case Instruction::REM_DOUBLE:
761 case Instruction::ADD_DOUBLE_2ADDR:
762 case Instruction::SUB_DOUBLE_2ADDR:
763 case Instruction::MUL_DOUBLE_2ADDR:
764 case Instruction::DIV_DOUBLE_2ADDR:
765 case Instruction::REM_DOUBLE_2ADDR:
buzbee408ad162012-06-06 16:45:18 -0700766 genArithOpDouble(cUnit, opcode, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700767 break;
768
769 case Instruction::RSUB_INT:
770 case Instruction::ADD_INT_LIT16:
771 case Instruction::MUL_INT_LIT16:
772 case Instruction::DIV_INT_LIT16:
773 case Instruction::REM_INT_LIT16:
774 case Instruction::AND_INT_LIT16:
775 case Instruction::OR_INT_LIT16:
776 case Instruction::XOR_INT_LIT16:
777 case Instruction::ADD_INT_LIT8:
778 case Instruction::RSUB_INT_LIT8:
779 case Instruction::MUL_INT_LIT8:
780 case Instruction::DIV_INT_LIT8:
781 case Instruction::REM_INT_LIT8:
782 case Instruction::AND_INT_LIT8:
783 case Instruction::OR_INT_LIT8:
784 case Instruction::XOR_INT_LIT8:
785 case Instruction::SHL_INT_LIT8:
786 case Instruction::SHR_INT_LIT8:
787 case Instruction::USHR_INT_LIT8:
buzbee408ad162012-06-06 16:45:18 -0700788 genArithOpIntLit(cUnit, opcode, rlDest, rlSrc[0], vC);
Bill Buzbeea114add2012-05-03 15:00:40 -0700789 break;
790
791 default:
792 res = true;
793 }
794 return res;
buzbeee3acd072012-02-25 17:03:10 -0800795}
796
buzbee31a4a6f2012-02-28 15:36:15 -0800797const char* extendedMIROpNames[kMirOpLast - kMirOpFirst] = {
Bill Buzbeea114add2012-05-03 15:00:40 -0700798 "kMirOpPhi",
799 "kMirOpCopy",
800 "kMirFusedCmplFloat",
801 "kMirFusedCmpgFloat",
802 "kMirFusedCmplDouble",
803 "kMirFusedCmpgDouble",
804 "kMirFusedCmpLong",
805 "kMirNop",
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700806 "kMirOpNullCheck",
807 "kMirOpRangeCheck",
808 "kMirOpDivZeroCheck",
809 "kMirOpCheck",
buzbeee3acd072012-02-25 17:03:10 -0800810};
811
812/* Extended MIR instructions like PHI */
buzbee84fd6932012-03-29 16:44:16 -0700813void handleExtendedMethodMIR(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir)
buzbeee3acd072012-02-25 17:03:10 -0800814{
Bill Buzbeea114add2012-05-03 15:00:40 -0700815 int opOffset = mir->dalvikInsn.opcode - kMirOpFirst;
816 char* msg = NULL;
817 if (cUnit->printMe) {
818 msg = (char*)oatNew(cUnit, strlen(extendedMIROpNames[opOffset]) + 1,
819 false, kAllocDebugInfo);
820 strcpy(msg, extendedMIROpNames[opOffset]);
821 }
822 LIR* op = newLIR1(cUnit, kPseudoExtended, (int) msg);
buzbeee3acd072012-02-25 17:03:10 -0800823
Bill Buzbeea114add2012-05-03 15:00:40 -0700824 switch ((ExtendedMIROpcode)mir->dalvikInsn.opcode) {
825 case kMirOpPhi: {
826 char* ssaString = NULL;
827 if (cUnit->printMe) {
828 ssaString = oatGetSSAString(cUnit, mir->ssaRep);
829 }
830 op->flags.isNop = true;
831 newLIR1(cUnit, kPseudoSSARep, (int) ssaString);
832 break;
buzbeee3acd072012-02-25 17:03:10 -0800833 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700834 case kMirOpCopy: {
835 RegLocation rlSrc = oatGetSrc(cUnit, mir, 0);
buzbee15bf9802012-06-12 17:49:27 -0700836 RegLocation rlDest = oatGetDest(cUnit, mir);
Bill Buzbeea114add2012-05-03 15:00:40 -0700837 storeValue(cUnit, rlDest, rlSrc);
838 break;
839 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700840 case kMirOpFusedCmplFloat:
841 genFusedFPCmpBranch(cUnit, bb, mir, false /*gt bias*/, false /*double*/);
842 break;
843 case kMirOpFusedCmpgFloat:
844 genFusedFPCmpBranch(cUnit, bb, mir, true /*gt bias*/, false /*double*/);
845 break;
846 case kMirOpFusedCmplDouble:
847 genFusedFPCmpBranch(cUnit, bb, mir, false /*gt bias*/, true /*double*/);
848 break;
849 case kMirOpFusedCmpgDouble:
850 genFusedFPCmpBranch(cUnit, bb, mir, true /*gt bias*/, true /*double*/);
851 break;
852 case kMirOpFusedCmpLong:
853 genFusedLongCmpBranch(cUnit, bb, mir);
854 break;
Bill Buzbeea114add2012-05-03 15:00:40 -0700855 default:
856 break;
857 }
buzbeee3acd072012-02-25 17:03:10 -0800858}
859
860/* Handle the content in each basic block */
buzbee31a4a6f2012-02-28 15:36:15 -0800861bool methodBlockCodeGen(CompilationUnit* cUnit, BasicBlock* bb)
buzbeee3acd072012-02-25 17:03:10 -0800862{
buzbee488a78c2012-09-10 15:55:34 -0700863 if (bb->blockType == kDead) return false;
buzbee8320f382012-09-11 16:29:42 -0700864 cUnit->currentDalvikOffset = bb->startOffset;
Bill Buzbeea114add2012-05-03 15:00:40 -0700865 MIR* mir;
buzbeea1da8a52012-07-09 14:00:21 -0700866 LIR* labelList = cUnit->blockLabelList;
Bill Buzbeea114add2012-05-03 15:00:40 -0700867 int blockId = bb->id;
buzbeee3acd072012-02-25 17:03:10 -0800868
Bill Buzbeea114add2012-05-03 15:00:40 -0700869 cUnit->curBlock = bb;
870 labelList[blockId].operands[0] = bb->startOffset;
buzbeee3acd072012-02-25 17:03:10 -0800871
Bill Buzbeea114add2012-05-03 15:00:40 -0700872 /* Insert the block label */
873 labelList[blockId].opcode = kPseudoNormalBlockLabel;
874 oatAppendLIR(cUnit, (LIR*) &labelList[blockId]);
buzbeee3acd072012-02-25 17:03:10 -0800875
buzbee8320f382012-09-11 16:29:42 -0700876 LIR* headLIR = NULL;
877
Bill Buzbeea5b30242012-09-28 07:19:44 -0700878 /* If this is a catch block, export the start address */
buzbee8320f382012-09-11 16:29:42 -0700879 if (bb->catchEntry) {
Bill Buzbeea5b30242012-09-28 07:19:44 -0700880 headLIR = newLIR0(cUnit, kPseudoExportedPC);
buzbee8320f382012-09-11 16:29:42 -0700881 }
882
Bill Buzbeea114add2012-05-03 15:00:40 -0700883 /* Free temp registers and reset redundant store tracking */
884 oatResetRegPool(cUnit);
885 oatResetDefTracking(cUnit);
886
buzbeed1643e42012-09-05 14:06:51 -0700887 oatClobberAllRegs(cUnit);
Bill Buzbeea114add2012-05-03 15:00:40 -0700888
Bill Buzbeea114add2012-05-03 15:00:40 -0700889
890 if (bb->blockType == kEntryBlock) {
buzbeead8f15e2012-06-18 14:49:45 -0700891 int startVReg = cUnit->numDalvikRegisters - cUnit->numIns;
892 genEntrySequence(cUnit, &cUnit->regLocation[startVReg],
893 cUnit->regLocation[cUnit->methodSReg]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700894 } else if (bb->blockType == kExitBlock) {
buzbee2cfc6392012-05-07 14:51:40 -0700895 genExitSequence(cUnit);
Bill Buzbeea114add2012-05-03 15:00:40 -0700896 }
897
898 for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
buzbeee3acd072012-02-25 17:03:10 -0800899 oatResetRegPool(cUnit);
Bill Buzbeea114add2012-05-03 15:00:40 -0700900 if (cUnit->disableOpt & (1 << kTrackLiveTemps)) {
901 oatClobberAllRegs(cUnit);
buzbeee1965672012-03-11 18:39:19 -0700902 }
903
Bill Buzbeea114add2012-05-03 15:00:40 -0700904 if (cUnit->disableOpt & (1 << kSuppressLoads)) {
905 oatResetDefTracking(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800906 }
907
buzbee3d661942012-03-14 17:37:27 -0700908#ifndef NDEBUG
Bill Buzbeea114add2012-05-03 15:00:40 -0700909 /* Reset temp tracking sanity check */
910 cUnit->liveSReg = INVALID_SREG;
buzbee3d661942012-03-14 17:37:27 -0700911#endif
912
Bill Buzbeea114add2012-05-03 15:00:40 -0700913 cUnit->currentDalvikOffset = mir->offset;
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700914 int opcode = mir->dalvikInsn.opcode;
Bill Buzbeea114add2012-05-03 15:00:40 -0700915 LIR* boundaryLIR;
buzbeee3acd072012-02-25 17:03:10 -0800916
Bill Buzbeea114add2012-05-03 15:00:40 -0700917 /* Mark the beginning of a Dalvik instruction for line tracking */
918 char* instStr = cUnit->printMe ?
919 oatGetDalvikDisassembly(cUnit, mir->dalvikInsn, "") : NULL;
buzbeed1643e42012-09-05 14:06:51 -0700920 boundaryLIR = markBoundary(cUnit, mir->offset, instStr);
Bill Buzbeea114add2012-05-03 15:00:40 -0700921 /* Remember the first LIR for this block */
922 if (headLIR == NULL) {
923 headLIR = boundaryLIR;
924 /* Set the first boundaryLIR as a scheduling barrier */
925 headLIR->defMask = ENCODE_ALL;
buzbeee3acd072012-02-25 17:03:10 -0800926 }
927
Bill Buzbeea114add2012-05-03 15:00:40 -0700928 /* Don't generate the SSA annotation unless verbose mode is on */
929 if (cUnit->printMe && mir->ssaRep) {
930 char* ssaString = oatGetSSAString(cUnit, mir->ssaRep);
931 newLIR1(cUnit, kPseudoSSARep, (int) ssaString);
932 }
933
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700934 if (opcode == kMirOpCheck) {
935 // Combine check and work halves of throwing instruction.
936 MIR* workHalf = mir->meta.throwInsn;
937 mir->dalvikInsn.opcode = workHalf->dalvikInsn.opcode;
938 opcode = workHalf->dalvikInsn.opcode;
939 SSARepresentation* ssaRep = workHalf->ssaRep;
940 workHalf->ssaRep = mir->ssaRep;
941 mir->ssaRep = ssaRep;
942 workHalf->dalvikInsn.opcode = static_cast<Instruction::Code>(kMirOpNop);
943 }
944
945 if (opcode >= kMirOpFirst) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700946 handleExtendedMethodMIR(cUnit, bb, mir);
947 continue;
948 }
949
950 bool notHandled = compileDalvikInstruction(cUnit, mir, bb, labelList);
951 if (notHandled) {
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700952 LOG(FATAL) << StringPrintf("%#06x: Opcode %#x (%s)",
953 mir->offset, opcode,
954 Instruction::Name(mir->dalvikInsn.opcode));
Bill Buzbeea114add2012-05-03 15:00:40 -0700955 }
956 }
957
958 if (headLIR) {
959 /*
960 * Eliminate redundant loads/stores and delay stores into later
961 * slots
962 */
963 oatApplyLocalOptimizations(cUnit, (LIR*) headLIR, cUnit->lastLIRInsn);
964
965 /*
966 * Generate an unconditional branch to the fallthrough block.
967 */
968 if (bb->fallThrough) {
969 opUnconditionalBranch(cUnit, &labelList[bb->fallThrough->id]);
970 }
971 }
972 return false;
buzbeee3acd072012-02-25 17:03:10 -0800973}
974
buzbee16da88c2012-03-20 10:38:17 -0700975/* Set basic block labels */
976bool labelBlocks(CompilationUnit* cUnit, BasicBlock* bb)
977{
buzbeea1da8a52012-07-09 14:00:21 -0700978 LIR* labelList = cUnit->blockLabelList;
Bill Buzbeea114add2012-05-03 15:00:40 -0700979 int blockId = bb->id;
buzbee16da88c2012-03-20 10:38:17 -0700980
Bill Buzbeea114add2012-05-03 15:00:40 -0700981 cUnit->curBlock = bb;
982 labelList[blockId].operands[0] = bb->startOffset;
buzbee16da88c2012-03-20 10:38:17 -0700983
Bill Buzbeea114add2012-05-03 15:00:40 -0700984 /* Insert the block label */
985 labelList[blockId].opcode = kPseudoNormalBlockLabel;
986 return false;
buzbee16da88c2012-03-20 10:38:17 -0700987}
988
989void oatSpecialMIR2LIR(CompilationUnit* cUnit, SpecialCaseHandler specialCase)
990{
Bill Buzbeea114add2012-05-03 15:00:40 -0700991 /* Find the first DalvikByteCode block */
992 int numReachableBlocks = cUnit->numReachableBlocks;
993 const GrowableList *blockList = &cUnit->blockList;
994 BasicBlock*bb = NULL;
995 for (int idx = 0; idx < numReachableBlocks; idx++) {
996 int dfsIndex = cUnit->dfsOrder.elemList[idx];
997 bb = (BasicBlock*)oatGrowableListGetElement(blockList, dfsIndex);
998 if (bb->blockType == kDalvikByteCode) {
999 break;
buzbee16da88c2012-03-20 10:38:17 -07001000 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001001 }
1002 if (bb == NULL) {
1003 return;
1004 }
1005 DCHECK_EQ(bb->startOffset, 0);
Elliott Hughes74847412012-06-20 18:10:21 -07001006 DCHECK(bb->firstMIRInsn != NULL);
buzbee16da88c2012-03-20 10:38:17 -07001007
Bill Buzbeea114add2012-05-03 15:00:40 -07001008 /* Get the first instruction */
1009 MIR* mir = bb->firstMIRInsn;
buzbee16da88c2012-03-20 10:38:17 -07001010
Bill Buzbeea114add2012-05-03 15:00:40 -07001011 /* Free temp registers and reset redundant store tracking */
1012 oatResetRegPool(cUnit);
1013 oatResetDefTracking(cUnit);
1014 oatClobberAllRegs(cUnit);
buzbee16da88c2012-03-20 10:38:17 -07001015
Bill Buzbeea114add2012-05-03 15:00:40 -07001016 genSpecialCase(cUnit, bb, mir, specialCase);
buzbee16da88c2012-03-20 10:38:17 -07001017}
1018
buzbeee3acd072012-02-25 17:03:10 -08001019void oatMethodMIR2LIR(CompilationUnit* cUnit)
1020{
Bill Buzbeea114add2012-05-03 15:00:40 -07001021 /* Used to hold the labels of each block */
1022 cUnit->blockLabelList =
buzbeea1da8a52012-07-09 14:00:21 -07001023 (LIR*) oatNew(cUnit, sizeof(LIR) * cUnit->numBlocks, true, kAllocLIR);
buzbeee3acd072012-02-25 17:03:10 -08001024
Bill Buzbeea114add2012-05-03 15:00:40 -07001025 oatDataFlowAnalysisDispatcher(cUnit, methodBlockCodeGen,
1026 kPreOrderDFSTraversal, false /* Iterative */);
Ian Rogersab2b55d2012-03-18 00:06:11 -07001027
Bill Buzbeea114add2012-05-03 15:00:40 -07001028 handleSuspendLaunchpads(cUnit);
buzbeee3acd072012-02-25 17:03:10 -08001029
Bill Buzbeea114add2012-05-03 15:00:40 -07001030 handleThrowLaunchpads(cUnit);
buzbeee3acd072012-02-25 17:03:10 -08001031
Bill Buzbeea114add2012-05-03 15:00:40 -07001032 handleIntrinsicLaunchpads(cUnit);
buzbeefc9e6fa2012-03-23 15:14:29 -07001033
Bill Buzbeea114add2012-05-03 15:00:40 -07001034 if (!(cUnit->disableOpt & (1 << kSafeOptimizations))) {
1035 removeRedundantBranches(cUnit);
1036 }
buzbeee3acd072012-02-25 17:03:10 -08001037}
1038
buzbeee3acd072012-02-25 17:03:10 -08001039} // namespace art