blob: 3321c33cf6ac6615c44676e1f798b7d97f548ddd [file] [log] [blame]
buzbeee3acd072012-02-25 17:03:10 -08001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "object_utils.h"
18
19namespace art {
20
21#define DISPLAY_MISSING_TARGETS (cUnit->enableDebug & \
Bill Buzbeea114add2012-05-03 15:00:40 -070022 (1 << kDebugDisplayMissingTargets))
buzbeee3acd072012-02-25 17:03:10 -080023
buzbee2cfc6392012-05-07 14:51:40 -070024const RegLocation badLoc = {kLocDalvikFrame, 0, 0, 0, 0, 0, 0, 0, 0,
25 INVALID_REG, INVALID_REG, INVALID_SREG,
26 INVALID_SREG};
buzbeee3acd072012-02-25 17:03:10 -080027
28/* Mark register usage state and return long retloc */
Ian Rogersf7d9ad32012-03-13 18:45:39 -070029RegLocation oatGetReturnWide(CompilationUnit* cUnit, bool isDouble)
buzbeee3acd072012-02-25 17:03:10 -080030{
Bill Buzbeea114add2012-05-03 15:00:40 -070031 RegLocation gpr_res = LOC_C_RETURN_WIDE;
32 RegLocation fpr_res = LOC_C_RETURN_WIDE_DOUBLE;
33 RegLocation res = isDouble ? fpr_res : gpr_res;
34 oatClobber(cUnit, res.lowReg);
35 oatClobber(cUnit, res.highReg);
36 oatLockTemp(cUnit, res.lowReg);
37 oatLockTemp(cUnit, res.highReg);
38 oatMarkPair(cUnit, res.lowReg, res.highReg);
39 return res;
buzbeee3acd072012-02-25 17:03:10 -080040}
41
Ian Rogersf7d9ad32012-03-13 18:45:39 -070042RegLocation oatGetReturn(CompilationUnit* cUnit, bool isFloat)
buzbeee3acd072012-02-25 17:03:10 -080043{
Ian Rogersf7d9ad32012-03-13 18:45:39 -070044 RegLocation gpr_res = LOC_C_RETURN;
45 RegLocation fpr_res = LOC_C_RETURN_FLOAT;
46 RegLocation res = isFloat ? fpr_res : gpr_res;
Bill Buzbeea114add2012-05-03 15:00:40 -070047 oatClobber(cUnit, res.lowReg);
48 if (cUnit->instructionSet == kMips) {
49 oatMarkInUse(cUnit, res.lowReg);
50 } else {
51 oatLockTemp(cUnit, res.lowReg);
52 }
53 return res;
buzbeee3acd072012-02-25 17:03:10 -080054}
55
buzbee3b3dbdd2012-06-13 13:39:34 -070056void genInvoke(CompilationUnit* cUnit, CallInfo* info)
buzbeee3acd072012-02-25 17:03:10 -080057{
buzbee15bf9802012-06-12 17:49:27 -070058 if (genIntrinsic(cUnit, info)) {
Bill Buzbeea114add2012-05-03 15:00:40 -070059 return;
60 }
buzbee15bf9802012-06-12 17:49:27 -070061 InvokeType originalType = info->type; // avoiding mutation by ComputeInvokeInfo
Bill Buzbeea114add2012-05-03 15:00:40 -070062 int callState = 0;
63 LIR* nullCk;
64 LIR** pNullCk = NULL;
65 NextCallInsn nextCallInsn;
66 oatFlushAllRegs(cUnit); /* Everything to home location */
67 // Explicit register usage
68 oatLockCallTemps(cUnit);
buzbeee3acd072012-02-25 17:03:10 -080069
Bill Buzbeea114add2012-05-03 15:00:40 -070070 OatCompilationUnit mUnit(cUnit->class_loader, cUnit->class_linker,
Ian Rogers00f7d0e2012-07-19 15:28:27 -070071 *cUnit->dex_file,
Bill Buzbeea114add2012-05-03 15:00:40 -070072 cUnit->code_item, cUnit->method_idx,
73 cUnit->access_flags);
Logan Chien4dd96f52012-02-29 01:26:58 +080074
buzbee3b3dbdd2012-06-13 13:39:34 -070075 uint32_t dexMethodIdx = info->index;
Bill Buzbeea114add2012-05-03 15:00:40 -070076 int vtableIdx;
77 uintptr_t directCode;
78 uintptr_t directMethod;
79 bool skipThis;
80 bool fastPath =
buzbee15bf9802012-06-12 17:49:27 -070081 cUnit->compiler->ComputeInvokeInfo(dexMethodIdx, &mUnit, info->type,
Bill Buzbeea114add2012-05-03 15:00:40 -070082 vtableIdx, directCode,
83 directMethod)
84 && !SLOW_INVOKE_PATH;
buzbee15bf9802012-06-12 17:49:27 -070085 if (info->type == kInterface) {
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 }
127 if (DISPLAY_MISSING_TARGETS) {
128 genShowTarget(cUnit);
129 }
buzbee8320f382012-09-11 16:29:42 -0700130 LIR* callInst;
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700131#if !defined(TARGET_X86)
buzbee8320f382012-09-11 16:29:42 -0700132 callInst = opReg(cUnit, kOpBlx, rINVOKE_TGT);
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700133#else
buzbee15bf9802012-06-12 17:49:27 -0700134 if (fastPath && info->type != kInterface) {
Mathieu Chartier66f19252012-09-18 08:57:04 -0700135 callInst = opMem(cUnit, kOpBlx, rARG0, AbstractMethod::GetCodeOffset().Int32Value());
Bill Buzbeea114add2012-05-03 15:00:40 -0700136 } else {
137 int trampoline = 0;
buzbee15bf9802012-06-12 17:49:27 -0700138 switch (info->type) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700139 case kInterface:
140 trampoline = fastPath ? ENTRYPOINT_OFFSET(pInvokeInterfaceTrampoline)
141 : ENTRYPOINT_OFFSET(pInvokeInterfaceTrampolineWithAccessCheck);
142 break;
143 case kDirect:
144 trampoline = ENTRYPOINT_OFFSET(pInvokeDirectTrampolineWithAccessCheck);
145 break;
146 case kStatic:
147 trampoline = ENTRYPOINT_OFFSET(pInvokeStaticTrampolineWithAccessCheck);
148 break;
149 case kSuper:
150 trampoline = ENTRYPOINT_OFFSET(pInvokeSuperTrampolineWithAccessCheck);
151 break;
152 case kVirtual:
153 trampoline = ENTRYPOINT_OFFSET(pInvokeVirtualTrampolineWithAccessCheck);
154 break;
155 default:
156 LOG(FATAL) << "Unexpected invoke type";
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700157 }
buzbee8320f382012-09-11 16:29:42 -0700158 callInst = opThreadMem(cUnit, kOpBlx, trampoline);
Bill Buzbeea114add2012-05-03 15:00:40 -0700159 }
buzbeea7678db2012-03-05 15:35:46 -0800160#endif
buzbee8320f382012-09-11 16:29:42 -0700161 markSafepointPC(cUnit, callInst);
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700162
Bill Buzbeea114add2012-05-03 15:00:40 -0700163 oatClobberCalleeSave(cUnit);
buzbee15bf9802012-06-12 17:49:27 -0700164 if (info->result.location != kLocInvalid) {
165 // We have a following MOVE_RESULT - do it now.
166 if (info->result.wide) {
buzbee52ed7762012-06-13 23:43:14 -0700167 RegLocation retLoc = oatGetReturnWide(cUnit, info->result.fp);
buzbee15bf9802012-06-12 17:49:27 -0700168 storeValueWide(cUnit, info->result, retLoc);
169 } else {
buzbee52ed7762012-06-13 23:43:14 -0700170 RegLocation retLoc = oatGetReturn(cUnit, info->result.fp);
buzbee15bf9802012-06-12 17:49:27 -0700171 storeValue(cUnit, info->result, retLoc);
172 }
173 }
174}
175
176/*
177 * Build an array of location records for the incoming arguments.
178 * Note: one location record per word of arguments, with dummy
179 * high-word loc for wide arguments. Also pull up any following
180 * MOVE_RESULT and incorporate it into the invoke.
181 */
buzbee6969d502012-06-15 16:40:31 -0700182CallInfo* oatNewCallInfo(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir,
183 InvokeType type, bool isRange)
buzbee15bf9802012-06-12 17:49:27 -0700184{
buzbee3b3dbdd2012-06-13 13:39:34 -0700185 CallInfo* info = (CallInfo*)oatNew(cUnit, sizeof(CallInfo), true,
buzbee15bf9802012-06-12 17:49:27 -0700186 kAllocMisc);
187 MIR* moveResultMIR = oatFindMoveResult(cUnit, bb, mir);
188 if (moveResultMIR == NULL) {
189 info->result.location = kLocInvalid;
190 } else {
191 info->result = oatGetRawDest(cUnit, moveResultMIR);
192 moveResultMIR->dalvikInsn.opcode = Instruction::NOP;
193 }
194 info->numArgWords = mir->ssaRep->numUses;
195 info->args = (info->numArgWords == 0) ? NULL : (RegLocation*)
196 oatNew(cUnit, sizeof(RegLocation) * info->numArgWords, false, kAllocMisc);
197 for (int i = 0; i < info->numArgWords; i++) {
198 info->args[i] = oatGetRawSrc(cUnit, mir, i);
199 }
200 info->optFlags = mir->optimizationFlags;
201 info->type = type;
202 info->isRange = isRange;
buzbee3b3dbdd2012-06-13 13:39:34 -0700203 info->index = mir->dalvikInsn.vB;
buzbee15bf9802012-06-12 17:49:27 -0700204 info->offset = mir->offset;
205 return info;
buzbeee3acd072012-02-25 17:03:10 -0800206}
207
208/*
209 * Target-independent code generation. Use only high-level
210 * load/store utilities here, or target-dependent genXX() handlers
211 * when necessary.
212 */
buzbee31a4a6f2012-02-28 15:36:15 -0800213bool compileDalvikInstruction(CompilationUnit* cUnit, MIR* mir,
214 BasicBlock* bb, LIR* labelList)
buzbeee3acd072012-02-25 17:03:10 -0800215{
Bill Buzbeea114add2012-05-03 15:00:40 -0700216 bool res = false; // Assume success
217 RegLocation rlSrc[3];
218 RegLocation rlDest = badLoc;
219 RegLocation rlResult = badLoc;
220 Instruction::Code opcode = mir->dalvikInsn.opcode;
buzbee408ad162012-06-06 16:45:18 -0700221 int optFlags = mir->optimizationFlags;
buzbee408ad162012-06-06 16:45:18 -0700222 uint32_t vB = mir->dalvikInsn.vB;
223 uint32_t vC = mir->dalvikInsn.vC;
buzbeee3acd072012-02-25 17:03:10 -0800224
Bill Buzbeea114add2012-05-03 15:00:40 -0700225 /* Prep Src and Dest locations */
226 int nextSreg = 0;
227 int nextLoc = 0;
228 int attrs = oatDataFlowAttributes[opcode];
229 rlSrc[0] = rlSrc[1] = rlSrc[2] = badLoc;
230 if (attrs & DF_UA) {
buzbeebff24652012-05-06 16:22:05 -0700231 if (attrs & DF_A_WIDE) {
buzbee15bf9802012-06-12 17:49:27 -0700232 rlSrc[nextLoc++] = oatGetSrcWide(cUnit, mir, nextSreg);
buzbeebff24652012-05-06 16:22:05 -0700233 nextSreg+= 2;
234 } else {
235 rlSrc[nextLoc++] = oatGetSrc(cUnit, mir, nextSreg);
236 nextSreg++;
237 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700238 }
239 if (attrs & DF_UB) {
buzbeebff24652012-05-06 16:22:05 -0700240 if (attrs & DF_B_WIDE) {
buzbee15bf9802012-06-12 17:49:27 -0700241 rlSrc[nextLoc++] = oatGetSrcWide(cUnit, mir, nextSreg);
buzbeebff24652012-05-06 16:22:05 -0700242 nextSreg+= 2;
243 } else {
244 rlSrc[nextLoc++] = oatGetSrc(cUnit, mir, nextSreg);
245 nextSreg++;
246 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700247 }
248 if (attrs & DF_UC) {
buzbeebff24652012-05-06 16:22:05 -0700249 if (attrs & DF_C_WIDE) {
buzbee15bf9802012-06-12 17:49:27 -0700250 rlSrc[nextLoc++] = oatGetSrcWide(cUnit, mir, nextSreg);
buzbeebff24652012-05-06 16:22:05 -0700251 } else {
252 rlSrc[nextLoc++] = oatGetSrc(cUnit, mir, nextSreg);
253 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700254 }
255 if (attrs & DF_DA) {
buzbeebff24652012-05-06 16:22:05 -0700256 if (attrs & DF_A_WIDE) {
buzbee15bf9802012-06-12 17:49:27 -0700257 rlDest = oatGetDestWide(cUnit, mir);
buzbeebff24652012-05-06 16:22:05 -0700258 } else {
buzbee15bf9802012-06-12 17:49:27 -0700259 rlDest = oatGetDest(cUnit, mir);
buzbeebff24652012-05-06 16:22:05 -0700260 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700261 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700262 switch (opcode) {
263 case Instruction::NOP:
264 break;
buzbeee3acd072012-02-25 17:03:10 -0800265
Ian Rogers474b6da2012-09-25 00:20:38 -0700266 case Instruction::MOVE_EXCEPTION:
267 genMoveException(cUnit, rlDest);
Bill Buzbeea114add2012-05-03 15:00:40 -0700268 break;
Bill Buzbeea114add2012-05-03 15:00:40 -0700269 case Instruction::RETURN_VOID:
TDYa1274f2935e2012-06-22 06:25:03 -0700270 if (!(cUnit->attrs & METHOD_IS_LEAF)) {
buzbee408ad162012-06-06 16:45:18 -0700271 genSuspendTest(cUnit, optFlags);
Bill Buzbeea114add2012-05-03 15:00:40 -0700272 }
273 break;
274
275 case Instruction::RETURN:
276 case Instruction::RETURN_OBJECT:
TDYa1274f2935e2012-06-22 06:25:03 -0700277 if (!(cUnit->attrs & METHOD_IS_LEAF)) {
buzbee408ad162012-06-06 16:45:18 -0700278 genSuspendTest(cUnit, optFlags);
Bill Buzbeea114add2012-05-03 15:00:40 -0700279 }
280 storeValue(cUnit, oatGetReturn(cUnit, cUnit->shorty[0] == 'F'), rlSrc[0]);
281 break;
282
283 case Instruction::RETURN_WIDE:
TDYa1274f2935e2012-06-22 06:25:03 -0700284 if (!(cUnit->attrs & METHOD_IS_LEAF)) {
buzbee408ad162012-06-06 16:45:18 -0700285 genSuspendTest(cUnit, optFlags);
Bill Buzbeea114add2012-05-03 15:00:40 -0700286 }
287 storeValueWide(cUnit, oatGetReturnWide(cUnit,
288 cUnit->shorty[0] == 'D'), rlSrc[0]);
289 break;
290
291 case Instruction::MOVE_RESULT_WIDE:
buzbee408ad162012-06-06 16:45:18 -0700292 if (optFlags & MIR_INLINED)
Bill Buzbeea114add2012-05-03 15:00:40 -0700293 break; // Nop - combined w/ previous invoke
294 storeValueWide(cUnit, rlDest, oatGetReturnWide(cUnit, rlDest.fp));
295 break;
296
297 case Instruction::MOVE_RESULT:
298 case Instruction::MOVE_RESULT_OBJECT:
buzbee408ad162012-06-06 16:45:18 -0700299 if (optFlags & MIR_INLINED)
Bill Buzbeea114add2012-05-03 15:00:40 -0700300 break; // Nop - combined w/ previous invoke
301 storeValue(cUnit, rlDest, oatGetReturn(cUnit, rlDest.fp));
302 break;
303
304 case Instruction::MOVE:
305 case Instruction::MOVE_OBJECT:
306 case Instruction::MOVE_16:
307 case Instruction::MOVE_OBJECT_16:
308 case Instruction::MOVE_FROM16:
309 case Instruction::MOVE_OBJECT_FROM16:
310 storeValue(cUnit, rlDest, rlSrc[0]);
311 break;
312
313 case Instruction::MOVE_WIDE:
314 case Instruction::MOVE_WIDE_16:
315 case Instruction::MOVE_WIDE_FROM16:
316 storeValueWide(cUnit, rlDest, rlSrc[0]);
317 break;
318
319 case Instruction::CONST:
320 case Instruction::CONST_4:
321 case Instruction::CONST_16:
322 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
buzbee408ad162012-06-06 16:45:18 -0700323 loadConstantNoClobber(cUnit, rlResult.lowReg, vB);
Bill Buzbeea114add2012-05-03 15:00:40 -0700324 storeValue(cUnit, rlDest, rlResult);
325 break;
326
327 case Instruction::CONST_HIGH16:
328 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
buzbee408ad162012-06-06 16:45:18 -0700329 loadConstantNoClobber(cUnit, rlResult.lowReg, vB << 16);
Bill Buzbeea114add2012-05-03 15:00:40 -0700330 storeValue(cUnit, rlDest, rlResult);
331 break;
332
333 case Instruction::CONST_WIDE_16:
334 case Instruction::CONST_WIDE_32:
335 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
buzbee408ad162012-06-06 16:45:18 -0700336 loadConstantValueWide(cUnit, rlResult.lowReg, rlResult.highReg, vB,
337 (vB & 0x80000000) ? -1 : 0);
Bill Buzbeea114add2012-05-03 15:00:40 -0700338 storeValueWide(cUnit, rlDest, rlResult);
339 break;
340
341 case Instruction::CONST_WIDE:
342 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
343 loadConstantValueWide(cUnit, rlResult.lowReg, rlResult.highReg,
344 mir->dalvikInsn.vB_wide & 0xffffffff,
345 (mir->dalvikInsn.vB_wide >> 32) & 0xffffffff);
346 storeValueWide(cUnit, rlDest, rlResult);
347 break;
348
349 case Instruction::CONST_WIDE_HIGH16:
350 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
351 loadConstantValueWide(cUnit, rlResult.lowReg, rlResult.highReg,
buzbee408ad162012-06-06 16:45:18 -0700352 0, vB << 16);
Bill Buzbeea114add2012-05-03 15:00:40 -0700353 storeValueWide(cUnit, rlDest, rlResult);
354 break;
355
356 case Instruction::MONITOR_ENTER:
buzbee408ad162012-06-06 16:45:18 -0700357 genMonitorEnter(cUnit, optFlags, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700358 break;
359
360 case Instruction::MONITOR_EXIT:
buzbee408ad162012-06-06 16:45:18 -0700361 genMonitorExit(cUnit, optFlags, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700362 break;
363
364 case Instruction::CHECK_CAST:
buzbee408ad162012-06-06 16:45:18 -0700365 genCheckCast(cUnit, vB, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700366 break;
367
368 case Instruction::INSTANCE_OF:
buzbee408ad162012-06-06 16:45:18 -0700369 genInstanceof(cUnit, vC, rlDest, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700370 break;
371
372 case Instruction::NEW_INSTANCE:
buzbee408ad162012-06-06 16:45:18 -0700373 genNewInstance(cUnit, vB, rlDest);
Bill Buzbeea114add2012-05-03 15:00:40 -0700374 break;
375
376 case Instruction::THROW:
buzbee408ad162012-06-06 16:45:18 -0700377 genThrow(cUnit, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700378 break;
379
Bill Buzbeea114add2012-05-03 15:00:40 -0700380 case Instruction::ARRAY_LENGTH:
381 int lenOffset;
382 lenOffset = Array::LengthOffset().Int32Value();
383 rlSrc[0] = loadValue(cUnit, rlSrc[0], kCoreReg);
buzbee408ad162012-06-06 16:45:18 -0700384 genNullCheck(cUnit, rlSrc[0].sRegLow, rlSrc[0].lowReg, optFlags);
Bill Buzbeea114add2012-05-03 15:00:40 -0700385 rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
386 loadWordDisp(cUnit, rlSrc[0].lowReg, lenOffset, rlResult.lowReg);
387 storeValue(cUnit, rlDest, rlResult);
388 break;
389
390 case Instruction::CONST_STRING:
391 case Instruction::CONST_STRING_JUMBO:
buzbee6969d502012-06-15 16:40:31 -0700392 genConstString(cUnit, vB, rlDest);
Bill Buzbeea114add2012-05-03 15:00:40 -0700393 break;
394
395 case Instruction::CONST_CLASS:
buzbee6969d502012-06-15 16:40:31 -0700396 genConstClass(cUnit, vB, rlDest);
Bill Buzbeea114add2012-05-03 15:00:40 -0700397 break;
398
399 case Instruction::FILL_ARRAY_DATA:
buzbee408ad162012-06-06 16:45:18 -0700400 genFillArrayData(cUnit, vB, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700401 break;
402
403 case Instruction::FILLED_NEW_ARRAY:
buzbee6969d502012-06-15 16:40:31 -0700404 genFilledNewArray(cUnit, oatNewCallInfo(cUnit, bb, mir, kStatic,
buzbee3b3dbdd2012-06-13 13:39:34 -0700405 false /* not range */));
Bill Buzbeea114add2012-05-03 15:00:40 -0700406 break;
407
408 case Instruction::FILLED_NEW_ARRAY_RANGE:
buzbee6969d502012-06-15 16:40:31 -0700409 genFilledNewArray(cUnit, oatNewCallInfo(cUnit, bb, mir, kStatic,
buzbee3b3dbdd2012-06-13 13:39:34 -0700410 true /* range */));
Bill Buzbeea114add2012-05-03 15:00:40 -0700411 break;
412
413 case Instruction::NEW_ARRAY:
buzbee408ad162012-06-06 16:45:18 -0700414 genNewArray(cUnit, vC, rlDest, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700415 break;
416
417 case Instruction::GOTO:
418 case Instruction::GOTO_16:
419 case Instruction::GOTO_32:
420 if (bb->taken->startOffset <= mir->offset) {
buzbee408ad162012-06-06 16:45:18 -0700421 genSuspendTestAndBranch(cUnit, optFlags, &labelList[bb->taken->id]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700422 } else {
423 opUnconditionalBranch(cUnit, &labelList[bb->taken->id]);
424 }
425 break;
426
427 case Instruction::PACKED_SWITCH:
buzbee408ad162012-06-06 16:45:18 -0700428 genPackedSwitch(cUnit, vB, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700429 break;
430
431 case Instruction::SPARSE_SWITCH:
buzbeea1da8a52012-07-09 14:00:21 -0700432 genSparseSwitch(cUnit, vB, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700433 break;
434
435 case Instruction::CMPL_FLOAT:
436 case Instruction::CMPG_FLOAT:
437 case Instruction::CMPL_DOUBLE:
438 case Instruction::CMPG_DOUBLE:
buzbee408ad162012-06-06 16:45:18 -0700439 res = genCmpFP(cUnit, opcode, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700440 break;
441
442 case Instruction::CMP_LONG:
buzbee408ad162012-06-06 16:45:18 -0700443 genCmpLong(cUnit, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700444 break;
445
446 case Instruction::IF_EQ:
447 case Instruction::IF_NE:
448 case Instruction::IF_LT:
449 case Instruction::IF_GE:
450 case Instruction::IF_GT:
451 case Instruction::IF_LE: {
buzbee3b3dbdd2012-06-13 13:39:34 -0700452 LIR* taken = &labelList[bb->taken->id];
453 LIR* fallThrough = &labelList[bb->fallThrough->id];
Bill Buzbeea114add2012-05-03 15:00:40 -0700454 bool backwardBranch;
455 backwardBranch = (bb->taken->startOffset <= mir->offset);
456 if (backwardBranch) {
buzbee408ad162012-06-06 16:45:18 -0700457 genSuspendTest(cUnit, optFlags);
Bill Buzbeea114add2012-05-03 15:00:40 -0700458 }
buzbee3b3dbdd2012-06-13 13:39:34 -0700459 genCompareAndBranch(cUnit, opcode, rlSrc[0], rlSrc[1], taken,
460 fallThrough);
Bill Buzbeea114add2012-05-03 15:00:40 -0700461 break;
462 }
463
464 case Instruction::IF_EQZ:
465 case Instruction::IF_NEZ:
466 case Instruction::IF_LTZ:
467 case Instruction::IF_GEZ:
468 case Instruction::IF_GTZ:
469 case Instruction::IF_LEZ: {
buzbee3b3dbdd2012-06-13 13:39:34 -0700470 LIR* taken = &labelList[bb->taken->id];
471 LIR* fallThrough = &labelList[bb->fallThrough->id];
Bill Buzbeea114add2012-05-03 15:00:40 -0700472 bool backwardBranch;
473 backwardBranch = (bb->taken->startOffset <= mir->offset);
474 if (backwardBranch) {
buzbee408ad162012-06-06 16:45:18 -0700475 genSuspendTest(cUnit, optFlags);
Bill Buzbeea114add2012-05-03 15:00:40 -0700476 }
buzbee3b3dbdd2012-06-13 13:39:34 -0700477 genCompareZeroAndBranch(cUnit, opcode, rlSrc[0], taken, fallThrough);
Bill Buzbeea114add2012-05-03 15:00:40 -0700478 break;
479 }
480
481 case Instruction::AGET_WIDE:
buzbee408ad162012-06-06 16:45:18 -0700482 genArrayGet(cUnit, optFlags, kLong, rlSrc[0], rlSrc[1], rlDest, 3);
Bill Buzbeea114add2012-05-03 15:00:40 -0700483 break;
484 case Instruction::AGET:
485 case Instruction::AGET_OBJECT:
buzbee408ad162012-06-06 16:45:18 -0700486 genArrayGet(cUnit, optFlags, kWord, rlSrc[0], rlSrc[1], rlDest, 2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700487 break;
488 case Instruction::AGET_BOOLEAN:
buzbee408ad162012-06-06 16:45:18 -0700489 genArrayGet(cUnit, optFlags, kUnsignedByte, rlSrc[0], rlSrc[1], rlDest, 0);
Bill Buzbeea114add2012-05-03 15:00:40 -0700490 break;
491 case Instruction::AGET_BYTE:
buzbee408ad162012-06-06 16:45:18 -0700492 genArrayGet(cUnit, optFlags, kSignedByte, rlSrc[0], rlSrc[1], rlDest, 0);
Bill Buzbeea114add2012-05-03 15:00:40 -0700493 break;
494 case Instruction::AGET_CHAR:
buzbee408ad162012-06-06 16:45:18 -0700495 genArrayGet(cUnit, optFlags, kUnsignedHalf, rlSrc[0], rlSrc[1], rlDest, 1);
Bill Buzbeea114add2012-05-03 15:00:40 -0700496 break;
497 case Instruction::AGET_SHORT:
buzbee408ad162012-06-06 16:45:18 -0700498 genArrayGet(cUnit, optFlags, kSignedHalf, rlSrc[0], rlSrc[1], rlDest, 1);
Bill Buzbeea114add2012-05-03 15:00:40 -0700499 break;
500 case Instruction::APUT_WIDE:
buzbee408ad162012-06-06 16:45:18 -0700501 genArrayPut(cUnit, optFlags, kLong, rlSrc[1], rlSrc[2], rlSrc[0], 3);
Bill Buzbeea114add2012-05-03 15:00:40 -0700502 break;
503 case Instruction::APUT:
buzbee408ad162012-06-06 16:45:18 -0700504 genArrayPut(cUnit, optFlags, kWord, rlSrc[1], rlSrc[2], rlSrc[0], 2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700505 break;
506 case Instruction::APUT_OBJECT:
buzbee408ad162012-06-06 16:45:18 -0700507 genArrayObjPut(cUnit, optFlags, rlSrc[1], rlSrc[2], rlSrc[0], 2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700508 break;
509 case Instruction::APUT_SHORT:
510 case Instruction::APUT_CHAR:
buzbee408ad162012-06-06 16:45:18 -0700511 genArrayPut(cUnit, optFlags, kUnsignedHalf, rlSrc[1], rlSrc[2], rlSrc[0], 1);
Bill Buzbeea114add2012-05-03 15:00:40 -0700512 break;
513 case Instruction::APUT_BYTE:
514 case Instruction::APUT_BOOLEAN:
buzbee408ad162012-06-06 16:45:18 -0700515 genArrayPut(cUnit, optFlags, kUnsignedByte, rlSrc[1], rlSrc[2],
Bill Buzbeea114add2012-05-03 15:00:40 -0700516 rlSrc[0], 0);
517 break;
518
519 case Instruction::IGET_OBJECT:
520 //case Instruction::IGET_OBJECT_VOLATILE:
buzbee408ad162012-06-06 16:45:18 -0700521 genIGet(cUnit, vC, optFlags, kWord, rlDest, rlSrc[0], false, true);
Bill Buzbeea114add2012-05-03 15:00:40 -0700522 break;
523
524 case Instruction::IGET_WIDE:
525 //case Instruction::IGET_WIDE_VOLATILE:
buzbee408ad162012-06-06 16:45:18 -0700526 genIGet(cUnit, vC, optFlags, kLong, rlDest, rlSrc[0], true, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700527 break;
528
529 case Instruction::IGET:
530 //case Instruction::IGET_VOLATILE:
buzbee408ad162012-06-06 16:45:18 -0700531 genIGet(cUnit, vC, optFlags, kWord, rlDest, rlSrc[0], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700532 break;
533
534 case Instruction::IGET_CHAR:
buzbee408ad162012-06-06 16:45:18 -0700535 genIGet(cUnit, vC, optFlags, kUnsignedHalf, rlDest, rlSrc[0], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700536 break;
537
538 case Instruction::IGET_SHORT:
buzbee408ad162012-06-06 16:45:18 -0700539 genIGet(cUnit, vC, optFlags, kSignedHalf, rlDest, rlSrc[0], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700540 break;
541
542 case Instruction::IGET_BOOLEAN:
543 case Instruction::IGET_BYTE:
buzbee408ad162012-06-06 16:45:18 -0700544 genIGet(cUnit, vC, optFlags, kUnsignedByte, rlDest, rlSrc[0], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700545 break;
546
547 case Instruction::IPUT_WIDE:
548 //case Instruction::IPUT_WIDE_VOLATILE:
buzbee408ad162012-06-06 16:45:18 -0700549 genIPut(cUnit, vC, optFlags, kLong, rlSrc[0], rlSrc[1], true, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700550 break;
551
552 case Instruction::IPUT_OBJECT:
553 //case Instruction::IPUT_OBJECT_VOLATILE:
buzbee408ad162012-06-06 16:45:18 -0700554 genIPut(cUnit, vC, optFlags, kWord, rlSrc[0], rlSrc[1], false, true);
Bill Buzbeea114add2012-05-03 15:00:40 -0700555 break;
556
557 case Instruction::IPUT:
558 //case Instruction::IPUT_VOLATILE:
buzbee408ad162012-06-06 16:45:18 -0700559 genIPut(cUnit, vC, optFlags, kWord, rlSrc[0], rlSrc[1], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700560 break;
561
562 case Instruction::IPUT_BOOLEAN:
563 case Instruction::IPUT_BYTE:
buzbee408ad162012-06-06 16:45:18 -0700564 genIPut(cUnit, vC, optFlags, kUnsignedByte, rlSrc[0], rlSrc[1], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700565 break;
566
567 case Instruction::IPUT_CHAR:
buzbee408ad162012-06-06 16:45:18 -0700568 genIPut(cUnit, vC, optFlags, kUnsignedHalf, rlSrc[0], rlSrc[1], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700569 break;
570
571 case Instruction::IPUT_SHORT:
buzbee408ad162012-06-06 16:45:18 -0700572 genIPut(cUnit, vC, optFlags, kSignedHalf, rlSrc[0], rlSrc[1], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700573 break;
574
575 case Instruction::SGET_OBJECT:
buzbee408ad162012-06-06 16:45:18 -0700576 genSget(cUnit, vB, rlDest, false, true);
Bill Buzbeea114add2012-05-03 15:00:40 -0700577 break;
578 case Instruction::SGET:
579 case Instruction::SGET_BOOLEAN:
580 case Instruction::SGET_BYTE:
581 case Instruction::SGET_CHAR:
582 case Instruction::SGET_SHORT:
buzbee408ad162012-06-06 16:45:18 -0700583 genSget(cUnit, vB, rlDest, false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700584 break;
585
586 case Instruction::SGET_WIDE:
buzbee408ad162012-06-06 16:45:18 -0700587 genSget(cUnit, vB, rlDest, true, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700588 break;
589
590 case Instruction::SPUT_OBJECT:
buzbee408ad162012-06-06 16:45:18 -0700591 genSput(cUnit, vB, rlSrc[0], false, true);
Bill Buzbeea114add2012-05-03 15:00:40 -0700592 break;
593
594 case Instruction::SPUT:
595 case Instruction::SPUT_BOOLEAN:
596 case Instruction::SPUT_BYTE:
597 case Instruction::SPUT_CHAR:
598 case Instruction::SPUT_SHORT:
buzbee408ad162012-06-06 16:45:18 -0700599 genSput(cUnit, vB, rlSrc[0], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700600 break;
601
602 case Instruction::SPUT_WIDE:
buzbee408ad162012-06-06 16:45:18 -0700603 genSput(cUnit, vB, rlSrc[0], true, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700604 break;
605
606 case Instruction::INVOKE_STATIC_RANGE:
buzbee6969d502012-06-15 16:40:31 -0700607 genInvoke(cUnit, oatNewCallInfo(cUnit, bb, mir, kStatic, true));
Bill Buzbeea114add2012-05-03 15:00:40 -0700608 break;
609 case Instruction::INVOKE_STATIC:
buzbee6969d502012-06-15 16:40:31 -0700610 genInvoke(cUnit, oatNewCallInfo(cUnit, bb, mir, kStatic, false));
Bill Buzbeea114add2012-05-03 15:00:40 -0700611 break;
612
613 case Instruction::INVOKE_DIRECT:
buzbee6969d502012-06-15 16:40:31 -0700614 genInvoke(cUnit, oatNewCallInfo(cUnit, bb, mir, kDirect, false));
Bill Buzbeea114add2012-05-03 15:00:40 -0700615 break;
616 case Instruction::INVOKE_DIRECT_RANGE:
buzbee6969d502012-06-15 16:40:31 -0700617 genInvoke(cUnit, oatNewCallInfo(cUnit, bb, mir, kDirect, true));
Bill Buzbeea114add2012-05-03 15:00:40 -0700618 break;
619
620 case Instruction::INVOKE_VIRTUAL:
buzbee6969d502012-06-15 16:40:31 -0700621 genInvoke(cUnit, oatNewCallInfo(cUnit, bb, mir, kVirtual, false));
Bill Buzbeea114add2012-05-03 15:00:40 -0700622 break;
623 case Instruction::INVOKE_VIRTUAL_RANGE:
buzbee6969d502012-06-15 16:40:31 -0700624 genInvoke(cUnit, oatNewCallInfo(cUnit, bb, mir, kVirtual, true));
Bill Buzbeea114add2012-05-03 15:00:40 -0700625 break;
626
627 case Instruction::INVOKE_SUPER:
buzbee6969d502012-06-15 16:40:31 -0700628 genInvoke(cUnit, oatNewCallInfo(cUnit, bb, mir, kSuper, false));
Bill Buzbeea114add2012-05-03 15:00:40 -0700629 break;
630 case Instruction::INVOKE_SUPER_RANGE:
buzbee6969d502012-06-15 16:40:31 -0700631 genInvoke(cUnit, oatNewCallInfo(cUnit, bb, mir, kSuper, true));
Bill Buzbeea114add2012-05-03 15:00:40 -0700632 break;
633
634 case Instruction::INVOKE_INTERFACE:
buzbee6969d502012-06-15 16:40:31 -0700635 genInvoke(cUnit, oatNewCallInfo(cUnit, bb, mir, kInterface, false));
Bill Buzbeea114add2012-05-03 15:00:40 -0700636 break;
637 case Instruction::INVOKE_INTERFACE_RANGE:
buzbee6969d502012-06-15 16:40:31 -0700638 genInvoke(cUnit, oatNewCallInfo(cUnit, bb, mir, kInterface, true));
Bill Buzbeea114add2012-05-03 15:00:40 -0700639 break;
640
641 case Instruction::NEG_INT:
642 case Instruction::NOT_INT:
buzbee408ad162012-06-06 16:45:18 -0700643 res = genArithOpInt(cUnit, opcode, rlDest, rlSrc[0], rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700644 break;
645
646 case Instruction::NEG_LONG:
647 case Instruction::NOT_LONG:
buzbee408ad162012-06-06 16:45:18 -0700648 res = genArithOpLong(cUnit, opcode, rlDest, rlSrc[0], rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700649 break;
650
651 case Instruction::NEG_FLOAT:
buzbee408ad162012-06-06 16:45:18 -0700652 res = genArithOpFloat(cUnit, opcode, rlDest, rlSrc[0], rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700653 break;
654
655 case Instruction::NEG_DOUBLE:
buzbee408ad162012-06-06 16:45:18 -0700656 res = genArithOpDouble(cUnit, opcode, rlDest, rlSrc[0], rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700657 break;
658
659 case Instruction::INT_TO_LONG:
buzbee408ad162012-06-06 16:45:18 -0700660 genIntToLong(cUnit, rlDest, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700661 break;
662
663 case Instruction::LONG_TO_INT:
664 rlSrc[0] = oatUpdateLocWide(cUnit, rlSrc[0]);
665 rlSrc[0] = oatWideToNarrow(cUnit, rlSrc[0]);
666 storeValue(cUnit, rlDest, rlSrc[0]);
667 break;
668
669 case Instruction::INT_TO_BYTE:
670 case Instruction::INT_TO_SHORT:
671 case Instruction::INT_TO_CHAR:
buzbee408ad162012-06-06 16:45:18 -0700672 genIntNarrowing(cUnit, opcode, rlDest, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700673 break;
674
675 case Instruction::INT_TO_FLOAT:
676 case Instruction::INT_TO_DOUBLE:
677 case Instruction::LONG_TO_FLOAT:
678 case Instruction::LONG_TO_DOUBLE:
679 case Instruction::FLOAT_TO_INT:
680 case Instruction::FLOAT_TO_LONG:
681 case Instruction::FLOAT_TO_DOUBLE:
682 case Instruction::DOUBLE_TO_INT:
683 case Instruction::DOUBLE_TO_LONG:
684 case Instruction::DOUBLE_TO_FLOAT:
buzbee408ad162012-06-06 16:45:18 -0700685 genConversion(cUnit, opcode, rlDest, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700686 break;
687
688 case Instruction::ADD_INT:
689 case Instruction::SUB_INT:
690 case Instruction::MUL_INT:
691 case Instruction::DIV_INT:
692 case Instruction::REM_INT:
693 case Instruction::AND_INT:
694 case Instruction::OR_INT:
695 case Instruction::XOR_INT:
696 case Instruction::SHL_INT:
697 case Instruction::SHR_INT:
698 case Instruction::USHR_INT:
699 case Instruction::ADD_INT_2ADDR:
700 case Instruction::SUB_INT_2ADDR:
701 case Instruction::MUL_INT_2ADDR:
702 case Instruction::DIV_INT_2ADDR:
703 case Instruction::REM_INT_2ADDR:
704 case Instruction::AND_INT_2ADDR:
705 case Instruction::OR_INT_2ADDR:
706 case Instruction::XOR_INT_2ADDR:
707 case Instruction::SHL_INT_2ADDR:
708 case Instruction::SHR_INT_2ADDR:
709 case Instruction::USHR_INT_2ADDR:
buzbee408ad162012-06-06 16:45:18 -0700710 genArithOpInt(cUnit, opcode, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700711 break;
712
713 case Instruction::ADD_LONG:
714 case Instruction::SUB_LONG:
715 case Instruction::MUL_LONG:
716 case Instruction::DIV_LONG:
717 case Instruction::REM_LONG:
718 case Instruction::AND_LONG:
719 case Instruction::OR_LONG:
720 case Instruction::XOR_LONG:
721 case Instruction::ADD_LONG_2ADDR:
722 case Instruction::SUB_LONG_2ADDR:
723 case Instruction::MUL_LONG_2ADDR:
724 case Instruction::DIV_LONG_2ADDR:
725 case Instruction::REM_LONG_2ADDR:
726 case Instruction::AND_LONG_2ADDR:
727 case Instruction::OR_LONG_2ADDR:
728 case Instruction::XOR_LONG_2ADDR:
buzbee408ad162012-06-06 16:45:18 -0700729 genArithOpLong(cUnit, opcode, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700730 break;
731
732 case Instruction::SHL_LONG:
733 case Instruction::SHR_LONG:
734 case Instruction::USHR_LONG:
735 case Instruction::SHL_LONG_2ADDR:
736 case Instruction::SHR_LONG_2ADDR:
737 case Instruction::USHR_LONG_2ADDR:
buzbee408ad162012-06-06 16:45:18 -0700738 genShiftOpLong(cUnit, opcode, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700739 break;
740
741 case Instruction::ADD_FLOAT:
742 case Instruction::SUB_FLOAT:
743 case Instruction::MUL_FLOAT:
744 case Instruction::DIV_FLOAT:
745 case Instruction::REM_FLOAT:
746 case Instruction::ADD_FLOAT_2ADDR:
747 case Instruction::SUB_FLOAT_2ADDR:
748 case Instruction::MUL_FLOAT_2ADDR:
749 case Instruction::DIV_FLOAT_2ADDR:
750 case Instruction::REM_FLOAT_2ADDR:
buzbee408ad162012-06-06 16:45:18 -0700751 genArithOpFloat(cUnit, opcode, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700752 break;
753
754 case Instruction::ADD_DOUBLE:
755 case Instruction::SUB_DOUBLE:
756 case Instruction::MUL_DOUBLE:
757 case Instruction::DIV_DOUBLE:
758 case Instruction::REM_DOUBLE:
759 case Instruction::ADD_DOUBLE_2ADDR:
760 case Instruction::SUB_DOUBLE_2ADDR:
761 case Instruction::MUL_DOUBLE_2ADDR:
762 case Instruction::DIV_DOUBLE_2ADDR:
763 case Instruction::REM_DOUBLE_2ADDR:
buzbee408ad162012-06-06 16:45:18 -0700764 genArithOpDouble(cUnit, opcode, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700765 break;
766
767 case Instruction::RSUB_INT:
768 case Instruction::ADD_INT_LIT16:
769 case Instruction::MUL_INT_LIT16:
770 case Instruction::DIV_INT_LIT16:
771 case Instruction::REM_INT_LIT16:
772 case Instruction::AND_INT_LIT16:
773 case Instruction::OR_INT_LIT16:
774 case Instruction::XOR_INT_LIT16:
775 case Instruction::ADD_INT_LIT8:
776 case Instruction::RSUB_INT_LIT8:
777 case Instruction::MUL_INT_LIT8:
778 case Instruction::DIV_INT_LIT8:
779 case Instruction::REM_INT_LIT8:
780 case Instruction::AND_INT_LIT8:
781 case Instruction::OR_INT_LIT8:
782 case Instruction::XOR_INT_LIT8:
783 case Instruction::SHL_INT_LIT8:
784 case Instruction::SHR_INT_LIT8:
785 case Instruction::USHR_INT_LIT8:
buzbee408ad162012-06-06 16:45:18 -0700786 genArithOpIntLit(cUnit, opcode, rlDest, rlSrc[0], vC);
Bill Buzbeea114add2012-05-03 15:00:40 -0700787 break;
788
789 default:
790 res = true;
791 }
792 return res;
buzbeee3acd072012-02-25 17:03:10 -0800793}
794
buzbee31a4a6f2012-02-28 15:36:15 -0800795const char* extendedMIROpNames[kMirOpLast - kMirOpFirst] = {
Bill Buzbeea114add2012-05-03 15:00:40 -0700796 "kMirOpPhi",
797 "kMirOpCopy",
798 "kMirFusedCmplFloat",
799 "kMirFusedCmpgFloat",
800 "kMirFusedCmplDouble",
801 "kMirFusedCmpgDouble",
802 "kMirFusedCmpLong",
803 "kMirNop",
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700804 "kMirOpNullCheck",
805 "kMirOpRangeCheck",
806 "kMirOpDivZeroCheck",
807 "kMirOpCheck",
buzbeee3acd072012-02-25 17:03:10 -0800808};
809
810/* Extended MIR instructions like PHI */
buzbee84fd6932012-03-29 16:44:16 -0700811void handleExtendedMethodMIR(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir)
buzbeee3acd072012-02-25 17:03:10 -0800812{
Bill Buzbeea114add2012-05-03 15:00:40 -0700813 int opOffset = mir->dalvikInsn.opcode - kMirOpFirst;
814 char* msg = NULL;
815 if (cUnit->printMe) {
816 msg = (char*)oatNew(cUnit, strlen(extendedMIROpNames[opOffset]) + 1,
817 false, kAllocDebugInfo);
818 strcpy(msg, extendedMIROpNames[opOffset]);
819 }
820 LIR* op = newLIR1(cUnit, kPseudoExtended, (int) msg);
buzbeee3acd072012-02-25 17:03:10 -0800821
Bill Buzbeea114add2012-05-03 15:00:40 -0700822 switch ((ExtendedMIROpcode)mir->dalvikInsn.opcode) {
823 case kMirOpPhi: {
824 char* ssaString = NULL;
825 if (cUnit->printMe) {
826 ssaString = oatGetSSAString(cUnit, mir->ssaRep);
827 }
828 op->flags.isNop = true;
829 newLIR1(cUnit, kPseudoSSARep, (int) ssaString);
830 break;
buzbeee3acd072012-02-25 17:03:10 -0800831 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700832 case kMirOpCopy: {
833 RegLocation rlSrc = oatGetSrc(cUnit, mir, 0);
buzbee15bf9802012-06-12 17:49:27 -0700834 RegLocation rlDest = oatGetDest(cUnit, mir);
Bill Buzbeea114add2012-05-03 15:00:40 -0700835 storeValue(cUnit, rlDest, rlSrc);
836 break;
837 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700838 case kMirOpFusedCmplFloat:
839 genFusedFPCmpBranch(cUnit, bb, mir, false /*gt bias*/, false /*double*/);
840 break;
841 case kMirOpFusedCmpgFloat:
842 genFusedFPCmpBranch(cUnit, bb, mir, true /*gt bias*/, false /*double*/);
843 break;
844 case kMirOpFusedCmplDouble:
845 genFusedFPCmpBranch(cUnit, bb, mir, false /*gt bias*/, true /*double*/);
846 break;
847 case kMirOpFusedCmpgDouble:
848 genFusedFPCmpBranch(cUnit, bb, mir, true /*gt bias*/, true /*double*/);
849 break;
850 case kMirOpFusedCmpLong:
851 genFusedLongCmpBranch(cUnit, bb, mir);
852 break;
Bill Buzbeea114add2012-05-03 15:00:40 -0700853 default:
854 break;
855 }
buzbeee3acd072012-02-25 17:03:10 -0800856}
857
858/* Handle the content in each basic block */
buzbee31a4a6f2012-02-28 15:36:15 -0800859bool methodBlockCodeGen(CompilationUnit* cUnit, BasicBlock* bb)
buzbeee3acd072012-02-25 17:03:10 -0800860{
buzbee488a78c2012-09-10 15:55:34 -0700861 if (bb->blockType == kDead) return false;
buzbee8320f382012-09-11 16:29:42 -0700862 cUnit->currentDalvikOffset = bb->startOffset;
Bill Buzbeea114add2012-05-03 15:00:40 -0700863 MIR* mir;
buzbeea1da8a52012-07-09 14:00:21 -0700864 LIR* labelList = cUnit->blockLabelList;
Bill Buzbeea114add2012-05-03 15:00:40 -0700865 int blockId = bb->id;
buzbeee3acd072012-02-25 17:03:10 -0800866
Bill Buzbeea114add2012-05-03 15:00:40 -0700867 cUnit->curBlock = bb;
868 labelList[blockId].operands[0] = bb->startOffset;
buzbeee3acd072012-02-25 17:03:10 -0800869
Bill Buzbeea114add2012-05-03 15:00:40 -0700870 /* Insert the block label */
871 labelList[blockId].opcode = kPseudoNormalBlockLabel;
872 oatAppendLIR(cUnit, (LIR*) &labelList[blockId]);
buzbeee3acd072012-02-25 17:03:10 -0800873
buzbee8320f382012-09-11 16:29:42 -0700874 LIR* headLIR = NULL;
875
Bill Buzbeea5b30242012-09-28 07:19:44 -0700876 /* If this is a catch block, export the start address */
buzbee8320f382012-09-11 16:29:42 -0700877 if (bb->catchEntry) {
Bill Buzbeea5b30242012-09-28 07:19:44 -0700878 headLIR = newLIR0(cUnit, kPseudoExportedPC);
buzbee8320f382012-09-11 16:29:42 -0700879 }
880
Bill Buzbeea114add2012-05-03 15:00:40 -0700881 /* Free temp registers and reset redundant store tracking */
882 oatResetRegPool(cUnit);
883 oatResetDefTracking(cUnit);
884
buzbeed1643e42012-09-05 14:06:51 -0700885 oatClobberAllRegs(cUnit);
Bill Buzbeea114add2012-05-03 15:00:40 -0700886
Bill Buzbeea114add2012-05-03 15:00:40 -0700887
888 if (bb->blockType == kEntryBlock) {
buzbeead8f15e2012-06-18 14:49:45 -0700889 int startVReg = cUnit->numDalvikRegisters - cUnit->numIns;
890 genEntrySequence(cUnit, &cUnit->regLocation[startVReg],
891 cUnit->regLocation[cUnit->methodSReg]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700892 } else if (bb->blockType == kExitBlock) {
buzbee2cfc6392012-05-07 14:51:40 -0700893 genExitSequence(cUnit);
Bill Buzbeea114add2012-05-03 15:00:40 -0700894 }
895
896 for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
buzbeee3acd072012-02-25 17:03:10 -0800897 oatResetRegPool(cUnit);
Bill Buzbeea114add2012-05-03 15:00:40 -0700898 if (cUnit->disableOpt & (1 << kTrackLiveTemps)) {
899 oatClobberAllRegs(cUnit);
buzbeee1965672012-03-11 18:39:19 -0700900 }
901
Bill Buzbeea114add2012-05-03 15:00:40 -0700902 if (cUnit->disableOpt & (1 << kSuppressLoads)) {
903 oatResetDefTracking(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800904 }
905
buzbee3d661942012-03-14 17:37:27 -0700906#ifndef NDEBUG
Bill Buzbeea114add2012-05-03 15:00:40 -0700907 /* Reset temp tracking sanity check */
908 cUnit->liveSReg = INVALID_SREG;
buzbee3d661942012-03-14 17:37:27 -0700909#endif
910
Bill Buzbeea114add2012-05-03 15:00:40 -0700911 cUnit->currentDalvikOffset = mir->offset;
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700912 int opcode = mir->dalvikInsn.opcode;
Bill Buzbeea114add2012-05-03 15:00:40 -0700913 LIR* boundaryLIR;
buzbeee3acd072012-02-25 17:03:10 -0800914
Bill Buzbeea114add2012-05-03 15:00:40 -0700915 /* Mark the beginning of a Dalvik instruction for line tracking */
916 char* instStr = cUnit->printMe ?
917 oatGetDalvikDisassembly(cUnit, mir->dalvikInsn, "") : NULL;
buzbeed1643e42012-09-05 14:06:51 -0700918 boundaryLIR = markBoundary(cUnit, mir->offset, instStr);
Bill Buzbeea114add2012-05-03 15:00:40 -0700919 /* Remember the first LIR for this block */
920 if (headLIR == NULL) {
921 headLIR = boundaryLIR;
922 /* Set the first boundaryLIR as a scheduling barrier */
923 headLIR->defMask = ENCODE_ALL;
buzbeee3acd072012-02-25 17:03:10 -0800924 }
925
Bill Buzbeea114add2012-05-03 15:00:40 -0700926 /* If we're compiling for the debugger, generate an update callout */
927 if (cUnit->genDebugger) {
928 genDebuggerUpdate(cUnit, mir->offset);
buzbeee3acd072012-02-25 17:03:10 -0800929 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700930
931 /* Don't generate the SSA annotation unless verbose mode is on */
932 if (cUnit->printMe && mir->ssaRep) {
933 char* ssaString = oatGetSSAString(cUnit, mir->ssaRep);
934 newLIR1(cUnit, kPseudoSSARep, (int) ssaString);
935 }
936
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700937 if (opcode == kMirOpCheck) {
938 // Combine check and work halves of throwing instruction.
939 MIR* workHalf = mir->meta.throwInsn;
940 mir->dalvikInsn.opcode = workHalf->dalvikInsn.opcode;
941 opcode = workHalf->dalvikInsn.opcode;
942 SSARepresentation* ssaRep = workHalf->ssaRep;
943 workHalf->ssaRep = mir->ssaRep;
944 mir->ssaRep = ssaRep;
945 workHalf->dalvikInsn.opcode = static_cast<Instruction::Code>(kMirOpNop);
946 }
947
948 if (opcode >= kMirOpFirst) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700949 handleExtendedMethodMIR(cUnit, bb, mir);
950 continue;
951 }
952
953 bool notHandled = compileDalvikInstruction(cUnit, mir, bb, labelList);
954 if (notHandled) {
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700955 LOG(FATAL) << StringPrintf("%#06x: Opcode %#x (%s)",
956 mir->offset, opcode,
957 Instruction::Name(mir->dalvikInsn.opcode));
Bill Buzbeea114add2012-05-03 15:00:40 -0700958 }
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{
buzbeea1da8a52012-07-09 14:00:21 -0700981 LIR* labelList = cUnit->blockLabelList;
Bill Buzbeea114add2012-05-03 15:00:40 -0700982 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);
Elliott Hughes74847412012-06-20 18:10:21 -07001009 DCHECK(bb->firstMIRInsn != NULL);
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 =
buzbeea1da8a52012-07-09 14:00:21 -07001026 (LIR*) 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