blob: 3170abc7f0415158bda321986cd616caa8cff3e9 [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
buzbee2cfc6392012-05-07 14:51:40 -070021const RegLocation badLoc = {kLocDalvikFrame, 0, 0, 0, 0, 0, 0, 0, 0,
22 INVALID_REG, INVALID_REG, INVALID_SREG,
23 INVALID_SREG};
buzbeee3acd072012-02-25 17:03:10 -080024
25/* Mark register usage state and return long retloc */
Ian Rogersf7d9ad32012-03-13 18:45:39 -070026RegLocation oatGetReturnWide(CompilationUnit* cUnit, bool isDouble)
buzbeee3acd072012-02-25 17:03:10 -080027{
buzbeef0504cd2012-11-13 16:31:10 -080028 RegLocation gpr_res = locCReturnWide();
29 RegLocation fpr_res = locCReturnDouble();
Bill Buzbeea114add2012-05-03 15:00:40 -070030 RegLocation res = isDouble ? fpr_res : gpr_res;
31 oatClobber(cUnit, res.lowReg);
32 oatClobber(cUnit, res.highReg);
33 oatLockTemp(cUnit, res.lowReg);
34 oatLockTemp(cUnit, res.highReg);
35 oatMarkPair(cUnit, res.lowReg, res.highReg);
36 return res;
buzbeee3acd072012-02-25 17:03:10 -080037}
38
Ian Rogersf7d9ad32012-03-13 18:45:39 -070039RegLocation oatGetReturn(CompilationUnit* cUnit, bool isFloat)
buzbeee3acd072012-02-25 17:03:10 -080040{
buzbeef0504cd2012-11-13 16:31:10 -080041 RegLocation gpr_res = locCReturn();
42 RegLocation fpr_res = locCReturnFloat();
Ian Rogersf7d9ad32012-03-13 18:45:39 -070043 RegLocation res = isFloat ? fpr_res : gpr_res;
Bill Buzbeea114add2012-05-03 15:00:40 -070044 oatClobber(cUnit, res.lowReg);
45 if (cUnit->instructionSet == kMips) {
46 oatMarkInUse(cUnit, res.lowReg);
47 } else {
48 oatLockTemp(cUnit, res.lowReg);
49 }
50 return res;
buzbeee3acd072012-02-25 17:03:10 -080051}
52
buzbee3b3dbdd2012-06-13 13:39:34 -070053void genInvoke(CompilationUnit* cUnit, CallInfo* info)
buzbeee3acd072012-02-25 17:03:10 -080054{
buzbee15bf9802012-06-12 17:49:27 -070055 if (genIntrinsic(cUnit, info)) {
Bill Buzbeea114add2012-05-03 15:00:40 -070056 return;
57 }
buzbee15bf9802012-06-12 17:49:27 -070058 InvokeType originalType = info->type; // avoiding mutation by ComputeInvokeInfo
Bill Buzbeea114add2012-05-03 15:00:40 -070059 int callState = 0;
60 LIR* nullCk;
61 LIR** pNullCk = NULL;
62 NextCallInsn nextCallInsn;
63 oatFlushAllRegs(cUnit); /* Everything to home location */
64 // Explicit register usage
65 oatLockCallTemps(cUnit);
buzbeee3acd072012-02-25 17:03:10 -080066
Bill Buzbeea114add2012-05-03 15:00:40 -070067 OatCompilationUnit mUnit(cUnit->class_loader, cUnit->class_linker,
Ian Rogers00f7d0e2012-07-19 15:28:27 -070068 *cUnit->dex_file,
Bill Buzbeea114add2012-05-03 15:00:40 -070069 cUnit->code_item, cUnit->method_idx,
70 cUnit->access_flags);
Logan Chien4dd96f52012-02-29 01:26:58 +080071
buzbee3b3dbdd2012-06-13 13:39:34 -070072 uint32_t dexMethodIdx = info->index;
Bill Buzbeea114add2012-05-03 15:00:40 -070073 int vtableIdx;
74 uintptr_t directCode;
75 uintptr_t directMethod;
76 bool skipThis;
77 bool fastPath =
buzbee15bf9802012-06-12 17:49:27 -070078 cUnit->compiler->ComputeInvokeInfo(dexMethodIdx, &mUnit, info->type,
Bill Buzbeea114add2012-05-03 15:00:40 -070079 vtableIdx, directCode,
80 directMethod)
81 && !SLOW_INVOKE_PATH;
buzbee15bf9802012-06-12 17:49:27 -070082 if (info->type == kInterface) {
Ian Rogers137e88f2012-10-08 17:46:47 -070083 if (fastPath) {
84 pNullCk = &nullCk;
85 }
Bill Buzbeea114add2012-05-03 15:00:40 -070086 nextCallInsn = fastPath ? nextInterfaceCallInsn
Ian Rogers137e88f2012-10-08 17:46:47 -070087 : nextInterfaceCallInsnWithAccessCheck;
Bill Buzbeea114add2012-05-03 15:00:40 -070088 skipThis = false;
buzbee15bf9802012-06-12 17:49:27 -070089 } else if (info->type == kDirect) {
Bill Buzbeea114add2012-05-03 15:00:40 -070090 if (fastPath) {
91 pNullCk = &nullCk;
buzbeee3acd072012-02-25 17:03:10 -080092 }
Bill Buzbeea114add2012-05-03 15:00:40 -070093 nextCallInsn = fastPath ? nextSDCallInsn : nextDirectCallInsnSP;
94 skipThis = false;
buzbee15bf9802012-06-12 17:49:27 -070095 } else if (info->type == kStatic) {
Bill Buzbeea114add2012-05-03 15:00:40 -070096 nextCallInsn = fastPath ? nextSDCallInsn : nextStaticCallInsnSP;
97 skipThis = false;
buzbee15bf9802012-06-12 17:49:27 -070098 } else if (info->type == kSuper) {
Bill Buzbeea114add2012-05-03 15:00:40 -070099 DCHECK(!fastPath); // Fast path is a direct call.
100 nextCallInsn = nextSuperCallInsnSP;
101 skipThis = false;
102 } else {
buzbee15bf9802012-06-12 17:49:27 -0700103 DCHECK_EQ(info->type, kVirtual);
Bill Buzbeea114add2012-05-03 15:00:40 -0700104 nextCallInsn = fastPath ? nextVCallInsn : nextVCallInsnSP;
105 skipThis = fastPath;
106 }
buzbee15bf9802012-06-12 17:49:27 -0700107 if (!info->isRange) {
108 callState = genDalvikArgsNoRange(cUnit, info, callState, pNullCk,
Bill Buzbeea114add2012-05-03 15:00:40 -0700109 nextCallInsn, dexMethodIdx,
110 vtableIdx, directCode, directMethod,
111 originalType, skipThis);
112 } else {
buzbee15bf9802012-06-12 17:49:27 -0700113 callState = genDalvikArgsRange(cUnit, info, callState, pNullCk,
Bill Buzbeea114add2012-05-03 15:00:40 -0700114 nextCallInsn, dexMethodIdx, vtableIdx,
115 directCode, directMethod, originalType,
116 skipThis);
117 }
118 // Finish up any of the call sequence not interleaved in arg loading
119 while (callState >= 0) {
buzbee15bf9802012-06-12 17:49:27 -0700120 callState = nextCallInsn(cUnit, info, callState, dexMethodIdx,
Bill Buzbeea114add2012-05-03 15:00:40 -0700121 vtableIdx, directCode, directMethod,
122 originalType);
123 }
buzbeeb046e162012-10-30 15:48:42 -0700124 if (cUnit->enableDebug & (1 << kDebugDisplayMissingTargets)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700125 genShowTarget(cUnit);
126 }
buzbee8320f382012-09-11 16:29:42 -0700127 LIR* callInst;
buzbeeb046e162012-10-30 15:48:42 -0700128 if (cUnit->instructionSet != kX86) {
buzbeef0504cd2012-11-13 16:31:10 -0800129 callInst = opReg(cUnit, kOpBlx, targetReg(kInvokeTgt));
Bill Buzbeea114add2012-05-03 15:00:40 -0700130 } else {
buzbeeb046e162012-10-30 15:48:42 -0700131 if (fastPath && info->type != kInterface) {
buzbeef0504cd2012-11-13 16:31:10 -0800132 callInst = opMem(cUnit, kOpBlx, targetReg(kArg0),
133 AbstractMethod::GetCodeOffset().Int32Value());
buzbeeb046e162012-10-30 15:48:42 -0700134 } else {
135 int trampoline = 0;
136 switch (info->type) {
137 case kInterface:
138 trampoline = fastPath ? ENTRYPOINT_OFFSET(pInvokeInterfaceTrampoline)
139 : ENTRYPOINT_OFFSET(pInvokeInterfaceTrampolineWithAccessCheck);
140 break;
141 case kDirect:
142 trampoline = ENTRYPOINT_OFFSET(pInvokeDirectTrampolineWithAccessCheck);
143 break;
144 case kStatic:
145 trampoline = ENTRYPOINT_OFFSET(pInvokeStaticTrampolineWithAccessCheck);
146 break;
147 case kSuper:
148 trampoline = ENTRYPOINT_OFFSET(pInvokeSuperTrampolineWithAccessCheck);
149 break;
150 case kVirtual:
151 trampoline = ENTRYPOINT_OFFSET(pInvokeVirtualTrampolineWithAccessCheck);
152 break;
153 default:
154 LOG(FATAL) << "Unexpected invoke type";
155 }
156 callInst = opThreadMem(cUnit, kOpBlx, trampoline);
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700157 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700158 }
buzbee8320f382012-09-11 16:29:42 -0700159 markSafepointPC(cUnit, callInst);
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700160
Bill Buzbeea114add2012-05-03 15:00:40 -0700161 oatClobberCalleeSave(cUnit);
buzbee15bf9802012-06-12 17:49:27 -0700162 if (info->result.location != kLocInvalid) {
163 // We have a following MOVE_RESULT - do it now.
164 if (info->result.wide) {
buzbee52ed7762012-06-13 23:43:14 -0700165 RegLocation retLoc = oatGetReturnWide(cUnit, info->result.fp);
buzbee15bf9802012-06-12 17:49:27 -0700166 storeValueWide(cUnit, info->result, retLoc);
167 } else {
buzbee52ed7762012-06-13 23:43:14 -0700168 RegLocation retLoc = oatGetReturn(cUnit, info->result.fp);
buzbee15bf9802012-06-12 17:49:27 -0700169 storeValue(cUnit, info->result, retLoc);
170 }
171 }
172}
173
174/*
175 * Build an array of location records for the incoming arguments.
176 * Note: one location record per word of arguments, with dummy
177 * high-word loc for wide arguments. Also pull up any following
178 * MOVE_RESULT and incorporate it into the invoke.
179 */
buzbee6969d502012-06-15 16:40:31 -0700180CallInfo* oatNewCallInfo(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir,
181 InvokeType type, bool isRange)
buzbee15bf9802012-06-12 17:49:27 -0700182{
buzbee3b3dbdd2012-06-13 13:39:34 -0700183 CallInfo* info = (CallInfo*)oatNew(cUnit, sizeof(CallInfo), true,
buzbee15bf9802012-06-12 17:49:27 -0700184 kAllocMisc);
185 MIR* moveResultMIR = oatFindMoveResult(cUnit, bb, mir);
186 if (moveResultMIR == NULL) {
187 info->result.location = kLocInvalid;
188 } else {
189 info->result = oatGetRawDest(cUnit, moveResultMIR);
190 moveResultMIR->dalvikInsn.opcode = Instruction::NOP;
191 }
192 info->numArgWords = mir->ssaRep->numUses;
193 info->args = (info->numArgWords == 0) ? NULL : (RegLocation*)
194 oatNew(cUnit, sizeof(RegLocation) * info->numArgWords, false, kAllocMisc);
195 for (int i = 0; i < info->numArgWords; i++) {
196 info->args[i] = oatGetRawSrc(cUnit, mir, i);
197 }
198 info->optFlags = mir->optimizationFlags;
199 info->type = type;
200 info->isRange = isRange;
buzbee3b3dbdd2012-06-13 13:39:34 -0700201 info->index = mir->dalvikInsn.vB;
buzbee15bf9802012-06-12 17:49:27 -0700202 info->offset = mir->offset;
203 return info;
buzbeee3acd072012-02-25 17:03:10 -0800204}
205
206/*
207 * Target-independent code generation. Use only high-level
208 * load/store utilities here, or target-dependent genXX() handlers
209 * when necessary.
210 */
buzbee31a4a6f2012-02-28 15:36:15 -0800211bool compileDalvikInstruction(CompilationUnit* cUnit, MIR* mir,
212 BasicBlock* bb, LIR* labelList)
buzbeee3acd072012-02-25 17:03:10 -0800213{
Bill Buzbeea114add2012-05-03 15:00:40 -0700214 bool res = false; // Assume success
215 RegLocation rlSrc[3];
216 RegLocation rlDest = badLoc;
217 RegLocation rlResult = badLoc;
218 Instruction::Code opcode = mir->dalvikInsn.opcode;
buzbee408ad162012-06-06 16:45:18 -0700219 int optFlags = mir->optimizationFlags;
buzbee408ad162012-06-06 16:45:18 -0700220 uint32_t vB = mir->dalvikInsn.vB;
221 uint32_t vC = mir->dalvikInsn.vC;
buzbeee3acd072012-02-25 17:03:10 -0800222
Bill Buzbeea114add2012-05-03 15:00:40 -0700223 /* Prep Src and Dest locations */
224 int nextSreg = 0;
225 int nextLoc = 0;
226 int attrs = oatDataFlowAttributes[opcode];
227 rlSrc[0] = rlSrc[1] = rlSrc[2] = badLoc;
228 if (attrs & DF_UA) {
buzbeebff24652012-05-06 16:22:05 -0700229 if (attrs & DF_A_WIDE) {
buzbee15bf9802012-06-12 17:49:27 -0700230 rlSrc[nextLoc++] = oatGetSrcWide(cUnit, mir, nextSreg);
buzbeebff24652012-05-06 16:22:05 -0700231 nextSreg+= 2;
232 } else {
233 rlSrc[nextLoc++] = oatGetSrc(cUnit, mir, nextSreg);
234 nextSreg++;
235 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700236 }
237 if (attrs & DF_UB) {
buzbeebff24652012-05-06 16:22:05 -0700238 if (attrs & DF_B_WIDE) {
buzbee15bf9802012-06-12 17:49:27 -0700239 rlSrc[nextLoc++] = oatGetSrcWide(cUnit, mir, nextSreg);
buzbeebff24652012-05-06 16:22:05 -0700240 nextSreg+= 2;
241 } else {
242 rlSrc[nextLoc++] = oatGetSrc(cUnit, mir, nextSreg);
243 nextSreg++;
244 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700245 }
246 if (attrs & DF_UC) {
buzbeebff24652012-05-06 16:22:05 -0700247 if (attrs & DF_C_WIDE) {
buzbee15bf9802012-06-12 17:49:27 -0700248 rlSrc[nextLoc++] = oatGetSrcWide(cUnit, mir, nextSreg);
buzbeebff24652012-05-06 16:22:05 -0700249 } else {
250 rlSrc[nextLoc++] = oatGetSrc(cUnit, mir, nextSreg);
251 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700252 }
253 if (attrs & DF_DA) {
buzbeebff24652012-05-06 16:22:05 -0700254 if (attrs & DF_A_WIDE) {
buzbee15bf9802012-06-12 17:49:27 -0700255 rlDest = oatGetDestWide(cUnit, mir);
buzbeebff24652012-05-06 16:22:05 -0700256 } else {
buzbee15bf9802012-06-12 17:49:27 -0700257 rlDest = oatGetDest(cUnit, mir);
buzbeebff24652012-05-06 16:22:05 -0700258 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700259 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700260 switch (opcode) {
261 case Instruction::NOP:
262 break;
buzbeee3acd072012-02-25 17:03:10 -0800263
Ian Rogers474b6da2012-09-25 00:20:38 -0700264 case Instruction::MOVE_EXCEPTION:
265 genMoveException(cUnit, rlDest);
Bill Buzbeea114add2012-05-03 15:00:40 -0700266 break;
Bill Buzbeea114add2012-05-03 15:00:40 -0700267 case Instruction::RETURN_VOID:
TDYa1274f2935e2012-06-22 06:25:03 -0700268 if (!(cUnit->attrs & METHOD_IS_LEAF)) {
buzbee408ad162012-06-06 16:45:18 -0700269 genSuspendTest(cUnit, optFlags);
Bill Buzbeea114add2012-05-03 15:00:40 -0700270 }
271 break;
272
273 case Instruction::RETURN:
274 case Instruction::RETURN_OBJECT:
TDYa1274f2935e2012-06-22 06:25:03 -0700275 if (!(cUnit->attrs & METHOD_IS_LEAF)) {
buzbee408ad162012-06-06 16:45:18 -0700276 genSuspendTest(cUnit, optFlags);
Bill Buzbeea114add2012-05-03 15:00:40 -0700277 }
278 storeValue(cUnit, oatGetReturn(cUnit, cUnit->shorty[0] == 'F'), rlSrc[0]);
279 break;
280
281 case Instruction::RETURN_WIDE:
TDYa1274f2935e2012-06-22 06:25:03 -0700282 if (!(cUnit->attrs & METHOD_IS_LEAF)) {
buzbee408ad162012-06-06 16:45:18 -0700283 genSuspendTest(cUnit, optFlags);
Bill Buzbeea114add2012-05-03 15:00:40 -0700284 }
285 storeValueWide(cUnit, oatGetReturnWide(cUnit,
286 cUnit->shorty[0] == 'D'), rlSrc[0]);
287 break;
288
289 case Instruction::MOVE_RESULT_WIDE:
buzbee408ad162012-06-06 16:45:18 -0700290 if (optFlags & MIR_INLINED)
Bill Buzbeea114add2012-05-03 15:00:40 -0700291 break; // Nop - combined w/ previous invoke
292 storeValueWide(cUnit, rlDest, oatGetReturnWide(cUnit, rlDest.fp));
293 break;
294
295 case Instruction::MOVE_RESULT:
296 case Instruction::MOVE_RESULT_OBJECT:
buzbee408ad162012-06-06 16:45:18 -0700297 if (optFlags & MIR_INLINED)
Bill Buzbeea114add2012-05-03 15:00:40 -0700298 break; // Nop - combined w/ previous invoke
299 storeValue(cUnit, rlDest, oatGetReturn(cUnit, rlDest.fp));
300 break;
301
302 case Instruction::MOVE:
303 case Instruction::MOVE_OBJECT:
304 case Instruction::MOVE_16:
305 case Instruction::MOVE_OBJECT_16:
306 case Instruction::MOVE_FROM16:
307 case Instruction::MOVE_OBJECT_FROM16:
308 storeValue(cUnit, rlDest, rlSrc[0]);
309 break;
310
311 case Instruction::MOVE_WIDE:
312 case Instruction::MOVE_WIDE_16:
313 case Instruction::MOVE_WIDE_FROM16:
314 storeValueWide(cUnit, rlDest, rlSrc[0]);
315 break;
316
317 case Instruction::CONST:
318 case Instruction::CONST_4:
319 case Instruction::CONST_16:
320 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
buzbee408ad162012-06-06 16:45:18 -0700321 loadConstantNoClobber(cUnit, rlResult.lowReg, vB);
Bill Buzbeea114add2012-05-03 15:00:40 -0700322 storeValue(cUnit, rlDest, rlResult);
323 break;
324
325 case Instruction::CONST_HIGH16:
326 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
buzbee408ad162012-06-06 16:45:18 -0700327 loadConstantNoClobber(cUnit, rlResult.lowReg, vB << 16);
Bill Buzbeea114add2012-05-03 15:00:40 -0700328 storeValue(cUnit, rlDest, rlResult);
329 break;
330
331 case Instruction::CONST_WIDE_16:
332 case Instruction::CONST_WIDE_32:
333 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
buzbee408ad162012-06-06 16:45:18 -0700334 loadConstantValueWide(cUnit, rlResult.lowReg, rlResult.highReg, vB,
335 (vB & 0x80000000) ? -1 : 0);
Bill Buzbeea114add2012-05-03 15:00:40 -0700336 storeValueWide(cUnit, rlDest, rlResult);
337 break;
338
339 case Instruction::CONST_WIDE:
340 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
341 loadConstantValueWide(cUnit, rlResult.lowReg, rlResult.highReg,
342 mir->dalvikInsn.vB_wide & 0xffffffff,
343 (mir->dalvikInsn.vB_wide >> 32) & 0xffffffff);
344 storeValueWide(cUnit, rlDest, rlResult);
345 break;
346
347 case Instruction::CONST_WIDE_HIGH16:
348 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
349 loadConstantValueWide(cUnit, rlResult.lowReg, rlResult.highReg,
buzbee408ad162012-06-06 16:45:18 -0700350 0, vB << 16);
Bill Buzbeea114add2012-05-03 15:00:40 -0700351 storeValueWide(cUnit, rlDest, rlResult);
352 break;
353
354 case Instruction::MONITOR_ENTER:
buzbee408ad162012-06-06 16:45:18 -0700355 genMonitorEnter(cUnit, optFlags, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700356 break;
357
358 case Instruction::MONITOR_EXIT:
buzbee408ad162012-06-06 16:45:18 -0700359 genMonitorExit(cUnit, optFlags, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700360 break;
361
362 case Instruction::CHECK_CAST:
buzbee408ad162012-06-06 16:45:18 -0700363 genCheckCast(cUnit, vB, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700364 break;
365
366 case Instruction::INSTANCE_OF:
buzbee408ad162012-06-06 16:45:18 -0700367 genInstanceof(cUnit, vC, rlDest, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700368 break;
369
370 case Instruction::NEW_INSTANCE:
buzbee408ad162012-06-06 16:45:18 -0700371 genNewInstance(cUnit, vB, rlDest);
Bill Buzbeea114add2012-05-03 15:00:40 -0700372 break;
373
374 case Instruction::THROW:
buzbee408ad162012-06-06 16:45:18 -0700375 genThrow(cUnit, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700376 break;
377
Bill Buzbeea114add2012-05-03 15:00:40 -0700378 case Instruction::ARRAY_LENGTH:
379 int lenOffset;
380 lenOffset = Array::LengthOffset().Int32Value();
381 rlSrc[0] = loadValue(cUnit, rlSrc[0], kCoreReg);
buzbee408ad162012-06-06 16:45:18 -0700382 genNullCheck(cUnit, rlSrc[0].sRegLow, rlSrc[0].lowReg, optFlags);
Bill Buzbeea114add2012-05-03 15:00:40 -0700383 rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
384 loadWordDisp(cUnit, rlSrc[0].lowReg, lenOffset, rlResult.lowReg);
385 storeValue(cUnit, rlDest, rlResult);
386 break;
387
388 case Instruction::CONST_STRING:
389 case Instruction::CONST_STRING_JUMBO:
buzbee6969d502012-06-15 16:40:31 -0700390 genConstString(cUnit, vB, rlDest);
Bill Buzbeea114add2012-05-03 15:00:40 -0700391 break;
392
393 case Instruction::CONST_CLASS:
buzbee6969d502012-06-15 16:40:31 -0700394 genConstClass(cUnit, vB, rlDest);
Bill Buzbeea114add2012-05-03 15:00:40 -0700395 break;
396
397 case Instruction::FILL_ARRAY_DATA:
buzbee408ad162012-06-06 16:45:18 -0700398 genFillArrayData(cUnit, vB, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700399 break;
400
401 case Instruction::FILLED_NEW_ARRAY:
buzbee6969d502012-06-15 16:40:31 -0700402 genFilledNewArray(cUnit, oatNewCallInfo(cUnit, bb, mir, kStatic,
buzbee3b3dbdd2012-06-13 13:39:34 -0700403 false /* not range */));
Bill Buzbeea114add2012-05-03 15:00:40 -0700404 break;
405
406 case Instruction::FILLED_NEW_ARRAY_RANGE:
buzbee6969d502012-06-15 16:40:31 -0700407 genFilledNewArray(cUnit, oatNewCallInfo(cUnit, bb, mir, kStatic,
buzbee3b3dbdd2012-06-13 13:39:34 -0700408 true /* range */));
Bill Buzbeea114add2012-05-03 15:00:40 -0700409 break;
410
411 case Instruction::NEW_ARRAY:
buzbee408ad162012-06-06 16:45:18 -0700412 genNewArray(cUnit, vC, rlDest, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700413 break;
414
415 case Instruction::GOTO:
416 case Instruction::GOTO_16:
417 case Instruction::GOTO_32:
418 if (bb->taken->startOffset <= mir->offset) {
buzbee408ad162012-06-06 16:45:18 -0700419 genSuspendTestAndBranch(cUnit, optFlags, &labelList[bb->taken->id]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700420 } else {
421 opUnconditionalBranch(cUnit, &labelList[bb->taken->id]);
422 }
423 break;
424
425 case Instruction::PACKED_SWITCH:
buzbee408ad162012-06-06 16:45:18 -0700426 genPackedSwitch(cUnit, vB, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700427 break;
428
429 case Instruction::SPARSE_SWITCH:
buzbeea1da8a52012-07-09 14:00:21 -0700430 genSparseSwitch(cUnit, vB, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700431 break;
432
433 case Instruction::CMPL_FLOAT:
434 case Instruction::CMPG_FLOAT:
435 case Instruction::CMPL_DOUBLE:
436 case Instruction::CMPG_DOUBLE:
buzbee408ad162012-06-06 16:45:18 -0700437 res = genCmpFP(cUnit, opcode, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700438 break;
439
440 case Instruction::CMP_LONG:
buzbee408ad162012-06-06 16:45:18 -0700441 genCmpLong(cUnit, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700442 break;
443
444 case Instruction::IF_EQ:
445 case Instruction::IF_NE:
446 case Instruction::IF_LT:
447 case Instruction::IF_GE:
448 case Instruction::IF_GT:
449 case Instruction::IF_LE: {
buzbee3b3dbdd2012-06-13 13:39:34 -0700450 LIR* taken = &labelList[bb->taken->id];
451 LIR* fallThrough = &labelList[bb->fallThrough->id];
Bill Buzbeea114add2012-05-03 15:00:40 -0700452 bool backwardBranch;
453 backwardBranch = (bb->taken->startOffset <= mir->offset);
454 if (backwardBranch) {
buzbee408ad162012-06-06 16:45:18 -0700455 genSuspendTest(cUnit, optFlags);
Bill Buzbeea114add2012-05-03 15:00:40 -0700456 }
buzbee3b3dbdd2012-06-13 13:39:34 -0700457 genCompareAndBranch(cUnit, opcode, rlSrc[0], rlSrc[1], taken,
458 fallThrough);
Bill Buzbeea114add2012-05-03 15:00:40 -0700459 break;
460 }
461
462 case Instruction::IF_EQZ:
463 case Instruction::IF_NEZ:
464 case Instruction::IF_LTZ:
465 case Instruction::IF_GEZ:
466 case Instruction::IF_GTZ:
467 case Instruction::IF_LEZ: {
buzbee3b3dbdd2012-06-13 13:39:34 -0700468 LIR* taken = &labelList[bb->taken->id];
469 LIR* fallThrough = &labelList[bb->fallThrough->id];
Bill Buzbeea114add2012-05-03 15:00:40 -0700470 bool backwardBranch;
471 backwardBranch = (bb->taken->startOffset <= mir->offset);
472 if (backwardBranch) {
buzbee408ad162012-06-06 16:45:18 -0700473 genSuspendTest(cUnit, optFlags);
Bill Buzbeea114add2012-05-03 15:00:40 -0700474 }
buzbee3b3dbdd2012-06-13 13:39:34 -0700475 genCompareZeroAndBranch(cUnit, opcode, rlSrc[0], taken, fallThrough);
Bill Buzbeea114add2012-05-03 15:00:40 -0700476 break;
477 }
478
479 case Instruction::AGET_WIDE:
buzbee408ad162012-06-06 16:45:18 -0700480 genArrayGet(cUnit, optFlags, kLong, rlSrc[0], rlSrc[1], rlDest, 3);
Bill Buzbeea114add2012-05-03 15:00:40 -0700481 break;
482 case Instruction::AGET:
483 case Instruction::AGET_OBJECT:
buzbee408ad162012-06-06 16:45:18 -0700484 genArrayGet(cUnit, optFlags, kWord, rlSrc[0], rlSrc[1], rlDest, 2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700485 break;
486 case Instruction::AGET_BOOLEAN:
buzbee408ad162012-06-06 16:45:18 -0700487 genArrayGet(cUnit, optFlags, kUnsignedByte, rlSrc[0], rlSrc[1], rlDest, 0);
Bill Buzbeea114add2012-05-03 15:00:40 -0700488 break;
489 case Instruction::AGET_BYTE:
buzbee408ad162012-06-06 16:45:18 -0700490 genArrayGet(cUnit, optFlags, kSignedByte, rlSrc[0], rlSrc[1], rlDest, 0);
Bill Buzbeea114add2012-05-03 15:00:40 -0700491 break;
492 case Instruction::AGET_CHAR:
buzbee408ad162012-06-06 16:45:18 -0700493 genArrayGet(cUnit, optFlags, kUnsignedHalf, rlSrc[0], rlSrc[1], rlDest, 1);
Bill Buzbeea114add2012-05-03 15:00:40 -0700494 break;
495 case Instruction::AGET_SHORT:
buzbee408ad162012-06-06 16:45:18 -0700496 genArrayGet(cUnit, optFlags, kSignedHalf, rlSrc[0], rlSrc[1], rlDest, 1);
Bill Buzbeea114add2012-05-03 15:00:40 -0700497 break;
498 case Instruction::APUT_WIDE:
buzbee408ad162012-06-06 16:45:18 -0700499 genArrayPut(cUnit, optFlags, kLong, rlSrc[1], rlSrc[2], rlSrc[0], 3);
Bill Buzbeea114add2012-05-03 15:00:40 -0700500 break;
501 case Instruction::APUT:
buzbee408ad162012-06-06 16:45:18 -0700502 genArrayPut(cUnit, optFlags, kWord, rlSrc[1], rlSrc[2], rlSrc[0], 2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700503 break;
504 case Instruction::APUT_OBJECT:
buzbee408ad162012-06-06 16:45:18 -0700505 genArrayObjPut(cUnit, optFlags, rlSrc[1], rlSrc[2], rlSrc[0], 2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700506 break;
507 case Instruction::APUT_SHORT:
508 case Instruction::APUT_CHAR:
buzbee408ad162012-06-06 16:45:18 -0700509 genArrayPut(cUnit, optFlags, kUnsignedHalf, rlSrc[1], rlSrc[2], rlSrc[0], 1);
Bill Buzbeea114add2012-05-03 15:00:40 -0700510 break;
511 case Instruction::APUT_BYTE:
512 case Instruction::APUT_BOOLEAN:
buzbee408ad162012-06-06 16:45:18 -0700513 genArrayPut(cUnit, optFlags, kUnsignedByte, rlSrc[1], rlSrc[2],
Bill Buzbeea114add2012-05-03 15:00:40 -0700514 rlSrc[0], 0);
515 break;
516
517 case Instruction::IGET_OBJECT:
518 //case Instruction::IGET_OBJECT_VOLATILE:
buzbee408ad162012-06-06 16:45:18 -0700519 genIGet(cUnit, vC, optFlags, kWord, rlDest, rlSrc[0], false, true);
Bill Buzbeea114add2012-05-03 15:00:40 -0700520 break;
521
522 case Instruction::IGET_WIDE:
523 //case Instruction::IGET_WIDE_VOLATILE:
buzbee408ad162012-06-06 16:45:18 -0700524 genIGet(cUnit, vC, optFlags, kLong, rlDest, rlSrc[0], true, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700525 break;
526
527 case Instruction::IGET:
528 //case Instruction::IGET_VOLATILE:
buzbee408ad162012-06-06 16:45:18 -0700529 genIGet(cUnit, vC, optFlags, kWord, rlDest, rlSrc[0], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700530 break;
531
532 case Instruction::IGET_CHAR:
buzbee408ad162012-06-06 16:45:18 -0700533 genIGet(cUnit, vC, optFlags, kUnsignedHalf, rlDest, rlSrc[0], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700534 break;
535
536 case Instruction::IGET_SHORT:
buzbee408ad162012-06-06 16:45:18 -0700537 genIGet(cUnit, vC, optFlags, kSignedHalf, rlDest, rlSrc[0], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700538 break;
539
540 case Instruction::IGET_BOOLEAN:
541 case Instruction::IGET_BYTE:
buzbee408ad162012-06-06 16:45:18 -0700542 genIGet(cUnit, vC, optFlags, kUnsignedByte, rlDest, rlSrc[0], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700543 break;
544
545 case Instruction::IPUT_WIDE:
546 //case Instruction::IPUT_WIDE_VOLATILE:
buzbee408ad162012-06-06 16:45:18 -0700547 genIPut(cUnit, vC, optFlags, kLong, rlSrc[0], rlSrc[1], true, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700548 break;
549
550 case Instruction::IPUT_OBJECT:
551 //case Instruction::IPUT_OBJECT_VOLATILE:
buzbee408ad162012-06-06 16:45:18 -0700552 genIPut(cUnit, vC, optFlags, kWord, rlSrc[0], rlSrc[1], false, true);
Bill Buzbeea114add2012-05-03 15:00:40 -0700553 break;
554
555 case Instruction::IPUT:
556 //case Instruction::IPUT_VOLATILE:
buzbee408ad162012-06-06 16:45:18 -0700557 genIPut(cUnit, vC, optFlags, kWord, rlSrc[0], rlSrc[1], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700558 break;
559
560 case Instruction::IPUT_BOOLEAN:
561 case Instruction::IPUT_BYTE:
buzbee408ad162012-06-06 16:45:18 -0700562 genIPut(cUnit, vC, optFlags, kUnsignedByte, rlSrc[0], rlSrc[1], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700563 break;
564
565 case Instruction::IPUT_CHAR:
buzbee408ad162012-06-06 16:45:18 -0700566 genIPut(cUnit, vC, optFlags, kUnsignedHalf, rlSrc[0], rlSrc[1], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700567 break;
568
569 case Instruction::IPUT_SHORT:
buzbee408ad162012-06-06 16:45:18 -0700570 genIPut(cUnit, vC, optFlags, kSignedHalf, rlSrc[0], rlSrc[1], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700571 break;
572
573 case Instruction::SGET_OBJECT:
buzbee408ad162012-06-06 16:45:18 -0700574 genSget(cUnit, vB, rlDest, false, true);
Bill Buzbeea114add2012-05-03 15:00:40 -0700575 break;
576 case Instruction::SGET:
577 case Instruction::SGET_BOOLEAN:
578 case Instruction::SGET_BYTE:
579 case Instruction::SGET_CHAR:
580 case Instruction::SGET_SHORT:
buzbee408ad162012-06-06 16:45:18 -0700581 genSget(cUnit, vB, rlDest, false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700582 break;
583
584 case Instruction::SGET_WIDE:
buzbee408ad162012-06-06 16:45:18 -0700585 genSget(cUnit, vB, rlDest, true, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700586 break;
587
588 case Instruction::SPUT_OBJECT:
buzbee408ad162012-06-06 16:45:18 -0700589 genSput(cUnit, vB, rlSrc[0], false, true);
Bill Buzbeea114add2012-05-03 15:00:40 -0700590 break;
591
592 case Instruction::SPUT:
593 case Instruction::SPUT_BOOLEAN:
594 case Instruction::SPUT_BYTE:
595 case Instruction::SPUT_CHAR:
596 case Instruction::SPUT_SHORT:
buzbee408ad162012-06-06 16:45:18 -0700597 genSput(cUnit, vB, rlSrc[0], false, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700598 break;
599
600 case Instruction::SPUT_WIDE:
buzbee408ad162012-06-06 16:45:18 -0700601 genSput(cUnit, vB, rlSrc[0], true, false);
Bill Buzbeea114add2012-05-03 15:00:40 -0700602 break;
603
604 case Instruction::INVOKE_STATIC_RANGE:
buzbee6969d502012-06-15 16:40:31 -0700605 genInvoke(cUnit, oatNewCallInfo(cUnit, bb, mir, kStatic, true));
Bill Buzbeea114add2012-05-03 15:00:40 -0700606 break;
607 case Instruction::INVOKE_STATIC:
buzbee6969d502012-06-15 16:40:31 -0700608 genInvoke(cUnit, oatNewCallInfo(cUnit, bb, mir, kStatic, false));
Bill Buzbeea114add2012-05-03 15:00:40 -0700609 break;
610
611 case Instruction::INVOKE_DIRECT:
buzbee6969d502012-06-15 16:40:31 -0700612 genInvoke(cUnit, oatNewCallInfo(cUnit, bb, mir, kDirect, false));
Bill Buzbeea114add2012-05-03 15:00:40 -0700613 break;
614 case Instruction::INVOKE_DIRECT_RANGE:
buzbee6969d502012-06-15 16:40:31 -0700615 genInvoke(cUnit, oatNewCallInfo(cUnit, bb, mir, kDirect, true));
Bill Buzbeea114add2012-05-03 15:00:40 -0700616 break;
617
618 case Instruction::INVOKE_VIRTUAL:
buzbee6969d502012-06-15 16:40:31 -0700619 genInvoke(cUnit, oatNewCallInfo(cUnit, bb, mir, kVirtual, false));
Bill Buzbeea114add2012-05-03 15:00:40 -0700620 break;
621 case Instruction::INVOKE_VIRTUAL_RANGE:
buzbee6969d502012-06-15 16:40:31 -0700622 genInvoke(cUnit, oatNewCallInfo(cUnit, bb, mir, kVirtual, true));
Bill Buzbeea114add2012-05-03 15:00:40 -0700623 break;
624
625 case Instruction::INVOKE_SUPER:
buzbee6969d502012-06-15 16:40:31 -0700626 genInvoke(cUnit, oatNewCallInfo(cUnit, bb, mir, kSuper, false));
Bill Buzbeea114add2012-05-03 15:00:40 -0700627 break;
628 case Instruction::INVOKE_SUPER_RANGE:
buzbee6969d502012-06-15 16:40:31 -0700629 genInvoke(cUnit, oatNewCallInfo(cUnit, bb, mir, kSuper, true));
Bill Buzbeea114add2012-05-03 15:00:40 -0700630 break;
631
632 case Instruction::INVOKE_INTERFACE:
buzbee6969d502012-06-15 16:40:31 -0700633 genInvoke(cUnit, oatNewCallInfo(cUnit, bb, mir, kInterface, false));
Bill Buzbeea114add2012-05-03 15:00:40 -0700634 break;
635 case Instruction::INVOKE_INTERFACE_RANGE:
buzbee6969d502012-06-15 16:40:31 -0700636 genInvoke(cUnit, oatNewCallInfo(cUnit, bb, mir, kInterface, true));
Bill Buzbeea114add2012-05-03 15:00:40 -0700637 break;
638
639 case Instruction::NEG_INT:
640 case Instruction::NOT_INT:
buzbee408ad162012-06-06 16:45:18 -0700641 res = genArithOpInt(cUnit, opcode, rlDest, rlSrc[0], rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700642 break;
643
644 case Instruction::NEG_LONG:
645 case Instruction::NOT_LONG:
buzbee408ad162012-06-06 16:45:18 -0700646 res = genArithOpLong(cUnit, opcode, rlDest, rlSrc[0], rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700647 break;
648
649 case Instruction::NEG_FLOAT:
buzbee408ad162012-06-06 16:45:18 -0700650 res = genArithOpFloat(cUnit, opcode, rlDest, rlSrc[0], rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700651 break;
652
653 case Instruction::NEG_DOUBLE:
buzbee408ad162012-06-06 16:45:18 -0700654 res = genArithOpDouble(cUnit, opcode, rlDest, rlSrc[0], rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700655 break;
656
657 case Instruction::INT_TO_LONG:
buzbee408ad162012-06-06 16:45:18 -0700658 genIntToLong(cUnit, rlDest, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700659 break;
660
661 case Instruction::LONG_TO_INT:
662 rlSrc[0] = oatUpdateLocWide(cUnit, rlSrc[0]);
663 rlSrc[0] = oatWideToNarrow(cUnit, rlSrc[0]);
664 storeValue(cUnit, rlDest, rlSrc[0]);
665 break;
666
667 case Instruction::INT_TO_BYTE:
668 case Instruction::INT_TO_SHORT:
669 case Instruction::INT_TO_CHAR:
buzbee408ad162012-06-06 16:45:18 -0700670 genIntNarrowing(cUnit, opcode, rlDest, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700671 break;
672
673 case Instruction::INT_TO_FLOAT:
674 case Instruction::INT_TO_DOUBLE:
675 case Instruction::LONG_TO_FLOAT:
676 case Instruction::LONG_TO_DOUBLE:
677 case Instruction::FLOAT_TO_INT:
678 case Instruction::FLOAT_TO_LONG:
679 case Instruction::FLOAT_TO_DOUBLE:
680 case Instruction::DOUBLE_TO_INT:
681 case Instruction::DOUBLE_TO_LONG:
682 case Instruction::DOUBLE_TO_FLOAT:
buzbee408ad162012-06-06 16:45:18 -0700683 genConversion(cUnit, opcode, rlDest, rlSrc[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700684 break;
685
686 case Instruction::ADD_INT:
687 case Instruction::SUB_INT:
688 case Instruction::MUL_INT:
689 case Instruction::DIV_INT:
690 case Instruction::REM_INT:
691 case Instruction::AND_INT:
692 case Instruction::OR_INT:
693 case Instruction::XOR_INT:
694 case Instruction::SHL_INT:
695 case Instruction::SHR_INT:
696 case Instruction::USHR_INT:
697 case Instruction::ADD_INT_2ADDR:
698 case Instruction::SUB_INT_2ADDR:
699 case Instruction::MUL_INT_2ADDR:
700 case Instruction::DIV_INT_2ADDR:
701 case Instruction::REM_INT_2ADDR:
702 case Instruction::AND_INT_2ADDR:
703 case Instruction::OR_INT_2ADDR:
704 case Instruction::XOR_INT_2ADDR:
705 case Instruction::SHL_INT_2ADDR:
706 case Instruction::SHR_INT_2ADDR:
707 case Instruction::USHR_INT_2ADDR:
buzbee408ad162012-06-06 16:45:18 -0700708 genArithOpInt(cUnit, opcode, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700709 break;
710
711 case Instruction::ADD_LONG:
712 case Instruction::SUB_LONG:
713 case Instruction::MUL_LONG:
714 case Instruction::DIV_LONG:
715 case Instruction::REM_LONG:
716 case Instruction::AND_LONG:
717 case Instruction::OR_LONG:
718 case Instruction::XOR_LONG:
719 case Instruction::ADD_LONG_2ADDR:
720 case Instruction::SUB_LONG_2ADDR:
721 case Instruction::MUL_LONG_2ADDR:
722 case Instruction::DIV_LONG_2ADDR:
723 case Instruction::REM_LONG_2ADDR:
724 case Instruction::AND_LONG_2ADDR:
725 case Instruction::OR_LONG_2ADDR:
726 case Instruction::XOR_LONG_2ADDR:
buzbee408ad162012-06-06 16:45:18 -0700727 genArithOpLong(cUnit, opcode, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700728 break;
729
730 case Instruction::SHL_LONG:
731 case Instruction::SHR_LONG:
732 case Instruction::USHR_LONG:
733 case Instruction::SHL_LONG_2ADDR:
734 case Instruction::SHR_LONG_2ADDR:
735 case Instruction::USHR_LONG_2ADDR:
buzbee408ad162012-06-06 16:45:18 -0700736 genShiftOpLong(cUnit, opcode, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700737 break;
738
739 case Instruction::ADD_FLOAT:
740 case Instruction::SUB_FLOAT:
741 case Instruction::MUL_FLOAT:
742 case Instruction::DIV_FLOAT:
743 case Instruction::REM_FLOAT:
744 case Instruction::ADD_FLOAT_2ADDR:
745 case Instruction::SUB_FLOAT_2ADDR:
746 case Instruction::MUL_FLOAT_2ADDR:
747 case Instruction::DIV_FLOAT_2ADDR:
748 case Instruction::REM_FLOAT_2ADDR:
buzbee408ad162012-06-06 16:45:18 -0700749 genArithOpFloat(cUnit, opcode, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700750 break;
751
752 case Instruction::ADD_DOUBLE:
753 case Instruction::SUB_DOUBLE:
754 case Instruction::MUL_DOUBLE:
755 case Instruction::DIV_DOUBLE:
756 case Instruction::REM_DOUBLE:
757 case Instruction::ADD_DOUBLE_2ADDR:
758 case Instruction::SUB_DOUBLE_2ADDR:
759 case Instruction::MUL_DOUBLE_2ADDR:
760 case Instruction::DIV_DOUBLE_2ADDR:
761 case Instruction::REM_DOUBLE_2ADDR:
buzbee408ad162012-06-06 16:45:18 -0700762 genArithOpDouble(cUnit, opcode, rlDest, rlSrc[0], rlSrc[1]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700763 break;
764
765 case Instruction::RSUB_INT:
766 case Instruction::ADD_INT_LIT16:
767 case Instruction::MUL_INT_LIT16:
768 case Instruction::DIV_INT_LIT16:
769 case Instruction::REM_INT_LIT16:
770 case Instruction::AND_INT_LIT16:
771 case Instruction::OR_INT_LIT16:
772 case Instruction::XOR_INT_LIT16:
773 case Instruction::ADD_INT_LIT8:
774 case Instruction::RSUB_INT_LIT8:
775 case Instruction::MUL_INT_LIT8:
776 case Instruction::DIV_INT_LIT8:
777 case Instruction::REM_INT_LIT8:
778 case Instruction::AND_INT_LIT8:
779 case Instruction::OR_INT_LIT8:
780 case Instruction::XOR_INT_LIT8:
781 case Instruction::SHL_INT_LIT8:
782 case Instruction::SHR_INT_LIT8:
783 case Instruction::USHR_INT_LIT8:
buzbee408ad162012-06-06 16:45:18 -0700784 genArithOpIntLit(cUnit, opcode, rlDest, rlSrc[0], vC);
Bill Buzbeea114add2012-05-03 15:00:40 -0700785 break;
786
787 default:
788 res = true;
789 }
790 return res;
buzbeee3acd072012-02-25 17:03:10 -0800791}
792
buzbee31a4a6f2012-02-28 15:36:15 -0800793const char* extendedMIROpNames[kMirOpLast - kMirOpFirst] = {
Bill Buzbeea114add2012-05-03 15:00:40 -0700794 "kMirOpPhi",
795 "kMirOpCopy",
796 "kMirFusedCmplFloat",
797 "kMirFusedCmpgFloat",
798 "kMirFusedCmplDouble",
799 "kMirFusedCmpgDouble",
800 "kMirFusedCmpLong",
801 "kMirNop",
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700802 "kMirOpNullCheck",
803 "kMirOpRangeCheck",
804 "kMirOpDivZeroCheck",
805 "kMirOpCheck",
buzbeee3acd072012-02-25 17:03:10 -0800806};
807
808/* Extended MIR instructions like PHI */
buzbee84fd6932012-03-29 16:44:16 -0700809void handleExtendedMethodMIR(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir)
buzbeee3acd072012-02-25 17:03:10 -0800810{
Bill Buzbeea114add2012-05-03 15:00:40 -0700811 int opOffset = mir->dalvikInsn.opcode - kMirOpFirst;
812 char* msg = NULL;
813 if (cUnit->printMe) {
814 msg = (char*)oatNew(cUnit, strlen(extendedMIROpNames[opOffset]) + 1,
815 false, kAllocDebugInfo);
816 strcpy(msg, extendedMIROpNames[opOffset]);
817 }
818 LIR* op = newLIR1(cUnit, kPseudoExtended, (int) msg);
buzbeee3acd072012-02-25 17:03:10 -0800819
Bill Buzbeea114add2012-05-03 15:00:40 -0700820 switch ((ExtendedMIROpcode)mir->dalvikInsn.opcode) {
821 case kMirOpPhi: {
822 char* ssaString = NULL;
823 if (cUnit->printMe) {
824 ssaString = oatGetSSAString(cUnit, mir->ssaRep);
825 }
826 op->flags.isNop = true;
827 newLIR1(cUnit, kPseudoSSARep, (int) ssaString);
828 break;
buzbeee3acd072012-02-25 17:03:10 -0800829 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700830 case kMirOpCopy: {
831 RegLocation rlSrc = oatGetSrc(cUnit, mir, 0);
buzbee15bf9802012-06-12 17:49:27 -0700832 RegLocation rlDest = oatGetDest(cUnit, mir);
Bill Buzbeea114add2012-05-03 15:00:40 -0700833 storeValue(cUnit, rlDest, rlSrc);
834 break;
835 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700836 case kMirOpFusedCmplFloat:
837 genFusedFPCmpBranch(cUnit, bb, mir, false /*gt bias*/, false /*double*/);
838 break;
839 case kMirOpFusedCmpgFloat:
840 genFusedFPCmpBranch(cUnit, bb, mir, true /*gt bias*/, false /*double*/);
841 break;
842 case kMirOpFusedCmplDouble:
843 genFusedFPCmpBranch(cUnit, bb, mir, false /*gt bias*/, true /*double*/);
844 break;
845 case kMirOpFusedCmpgDouble:
846 genFusedFPCmpBranch(cUnit, bb, mir, true /*gt bias*/, true /*double*/);
847 break;
848 case kMirOpFusedCmpLong:
849 genFusedLongCmpBranch(cUnit, bb, mir);
850 break;
Bill Buzbeea114add2012-05-03 15:00:40 -0700851 default:
852 break;
853 }
buzbeee3acd072012-02-25 17:03:10 -0800854}
855
856/* Handle the content in each basic block */
buzbee31a4a6f2012-02-28 15:36:15 -0800857bool methodBlockCodeGen(CompilationUnit* cUnit, BasicBlock* bb)
buzbeee3acd072012-02-25 17:03:10 -0800858{
buzbee488a78c2012-09-10 15:55:34 -0700859 if (bb->blockType == kDead) return false;
buzbee8320f382012-09-11 16:29:42 -0700860 cUnit->currentDalvikOffset = bb->startOffset;
Bill Buzbeea114add2012-05-03 15:00:40 -0700861 MIR* mir;
buzbeea1da8a52012-07-09 14:00:21 -0700862 LIR* labelList = cUnit->blockLabelList;
Bill Buzbeea114add2012-05-03 15:00:40 -0700863 int blockId = bb->id;
buzbeee3acd072012-02-25 17:03:10 -0800864
Bill Buzbeea114add2012-05-03 15:00:40 -0700865 cUnit->curBlock = bb;
866 labelList[blockId].operands[0] = bb->startOffset;
buzbeee3acd072012-02-25 17:03:10 -0800867
Bill Buzbeea114add2012-05-03 15:00:40 -0700868 /* Insert the block label */
869 labelList[blockId].opcode = kPseudoNormalBlockLabel;
870 oatAppendLIR(cUnit, (LIR*) &labelList[blockId]);
buzbeee3acd072012-02-25 17:03:10 -0800871
buzbee8320f382012-09-11 16:29:42 -0700872 LIR* headLIR = NULL;
873
Bill Buzbeea5b30242012-09-28 07:19:44 -0700874 /* If this is a catch block, export the start address */
buzbee8320f382012-09-11 16:29:42 -0700875 if (bb->catchEntry) {
Bill Buzbeea5b30242012-09-28 07:19:44 -0700876 headLIR = newLIR0(cUnit, kPseudoExportedPC);
buzbee8320f382012-09-11 16:29:42 -0700877 }
878
Bill Buzbeea114add2012-05-03 15:00:40 -0700879 /* Free temp registers and reset redundant store tracking */
880 oatResetRegPool(cUnit);
881 oatResetDefTracking(cUnit);
882
buzbeed1643e42012-09-05 14:06:51 -0700883 oatClobberAllRegs(cUnit);
Bill Buzbeea114add2012-05-03 15:00:40 -0700884
Bill Buzbeea114add2012-05-03 15:00:40 -0700885
886 if (bb->blockType == kEntryBlock) {
buzbeead8f15e2012-06-18 14:49:45 -0700887 int startVReg = cUnit->numDalvikRegisters - cUnit->numIns;
888 genEntrySequence(cUnit, &cUnit->regLocation[startVReg],
889 cUnit->regLocation[cUnit->methodSReg]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700890 } else if (bb->blockType == kExitBlock) {
buzbee2cfc6392012-05-07 14:51:40 -0700891 genExitSequence(cUnit);
Bill Buzbeea114add2012-05-03 15:00:40 -0700892 }
893
894 for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
buzbeee3acd072012-02-25 17:03:10 -0800895 oatResetRegPool(cUnit);
Bill Buzbeea114add2012-05-03 15:00:40 -0700896 if (cUnit->disableOpt & (1 << kTrackLiveTemps)) {
897 oatClobberAllRegs(cUnit);
buzbeee1965672012-03-11 18:39:19 -0700898 }
899
Bill Buzbeea114add2012-05-03 15:00:40 -0700900 if (cUnit->disableOpt & (1 << kSuppressLoads)) {
901 oatResetDefTracking(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800902 }
903
buzbee3d661942012-03-14 17:37:27 -0700904#ifndef NDEBUG
Bill Buzbeea114add2012-05-03 15:00:40 -0700905 /* Reset temp tracking sanity check */
906 cUnit->liveSReg = INVALID_SREG;
buzbee3d661942012-03-14 17:37:27 -0700907#endif
908
Bill Buzbeea114add2012-05-03 15:00:40 -0700909 cUnit->currentDalvikOffset = mir->offset;
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700910 int opcode = mir->dalvikInsn.opcode;
Bill Buzbeea114add2012-05-03 15:00:40 -0700911 LIR* boundaryLIR;
buzbeee3acd072012-02-25 17:03:10 -0800912
Bill Buzbeea114add2012-05-03 15:00:40 -0700913 /* Mark the beginning of a Dalvik instruction for line tracking */
914 char* instStr = cUnit->printMe ?
915 oatGetDalvikDisassembly(cUnit, mir->dalvikInsn, "") : NULL;
buzbeed1643e42012-09-05 14:06:51 -0700916 boundaryLIR = markBoundary(cUnit, mir->offset, instStr);
Bill Buzbeea114add2012-05-03 15:00:40 -0700917 /* Remember the first LIR for this block */
918 if (headLIR == NULL) {
919 headLIR = boundaryLIR;
920 /* Set the first boundaryLIR as a scheduling barrier */
921 headLIR->defMask = ENCODE_ALL;
buzbeee3acd072012-02-25 17:03:10 -0800922 }
923
Bill Buzbeea114add2012-05-03 15:00:40 -0700924 /* Don't generate the SSA annotation unless verbose mode is on */
925 if (cUnit->printMe && mir->ssaRep) {
926 char* ssaString = oatGetSSAString(cUnit, mir->ssaRep);
927 newLIR1(cUnit, kPseudoSSARep, (int) ssaString);
928 }
929
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700930 if (opcode == kMirOpCheck) {
931 // Combine check and work halves of throwing instruction.
932 MIR* workHalf = mir->meta.throwInsn;
933 mir->dalvikInsn.opcode = workHalf->dalvikInsn.opcode;
934 opcode = workHalf->dalvikInsn.opcode;
935 SSARepresentation* ssaRep = workHalf->ssaRep;
936 workHalf->ssaRep = mir->ssaRep;
937 mir->ssaRep = ssaRep;
938 workHalf->dalvikInsn.opcode = static_cast<Instruction::Code>(kMirOpNop);
939 }
940
941 if (opcode >= kMirOpFirst) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700942 handleExtendedMethodMIR(cUnit, bb, mir);
943 continue;
944 }
945
946 bool notHandled = compileDalvikInstruction(cUnit, mir, bb, labelList);
947 if (notHandled) {
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700948 LOG(FATAL) << StringPrintf("%#06x: Opcode %#x (%s)",
949 mir->offset, opcode,
950 Instruction::Name(mir->dalvikInsn.opcode));
Bill Buzbeea114add2012-05-03 15:00:40 -0700951 }
952 }
953
954 if (headLIR) {
955 /*
956 * Eliminate redundant loads/stores and delay stores into later
957 * slots
958 */
959 oatApplyLocalOptimizations(cUnit, (LIR*) headLIR, cUnit->lastLIRInsn);
960
961 /*
962 * Generate an unconditional branch to the fallthrough block.
963 */
964 if (bb->fallThrough) {
965 opUnconditionalBranch(cUnit, &labelList[bb->fallThrough->id]);
966 }
967 }
968 return false;
buzbeee3acd072012-02-25 17:03:10 -0800969}
970
buzbee16da88c2012-03-20 10:38:17 -0700971/* Set basic block labels */
972bool labelBlocks(CompilationUnit* cUnit, BasicBlock* bb)
973{
buzbeea1da8a52012-07-09 14:00:21 -0700974 LIR* labelList = cUnit->blockLabelList;
Bill Buzbeea114add2012-05-03 15:00:40 -0700975 int blockId = bb->id;
buzbee16da88c2012-03-20 10:38:17 -0700976
Bill Buzbeea114add2012-05-03 15:00:40 -0700977 cUnit->curBlock = bb;
978 labelList[blockId].operands[0] = bb->startOffset;
buzbee16da88c2012-03-20 10:38:17 -0700979
Bill Buzbeea114add2012-05-03 15:00:40 -0700980 /* Insert the block label */
981 labelList[blockId].opcode = kPseudoNormalBlockLabel;
982 return false;
buzbee16da88c2012-03-20 10:38:17 -0700983}
984
985void oatSpecialMIR2LIR(CompilationUnit* cUnit, SpecialCaseHandler specialCase)
986{
Bill Buzbeea114add2012-05-03 15:00:40 -0700987 /* Find the first DalvikByteCode block */
988 int numReachableBlocks = cUnit->numReachableBlocks;
989 const GrowableList *blockList = &cUnit->blockList;
990 BasicBlock*bb = NULL;
991 for (int idx = 0; idx < numReachableBlocks; idx++) {
992 int dfsIndex = cUnit->dfsOrder.elemList[idx];
993 bb = (BasicBlock*)oatGrowableListGetElement(blockList, dfsIndex);
994 if (bb->blockType == kDalvikByteCode) {
995 break;
buzbee16da88c2012-03-20 10:38:17 -0700996 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700997 }
998 if (bb == NULL) {
999 return;
1000 }
1001 DCHECK_EQ(bb->startOffset, 0);
Elliott Hughes74847412012-06-20 18:10:21 -07001002 DCHECK(bb->firstMIRInsn != NULL);
buzbee16da88c2012-03-20 10:38:17 -07001003
Bill Buzbeea114add2012-05-03 15:00:40 -07001004 /* Get the first instruction */
1005 MIR* mir = bb->firstMIRInsn;
buzbee16da88c2012-03-20 10:38:17 -07001006
Bill Buzbeea114add2012-05-03 15:00:40 -07001007 /* Free temp registers and reset redundant store tracking */
1008 oatResetRegPool(cUnit);
1009 oatResetDefTracking(cUnit);
1010 oatClobberAllRegs(cUnit);
buzbee16da88c2012-03-20 10:38:17 -07001011
Bill Buzbeea114add2012-05-03 15:00:40 -07001012 genSpecialCase(cUnit, bb, mir, specialCase);
buzbee16da88c2012-03-20 10:38:17 -07001013}
1014
buzbeee3acd072012-02-25 17:03:10 -08001015void oatMethodMIR2LIR(CompilationUnit* cUnit)
1016{
Bill Buzbeea114add2012-05-03 15:00:40 -07001017 /* Used to hold the labels of each block */
1018 cUnit->blockLabelList =
buzbeea1da8a52012-07-09 14:00:21 -07001019 (LIR*) oatNew(cUnit, sizeof(LIR) * cUnit->numBlocks, true, kAllocLIR);
buzbeee3acd072012-02-25 17:03:10 -08001020
Bill Buzbeea114add2012-05-03 15:00:40 -07001021 oatDataFlowAnalysisDispatcher(cUnit, methodBlockCodeGen,
1022 kPreOrderDFSTraversal, false /* Iterative */);
Ian Rogersab2b55d2012-03-18 00:06:11 -07001023
Bill Buzbeea114add2012-05-03 15:00:40 -07001024 handleSuspendLaunchpads(cUnit);
buzbeee3acd072012-02-25 17:03:10 -08001025
Bill Buzbeea114add2012-05-03 15:00:40 -07001026 handleThrowLaunchpads(cUnit);
buzbeee3acd072012-02-25 17:03:10 -08001027
Bill Buzbeea114add2012-05-03 15:00:40 -07001028 handleIntrinsicLaunchpads(cUnit);
buzbeefc9e6fa2012-03-23 15:14:29 -07001029
Bill Buzbeea114add2012-05-03 15:00:40 -07001030 if (!(cUnit->disableOpt & (1 << kSafeOptimizations))) {
1031 removeRedundantBranches(cUnit);
1032 }
buzbeee3acd072012-02-25 17:03:10 -08001033}
1034
1035/* Needed by the ld/st optmizatons */
buzbee31a4a6f2012-02-28 15:36:15 -08001036LIR* oatRegCopyNoInsert(CompilationUnit* cUnit, int rDest, int rSrc)
buzbeee3acd072012-02-25 17:03:10 -08001037{
Bill Buzbeea114add2012-05-03 15:00:40 -07001038 return opRegCopyNoInsert(cUnit, rDest, rSrc);
buzbeee3acd072012-02-25 17:03:10 -08001039}
1040
1041/* Needed by the register allocator */
1042void oatRegCopy(CompilationUnit* cUnit, int rDest, int rSrc)
1043{
Bill Buzbeea114add2012-05-03 15:00:40 -07001044 opRegCopy(cUnit, rDest, rSrc);
buzbeee3acd072012-02-25 17:03:10 -08001045}
1046
1047/* Needed by the register allocator */
1048void oatRegCopyWide(CompilationUnit* cUnit, int destLo, int destHi,
Bill Buzbeea114add2012-05-03 15:00:40 -07001049 int srcLo, int srcHi)
buzbeee3acd072012-02-25 17:03:10 -08001050{
Bill Buzbeea114add2012-05-03 15:00:40 -07001051 opRegCopyWide(cUnit, destLo, destHi, srcLo, srcHi);
buzbeee3acd072012-02-25 17:03:10 -08001052}
1053
1054void oatFlushRegImpl(CompilationUnit* cUnit, int rBase,
Bill Buzbeea114add2012-05-03 15:00:40 -07001055 int displacement, int rSrc, OpSize size)
buzbeee3acd072012-02-25 17:03:10 -08001056{
Bill Buzbeea114add2012-05-03 15:00:40 -07001057 storeBaseDisp(cUnit, rBase, displacement, rSrc, size);
buzbeee3acd072012-02-25 17:03:10 -08001058}
1059
1060void oatFlushRegWideImpl(CompilationUnit* cUnit, int rBase,
Bill Buzbeea114add2012-05-03 15:00:40 -07001061 int displacement, int rSrcLo, int rSrcHi)
buzbeee3acd072012-02-25 17:03:10 -08001062{
Bill Buzbeea114add2012-05-03 15:00:40 -07001063 storeBaseDispWide(cUnit, rBase, displacement, rSrcLo, rSrcHi);
buzbeee3acd072012-02-25 17:03:10 -08001064}
1065
1066} // namespace art