blob: 8d6bf547d064cd8ec2b66e29a796e364d9532354 [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
buzbee31a4a6f2012-02-28 15:36:15 -080024const RegLocation badLoc = {kLocDalvikFrame, 0, 0, 0, 0, 0, 0,
25 INVALID_REG, INVALID_REG, INVALID_SREG};
buzbeee3acd072012-02-25 17:03:10 -080026
27/* Mark register usage state and return long retloc */
Ian Rogersf7d9ad32012-03-13 18:45:39 -070028RegLocation oatGetReturnWide(CompilationUnit* cUnit, bool isDouble)
buzbeee3acd072012-02-25 17:03:10 -080029{
Bill Buzbeea114add2012-05-03 15:00:40 -070030 RegLocation gpr_res = LOC_C_RETURN_WIDE;
31 RegLocation fpr_res = LOC_C_RETURN_WIDE_DOUBLE;
32 RegLocation res = isDouble ? fpr_res : gpr_res;
33 oatClobber(cUnit, res.lowReg);
34 oatClobber(cUnit, res.highReg);
35 oatLockTemp(cUnit, res.lowReg);
36 oatLockTemp(cUnit, res.highReg);
37 oatMarkPair(cUnit, res.lowReg, res.highReg);
38 return res;
buzbeee3acd072012-02-25 17:03:10 -080039}
40
Ian Rogersf7d9ad32012-03-13 18:45:39 -070041RegLocation oatGetReturn(CompilationUnit* cUnit, bool isFloat)
buzbeee3acd072012-02-25 17:03:10 -080042{
Ian Rogersf7d9ad32012-03-13 18:45:39 -070043 RegLocation gpr_res = LOC_C_RETURN;
44 RegLocation fpr_res = LOC_C_RETURN_FLOAT;
45 RegLocation res = isFloat ? fpr_res : gpr_res;
Bill Buzbeea114add2012-05-03 15:00:40 -070046 oatClobber(cUnit, res.lowReg);
47 if (cUnit->instructionSet == kMips) {
48 oatMarkInUse(cUnit, res.lowReg);
49 } else {
50 oatLockTemp(cUnit, res.lowReg);
51 }
52 return res;
buzbeee3acd072012-02-25 17:03:10 -080053}
54
buzbeefc9e6fa2012-03-23 15:14:29 -070055void genInvoke(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir,
56 InvokeType type, bool isRange)
buzbeee3acd072012-02-25 17:03:10 -080057{
Bill Buzbeea114add2012-05-03 15:00:40 -070058 if (genIntrinsic(cUnit, bb, mir, type, isRange)) {
59 return;
60 }
61 DecodedInstruction* dInsn = &mir->dalvikInsn;
62 InvokeType originalType = type; // avoiding mutation by ComputeInvokeInfo
63 int callState = 0;
64 LIR* nullCk;
65 LIR** pNullCk = NULL;
66 NextCallInsn nextCallInsn;
67 oatFlushAllRegs(cUnit); /* Everything to home location */
68 // Explicit register usage
69 oatLockCallTemps(cUnit);
buzbeee3acd072012-02-25 17:03:10 -080070
Bill Buzbeea114add2012-05-03 15:00:40 -070071 OatCompilationUnit mUnit(cUnit->class_loader, cUnit->class_linker,
72 *cUnit->dex_file, *cUnit->dex_cache,
73 cUnit->code_item, cUnit->method_idx,
74 cUnit->access_flags);
Logan Chien4dd96f52012-02-29 01:26:58 +080075
Bill Buzbeea114add2012-05-03 15:00:40 -070076 uint32_t dexMethodIdx = dInsn->vB;
77 int vtableIdx;
78 uintptr_t directCode;
79 uintptr_t directMethod;
80 bool skipThis;
81 bool fastPath =
82 cUnit->compiler->ComputeInvokeInfo(dexMethodIdx, &mUnit, type,
83 vtableIdx, directCode,
84 directMethod)
85 && !SLOW_INVOKE_PATH;
86 if (type == kInterface) {
87 nextCallInsn = fastPath ? nextInterfaceCallInsn
88 : nextInterfaceCallInsnWithAccessCheck;
89 skipThis = false;
90 } else if (type == kDirect) {
91 if (fastPath) {
92 pNullCk = &nullCk;
buzbeee3acd072012-02-25 17:03:10 -080093 }
Bill Buzbeea114add2012-05-03 15:00:40 -070094 nextCallInsn = fastPath ? nextSDCallInsn : nextDirectCallInsnSP;
95 skipThis = false;
96 } else if (type == kStatic) {
97 nextCallInsn = fastPath ? nextSDCallInsn : nextStaticCallInsnSP;
98 skipThis = false;
99 } else if (type == kSuper) {
100 DCHECK(!fastPath); // Fast path is a direct call.
101 nextCallInsn = nextSuperCallInsnSP;
102 skipThis = false;
103 } else {
104 DCHECK_EQ(type, kVirtual);
105 nextCallInsn = fastPath ? nextVCallInsn : nextVCallInsnSP;
106 skipThis = fastPath;
107 }
108 if (!isRange) {
109 callState = genDalvikArgsNoRange(cUnit, mir, dInsn, callState, pNullCk,
110 nextCallInsn, dexMethodIdx,
111 vtableIdx, directCode, directMethod,
112 originalType, skipThis);
113 } else {
114 callState = genDalvikArgsRange(cUnit, mir, dInsn, callState, pNullCk,
115 nextCallInsn, dexMethodIdx, vtableIdx,
116 directCode, directMethod, originalType,
117 skipThis);
118 }
119 // Finish up any of the call sequence not interleaved in arg loading
120 while (callState >= 0) {
121 callState = nextCallInsn(cUnit, mir, callState, dexMethodIdx,
122 vtableIdx, directCode, directMethod,
123 originalType);
124 }
125 if (DISPLAY_MISSING_TARGETS) {
126 genShowTarget(cUnit);
127 }
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700128#if !defined(TARGET_X86)
Bill Buzbeea114add2012-05-03 15:00:40 -0700129 opReg(cUnit, kOpBlx, rINVOKE_TGT);
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700130#else
Bill Buzbeea114add2012-05-03 15:00:40 -0700131 if (fastPath && type != kInterface) {
132 opMem(cUnit, kOpBlx, rARG0, Method::GetCodeOffset().Int32Value());
133 } else {
134 int trampoline = 0;
135 switch (type) {
136 case kInterface:
137 trampoline = fastPath ? ENTRYPOINT_OFFSET(pInvokeInterfaceTrampoline)
138 : ENTRYPOINT_OFFSET(pInvokeInterfaceTrampolineWithAccessCheck);
139 break;
140 case kDirect:
141 trampoline = ENTRYPOINT_OFFSET(pInvokeDirectTrampolineWithAccessCheck);
142 break;
143 case kStatic:
144 trampoline = ENTRYPOINT_OFFSET(pInvokeStaticTrampolineWithAccessCheck);
145 break;
146 case kSuper:
147 trampoline = ENTRYPOINT_OFFSET(pInvokeSuperTrampolineWithAccessCheck);
148 break;
149 case kVirtual:
150 trampoline = ENTRYPOINT_OFFSET(pInvokeVirtualTrampolineWithAccessCheck);
151 break;
152 default:
153 LOG(FATAL) << "Unexpected invoke type";
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700154 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700155 opThreadMem(cUnit, kOpBlx, trampoline);
156 }
buzbeea7678db2012-03-05 15:35:46 -0800157#endif
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700158
Bill Buzbeea114add2012-05-03 15:00:40 -0700159 oatClobberCalleeSave(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800160}
161
162/*
163 * Target-independent code generation. Use only high-level
164 * load/store utilities here, or target-dependent genXX() handlers
165 * when necessary.
166 */
buzbee31a4a6f2012-02-28 15:36:15 -0800167bool compileDalvikInstruction(CompilationUnit* cUnit, MIR* mir,
168 BasicBlock* bb, LIR* labelList)
buzbeee3acd072012-02-25 17:03:10 -0800169{
Bill Buzbeea114add2012-05-03 15:00:40 -0700170 bool res = false; // Assume success
171 RegLocation rlSrc[3];
172 RegLocation rlDest = badLoc;
173 RegLocation rlResult = badLoc;
174 Instruction::Code opcode = mir->dalvikInsn.opcode;
buzbeee3acd072012-02-25 17:03:10 -0800175
Bill Buzbeea114add2012-05-03 15:00:40 -0700176 /* Prep Src and Dest locations */
177 int nextSreg = 0;
178 int nextLoc = 0;
179 int attrs = oatDataFlowAttributes[opcode];
180 rlSrc[0] = rlSrc[1] = rlSrc[2] = badLoc;
181 if (attrs & DF_UA) {
182 rlSrc[nextLoc++] = oatGetSrc(cUnit, mir, nextSreg);
183 nextSreg++;
184 } else if (attrs & DF_UA_WIDE) {
185 rlSrc[nextLoc++] = oatGetSrcWide(cUnit, mir, nextSreg, nextSreg + 1);
186 nextSreg+= 2;
187 }
188 if (attrs & DF_UB) {
189 rlSrc[nextLoc++] = oatGetSrc(cUnit, mir, nextSreg);
190 nextSreg++;
191 } else if (attrs & DF_UB_WIDE) {
192 rlSrc[nextLoc++] = oatGetSrcWide(cUnit, mir, nextSreg, nextSreg + 1);
193 nextSreg+= 2;
194 }
195 if (attrs & DF_UC) {
196 rlSrc[nextLoc++] = oatGetSrc(cUnit, mir, nextSreg);
197 } else if (attrs & DF_UC_WIDE) {
198 rlSrc[nextLoc++] = oatGetSrcWide(cUnit, mir, nextSreg, nextSreg + 1);
199 }
200 if (attrs & DF_DA) {
201 rlDest = oatGetDest(cUnit, mir, 0);
202 } else if (attrs & DF_DA_WIDE) {
203 rlDest = oatGetDestWide(cUnit, mir, 0, 1);
204 }
buzbeee3acd072012-02-25 17:03:10 -0800205
Bill Buzbeea114add2012-05-03 15:00:40 -0700206 switch (opcode) {
207 case Instruction::NOP:
208 break;
buzbeee3acd072012-02-25 17:03:10 -0800209
Bill Buzbeea114add2012-05-03 15:00:40 -0700210 case Instruction::MOVE_EXCEPTION: {
211 int exOffset = Thread::ExceptionOffset().Int32Value();
212 rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
Ian Rogersc6f3bb82012-03-21 20:40:33 -0700213#if defined(TARGET_X86)
Bill Buzbeea114add2012-05-03 15:00:40 -0700214 newLIR2(cUnit, kX86Mov32RT, rlResult.lowReg, exOffset);
215 newLIR2(cUnit, kX86Mov32TI, exOffset, 0);
Ian Rogersc6f3bb82012-03-21 20:40:33 -0700216#else
Bill Buzbeea114add2012-05-03 15:00:40 -0700217 int resetReg = oatAllocTemp(cUnit);
218 loadWordDisp(cUnit, rSELF, exOffset, rlResult.lowReg);
219 loadConstant(cUnit, resetReg, 0);
220 storeWordDisp(cUnit, rSELF, exOffset, resetReg);
221 storeValue(cUnit, rlDest, rlResult);
222 oatFreeTemp(cUnit, resetReg);
buzbeea7678db2012-03-05 15:35:46 -0800223#endif
Bill Buzbeea114add2012-05-03 15:00:40 -0700224 break;
buzbeee3acd072012-02-25 17:03:10 -0800225 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700226 case Instruction::RETURN_VOID:
227 if (!cUnit->attrs & METHOD_IS_LEAF) {
228 genSuspendTest(cUnit, mir);
229 }
230 break;
231
232 case Instruction::RETURN:
233 case Instruction::RETURN_OBJECT:
234 if (!cUnit->attrs & METHOD_IS_LEAF) {
235 genSuspendTest(cUnit, mir);
236 }
237 storeValue(cUnit, oatGetReturn(cUnit, cUnit->shorty[0] == 'F'), rlSrc[0]);
238 break;
239
240 case Instruction::RETURN_WIDE:
241 if (!cUnit->attrs & METHOD_IS_LEAF) {
242 genSuspendTest(cUnit, mir);
243 }
244 storeValueWide(cUnit, oatGetReturnWide(cUnit,
245 cUnit->shorty[0] == 'D'), rlSrc[0]);
246 break;
247
248 case Instruction::MOVE_RESULT_WIDE:
249 if (mir->optimizationFlags & MIR_INLINED)
250 break; // Nop - combined w/ previous invoke
251 storeValueWide(cUnit, rlDest, oatGetReturnWide(cUnit, rlDest.fp));
252 break;
253
254 case Instruction::MOVE_RESULT:
255 case Instruction::MOVE_RESULT_OBJECT:
256 if (mir->optimizationFlags & MIR_INLINED)
257 break; // Nop - combined w/ previous invoke
258 storeValue(cUnit, rlDest, oatGetReturn(cUnit, rlDest.fp));
259 break;
260
261 case Instruction::MOVE:
262 case Instruction::MOVE_OBJECT:
263 case Instruction::MOVE_16:
264 case Instruction::MOVE_OBJECT_16:
265 case Instruction::MOVE_FROM16:
266 case Instruction::MOVE_OBJECT_FROM16:
267 storeValue(cUnit, rlDest, rlSrc[0]);
268 break;
269
270 case Instruction::MOVE_WIDE:
271 case Instruction::MOVE_WIDE_16:
272 case Instruction::MOVE_WIDE_FROM16:
273 storeValueWide(cUnit, rlDest, rlSrc[0]);
274 break;
275
276 case Instruction::CONST:
277 case Instruction::CONST_4:
278 case Instruction::CONST_16:
279 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
280 loadConstantNoClobber(cUnit, rlResult.lowReg, mir->dalvikInsn.vB);
281 storeValue(cUnit, rlDest, rlResult);
282 break;
283
284 case Instruction::CONST_HIGH16:
285 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
286 loadConstantNoClobber(cUnit, rlResult.lowReg, mir->dalvikInsn.vB << 16);
287 storeValue(cUnit, rlDest, rlResult);
288 break;
289
290 case Instruction::CONST_WIDE_16:
291 case Instruction::CONST_WIDE_32:
292 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
293 loadConstantValueWide(cUnit, rlResult.lowReg, rlResult.highReg,
294 mir->dalvikInsn.vB,
295 (mir->dalvikInsn.vB & 0x80000000) ? -1 : 0);
296 storeValueWide(cUnit, rlDest, rlResult);
297 break;
298
299 case Instruction::CONST_WIDE:
300 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
301 loadConstantValueWide(cUnit, rlResult.lowReg, rlResult.highReg,
302 mir->dalvikInsn.vB_wide & 0xffffffff,
303 (mir->dalvikInsn.vB_wide >> 32) & 0xffffffff);
304 storeValueWide(cUnit, rlDest, rlResult);
305 break;
306
307 case Instruction::CONST_WIDE_HIGH16:
308 rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true);
309 loadConstantValueWide(cUnit, rlResult.lowReg, rlResult.highReg,
310 0, mir->dalvikInsn.vB << 16);
311 storeValueWide(cUnit, rlDest, rlResult);
312 break;
313
314 case Instruction::MONITOR_ENTER:
315 genMonitorEnter(cUnit, mir, rlSrc[0]);
316 break;
317
318 case Instruction::MONITOR_EXIT:
319 genMonitorExit(cUnit, mir, rlSrc[0]);
320 break;
321
322 case Instruction::CHECK_CAST:
323 genCheckCast(cUnit, mir, rlSrc[0]);
324 break;
325
326 case Instruction::INSTANCE_OF:
327 genInstanceof(cUnit, mir, rlDest, rlSrc[0]);
328 break;
329
330 case Instruction::NEW_INSTANCE:
331 genNewInstance(cUnit, mir, rlDest);
332 break;
333
334 case Instruction::THROW:
335 genThrow(cUnit, mir, rlSrc[0]);
336 break;
337
338 case Instruction::THROW_VERIFICATION_ERROR:
339 genThrowVerificationError(cUnit, mir);
340 break;
341
342 case Instruction::ARRAY_LENGTH:
343 int lenOffset;
344 lenOffset = Array::LengthOffset().Int32Value();
345 rlSrc[0] = loadValue(cUnit, rlSrc[0], kCoreReg);
346 genNullCheck(cUnit, rlSrc[0].sRegLow, rlSrc[0].lowReg, mir);
347 rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
348 loadWordDisp(cUnit, rlSrc[0].lowReg, lenOffset, rlResult.lowReg);
349 storeValue(cUnit, rlDest, rlResult);
350 break;
351
352 case Instruction::CONST_STRING:
353 case Instruction::CONST_STRING_JUMBO:
354 genConstString(cUnit, mir, rlDest, rlSrc[0]);
355 break;
356
357 case Instruction::CONST_CLASS:
358 genConstClass(cUnit, mir, rlDest, rlSrc[0]);
359 break;
360
361 case Instruction::FILL_ARRAY_DATA:
362 genFillArrayData(cUnit, mir, rlSrc[0]);
363 break;
364
365 case Instruction::FILLED_NEW_ARRAY:
366 genFilledNewArray(cUnit, mir, false /* not range */);
367 break;
368
369 case Instruction::FILLED_NEW_ARRAY_RANGE:
370 genFilledNewArray(cUnit, mir, true /* range */);
371 break;
372
373 case Instruction::NEW_ARRAY:
374 genNewArray(cUnit, mir, rlDest, rlSrc[0]);
375 break;
376
377 case Instruction::GOTO:
378 case Instruction::GOTO_16:
379 case Instruction::GOTO_32:
380 if (bb->taken->startOffset <= mir->offset) {
381 genSuspendTestAndBranch(cUnit, mir, &labelList[bb->taken->id]);
382 } else {
383 opUnconditionalBranch(cUnit, &labelList[bb->taken->id]);
384 }
385 break;
386
387 case Instruction::PACKED_SWITCH:
388 genPackedSwitch(cUnit, mir, rlSrc[0]);
389 break;
390
391 case Instruction::SPARSE_SWITCH:
392 genSparseSwitch(cUnit, mir, rlSrc[0], labelList);
393 break;
394
395 case Instruction::CMPL_FLOAT:
396 case Instruction::CMPG_FLOAT:
397 case Instruction::CMPL_DOUBLE:
398 case Instruction::CMPG_DOUBLE:
399 res = genCmpFP(cUnit, mir, rlDest, rlSrc[0], rlSrc[1]);
400 break;
401
402 case Instruction::CMP_LONG:
403 genCmpLong(cUnit, mir, rlDest, rlSrc[0], rlSrc[1]);
404 break;
405
406 case Instruction::IF_EQ:
407 case Instruction::IF_NE:
408 case Instruction::IF_LT:
409 case Instruction::IF_GE:
410 case Instruction::IF_GT:
411 case Instruction::IF_LE: {
412 bool backwardBranch;
413 backwardBranch = (bb->taken->startOffset <= mir->offset);
414 if (backwardBranch) {
415 genSuspendTest(cUnit, mir);
416 }
417 genCompareAndBranch(cUnit, bb, mir, rlSrc[0], rlSrc[1], labelList);
418 break;
419 }
420
421 case Instruction::IF_EQZ:
422 case Instruction::IF_NEZ:
423 case Instruction::IF_LTZ:
424 case Instruction::IF_GEZ:
425 case Instruction::IF_GTZ:
426 case Instruction::IF_LEZ: {
427 bool backwardBranch;
428 backwardBranch = (bb->taken->startOffset <= mir->offset);
429 if (backwardBranch) {
430 genSuspendTest(cUnit, mir);
431 }
432 genCompareZeroAndBranch(cUnit, bb, mir, rlSrc[0], labelList);
433 break;
434 }
435
436 case Instruction::AGET_WIDE:
437 genArrayGet(cUnit, mir, kLong, rlSrc[0], rlSrc[1], rlDest, 3);
438 break;
439 case Instruction::AGET:
440 case Instruction::AGET_OBJECT:
441 genArrayGet(cUnit, mir, kWord, rlSrc[0], rlSrc[1], rlDest, 2);
442 break;
443 case Instruction::AGET_BOOLEAN:
444 genArrayGet(cUnit, mir, kUnsignedByte, rlSrc[0], rlSrc[1], rlDest, 0);
445 break;
446 case Instruction::AGET_BYTE:
447 genArrayGet(cUnit, mir, kSignedByte, rlSrc[0], rlSrc[1], rlDest, 0);
448 break;
449 case Instruction::AGET_CHAR:
450 genArrayGet(cUnit, mir, kUnsignedHalf, rlSrc[0], rlSrc[1], rlDest, 1);
451 break;
452 case Instruction::AGET_SHORT:
453 genArrayGet(cUnit, mir, kSignedHalf, rlSrc[0], rlSrc[1], rlDest, 1);
454 break;
455 case Instruction::APUT_WIDE:
456 genArrayPut(cUnit, mir, kLong, rlSrc[1], rlSrc[2], rlSrc[0], 3);
457 break;
458 case Instruction::APUT:
459 genArrayPut(cUnit, mir, kWord, rlSrc[1], rlSrc[2], rlSrc[0], 2);
460 break;
461 case Instruction::APUT_OBJECT:
462 genArrayObjPut(cUnit, mir, rlSrc[1], rlSrc[2], rlSrc[0], 2);
463 break;
464 case Instruction::APUT_SHORT:
465 case Instruction::APUT_CHAR:
466 genArrayPut(cUnit, mir, kUnsignedHalf, rlSrc[1], rlSrc[2], rlSrc[0], 1);
467 break;
468 case Instruction::APUT_BYTE:
469 case Instruction::APUT_BOOLEAN:
470 genArrayPut(cUnit, mir, kUnsignedByte, rlSrc[1], rlSrc[2],
471 rlSrc[0], 0);
472 break;
473
474 case Instruction::IGET_OBJECT:
475 //case Instruction::IGET_OBJECT_VOLATILE:
476 genIGet(cUnit, mir, kWord, rlDest, rlSrc[0], false, true);
477 break;
478
479 case Instruction::IGET_WIDE:
480 //case Instruction::IGET_WIDE_VOLATILE:
481 genIGet(cUnit, mir, kLong, rlDest, rlSrc[0], true, false);
482 break;
483
484 case Instruction::IGET:
485 //case Instruction::IGET_VOLATILE:
486 genIGet(cUnit, mir, kWord, rlDest, rlSrc[0], false, false);
487 break;
488
489 case Instruction::IGET_CHAR:
490 genIGet(cUnit, mir, kUnsignedHalf, rlDest, rlSrc[0], false, false);
491 break;
492
493 case Instruction::IGET_SHORT:
494 genIGet(cUnit, mir, kSignedHalf, rlDest, rlSrc[0], false, false);
495 break;
496
497 case Instruction::IGET_BOOLEAN:
498 case Instruction::IGET_BYTE:
499 genIGet(cUnit, mir, kUnsignedByte, rlDest, rlSrc[0], false, false);
500 break;
501
502 case Instruction::IPUT_WIDE:
503 //case Instruction::IPUT_WIDE_VOLATILE:
504 genIPut(cUnit, mir, kLong, rlSrc[0], rlSrc[1], true, false);
505 break;
506
507 case Instruction::IPUT_OBJECT:
508 //case Instruction::IPUT_OBJECT_VOLATILE:
509 genIPut(cUnit, mir, kWord, rlSrc[0], rlSrc[1], false, true);
510 break;
511
512 case Instruction::IPUT:
513 //case Instruction::IPUT_VOLATILE:
514 genIPut(cUnit, mir, kWord, rlSrc[0], rlSrc[1], false, false);
515 break;
516
517 case Instruction::IPUT_BOOLEAN:
518 case Instruction::IPUT_BYTE:
519 genIPut(cUnit, mir, kUnsignedByte, rlSrc[0], rlSrc[1], false, false);
520 break;
521
522 case Instruction::IPUT_CHAR:
523 genIPut(cUnit, mir, kUnsignedHalf, rlSrc[0], rlSrc[1], false, false);
524 break;
525
526 case Instruction::IPUT_SHORT:
527 genIPut(cUnit, mir, kSignedHalf, rlSrc[0], rlSrc[1], false, false);
528 break;
529
530 case Instruction::SGET_OBJECT:
531 genSget(cUnit, mir, rlDest, false, true);
532 break;
533 case Instruction::SGET:
534 case Instruction::SGET_BOOLEAN:
535 case Instruction::SGET_BYTE:
536 case Instruction::SGET_CHAR:
537 case Instruction::SGET_SHORT:
538 genSget(cUnit, mir, rlDest, false, false);
539 break;
540
541 case Instruction::SGET_WIDE:
542 genSget(cUnit, mir, rlDest, true, false);
543 break;
544
545 case Instruction::SPUT_OBJECT:
546 genSput(cUnit, mir, rlSrc[0], false, true);
547 break;
548
549 case Instruction::SPUT:
550 case Instruction::SPUT_BOOLEAN:
551 case Instruction::SPUT_BYTE:
552 case Instruction::SPUT_CHAR:
553 case Instruction::SPUT_SHORT:
554 genSput(cUnit, mir, rlSrc[0], false, false);
555 break;
556
557 case Instruction::SPUT_WIDE:
558 genSput(cUnit, mir, rlSrc[0], true, false);
559 break;
560
561 case Instruction::INVOKE_STATIC_RANGE:
562 genInvoke(cUnit, bb, mir, kStatic, true /*range*/);
563 break;
564 case Instruction::INVOKE_STATIC:
565 genInvoke(cUnit, bb, mir, kStatic, false /*range*/);
566 break;
567
568 case Instruction::INVOKE_DIRECT:
569 genInvoke(cUnit, bb, mir, kDirect, false /*range*/);
570 break;
571 case Instruction::INVOKE_DIRECT_RANGE:
572 genInvoke(cUnit, bb, mir, kDirect, true /*range*/);
573 break;
574
575 case Instruction::INVOKE_VIRTUAL:
576 genInvoke(cUnit, bb, mir, kVirtual, false /*range*/);
577 break;
578 case Instruction::INVOKE_VIRTUAL_RANGE:
579 genInvoke(cUnit, bb, mir, kVirtual, true /*range*/);
580 break;
581
582 case Instruction::INVOKE_SUPER:
583 genInvoke(cUnit, bb, mir, kSuper, false /*range*/);
584 break;
585 case Instruction::INVOKE_SUPER_RANGE:
586 genInvoke(cUnit, bb, mir, kSuper, true /*range*/);
587 break;
588
589 case Instruction::INVOKE_INTERFACE:
590 genInvoke(cUnit, bb, mir, kInterface, false /*range*/);
591 break;
592 case Instruction::INVOKE_INTERFACE_RANGE:
593 genInvoke(cUnit, bb, mir, kInterface, true /*range*/);
594 break;
595
596 case Instruction::NEG_INT:
597 case Instruction::NOT_INT:
598 res = genArithOpInt(cUnit, mir, rlDest, rlSrc[0], rlSrc[0]);
599 break;
600
601 case Instruction::NEG_LONG:
602 case Instruction::NOT_LONG:
603 res = genArithOpLong(cUnit, mir, rlDest, rlSrc[0], rlSrc[0]);
604 break;
605
606 case Instruction::NEG_FLOAT:
607 res = genArithOpFloat(cUnit, mir, rlDest, rlSrc[0], rlSrc[0]);
608 break;
609
610 case Instruction::NEG_DOUBLE:
611 res = genArithOpDouble(cUnit, mir, rlDest, rlSrc[0], rlSrc[0]);
612 break;
613
614 case Instruction::INT_TO_LONG:
615 genIntToLong(cUnit, mir, rlDest, rlSrc[0]);
616 break;
617
618 case Instruction::LONG_TO_INT:
619 rlSrc[0] = oatUpdateLocWide(cUnit, rlSrc[0]);
620 rlSrc[0] = oatWideToNarrow(cUnit, rlSrc[0]);
621 storeValue(cUnit, rlDest, rlSrc[0]);
622 break;
623
624 case Instruction::INT_TO_BYTE:
625 case Instruction::INT_TO_SHORT:
626 case Instruction::INT_TO_CHAR:
627 genIntNarrowing(cUnit, mir, rlDest, rlSrc[0]);
628 break;
629
630 case Instruction::INT_TO_FLOAT:
631 case Instruction::INT_TO_DOUBLE:
632 case Instruction::LONG_TO_FLOAT:
633 case Instruction::LONG_TO_DOUBLE:
634 case Instruction::FLOAT_TO_INT:
635 case Instruction::FLOAT_TO_LONG:
636 case Instruction::FLOAT_TO_DOUBLE:
637 case Instruction::DOUBLE_TO_INT:
638 case Instruction::DOUBLE_TO_LONG:
639 case Instruction::DOUBLE_TO_FLOAT:
640 genConversion(cUnit, mir);
641 break;
642
643 case Instruction::ADD_INT:
644 case Instruction::SUB_INT:
645 case Instruction::MUL_INT:
646 case Instruction::DIV_INT:
647 case Instruction::REM_INT:
648 case Instruction::AND_INT:
649 case Instruction::OR_INT:
650 case Instruction::XOR_INT:
651 case Instruction::SHL_INT:
652 case Instruction::SHR_INT:
653 case Instruction::USHR_INT:
654 case Instruction::ADD_INT_2ADDR:
655 case Instruction::SUB_INT_2ADDR:
656 case Instruction::MUL_INT_2ADDR:
657 case Instruction::DIV_INT_2ADDR:
658 case Instruction::REM_INT_2ADDR:
659 case Instruction::AND_INT_2ADDR:
660 case Instruction::OR_INT_2ADDR:
661 case Instruction::XOR_INT_2ADDR:
662 case Instruction::SHL_INT_2ADDR:
663 case Instruction::SHR_INT_2ADDR:
664 case Instruction::USHR_INT_2ADDR:
665 genArithOpInt(cUnit, mir, rlDest, rlSrc[0], rlSrc[1]);
666 break;
667
668 case Instruction::ADD_LONG:
669 case Instruction::SUB_LONG:
670 case Instruction::MUL_LONG:
671 case Instruction::DIV_LONG:
672 case Instruction::REM_LONG:
673 case Instruction::AND_LONG:
674 case Instruction::OR_LONG:
675 case Instruction::XOR_LONG:
676 case Instruction::ADD_LONG_2ADDR:
677 case Instruction::SUB_LONG_2ADDR:
678 case Instruction::MUL_LONG_2ADDR:
679 case Instruction::DIV_LONG_2ADDR:
680 case Instruction::REM_LONG_2ADDR:
681 case Instruction::AND_LONG_2ADDR:
682 case Instruction::OR_LONG_2ADDR:
683 case Instruction::XOR_LONG_2ADDR:
684 genArithOpLong(cUnit, mir, rlDest, rlSrc[0], rlSrc[1]);
685 break;
686
687 case Instruction::SHL_LONG:
688 case Instruction::SHR_LONG:
689 case Instruction::USHR_LONG:
690 case Instruction::SHL_LONG_2ADDR:
691 case Instruction::SHR_LONG_2ADDR:
692 case Instruction::USHR_LONG_2ADDR:
693 genShiftOpLong(cUnit,mir, rlDest, rlSrc[0], rlSrc[1]);
694 break;
695
696 case Instruction::ADD_FLOAT:
697 case Instruction::SUB_FLOAT:
698 case Instruction::MUL_FLOAT:
699 case Instruction::DIV_FLOAT:
700 case Instruction::REM_FLOAT:
701 case Instruction::ADD_FLOAT_2ADDR:
702 case Instruction::SUB_FLOAT_2ADDR:
703 case Instruction::MUL_FLOAT_2ADDR:
704 case Instruction::DIV_FLOAT_2ADDR:
705 case Instruction::REM_FLOAT_2ADDR:
706 genArithOpFloat(cUnit, mir, rlDest, rlSrc[0], rlSrc[1]);
707 break;
708
709 case Instruction::ADD_DOUBLE:
710 case Instruction::SUB_DOUBLE:
711 case Instruction::MUL_DOUBLE:
712 case Instruction::DIV_DOUBLE:
713 case Instruction::REM_DOUBLE:
714 case Instruction::ADD_DOUBLE_2ADDR:
715 case Instruction::SUB_DOUBLE_2ADDR:
716 case Instruction::MUL_DOUBLE_2ADDR:
717 case Instruction::DIV_DOUBLE_2ADDR:
718 case Instruction::REM_DOUBLE_2ADDR:
719 genArithOpDouble(cUnit, mir, rlDest, rlSrc[0], rlSrc[1]);
720 break;
721
722 case Instruction::RSUB_INT:
723 case Instruction::ADD_INT_LIT16:
724 case Instruction::MUL_INT_LIT16:
725 case Instruction::DIV_INT_LIT16:
726 case Instruction::REM_INT_LIT16:
727 case Instruction::AND_INT_LIT16:
728 case Instruction::OR_INT_LIT16:
729 case Instruction::XOR_INT_LIT16:
730 case Instruction::ADD_INT_LIT8:
731 case Instruction::RSUB_INT_LIT8:
732 case Instruction::MUL_INT_LIT8:
733 case Instruction::DIV_INT_LIT8:
734 case Instruction::REM_INT_LIT8:
735 case Instruction::AND_INT_LIT8:
736 case Instruction::OR_INT_LIT8:
737 case Instruction::XOR_INT_LIT8:
738 case Instruction::SHL_INT_LIT8:
739 case Instruction::SHR_INT_LIT8:
740 case Instruction::USHR_INT_LIT8:
741 genArithOpIntLit(cUnit, mir, rlDest, rlSrc[0], mir->dalvikInsn.vC);
742 break;
743
744 default:
745 res = true;
746 }
747 return res;
buzbeee3acd072012-02-25 17:03:10 -0800748}
749
buzbee31a4a6f2012-02-28 15:36:15 -0800750const char* extendedMIROpNames[kMirOpLast - kMirOpFirst] = {
Bill Buzbeea114add2012-05-03 15:00:40 -0700751 "kMirOpPhi",
752 "kMirOpCopy",
753 "kMirFusedCmplFloat",
754 "kMirFusedCmpgFloat",
755 "kMirFusedCmplDouble",
756 "kMirFusedCmpgDouble",
757 "kMirFusedCmpLong",
758 "kMirNop",
759 "kMirOpNullNRangeUpCheck",
760 "kMirOpNullNRangeDownCheck",
761 "kMirOpLowerBound",
buzbeee3acd072012-02-25 17:03:10 -0800762};
763
764/* Extended MIR instructions like PHI */
buzbee84fd6932012-03-29 16:44:16 -0700765void handleExtendedMethodMIR(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir)
buzbeee3acd072012-02-25 17:03:10 -0800766{
Bill Buzbeea114add2012-05-03 15:00:40 -0700767 int opOffset = mir->dalvikInsn.opcode - kMirOpFirst;
768 char* msg = NULL;
769 if (cUnit->printMe) {
770 msg = (char*)oatNew(cUnit, strlen(extendedMIROpNames[opOffset]) + 1,
771 false, kAllocDebugInfo);
772 strcpy(msg, extendedMIROpNames[opOffset]);
773 }
774 LIR* op = newLIR1(cUnit, kPseudoExtended, (int) msg);
buzbeee3acd072012-02-25 17:03:10 -0800775
Bill Buzbeea114add2012-05-03 15:00:40 -0700776 switch ((ExtendedMIROpcode)mir->dalvikInsn.opcode) {
777 case kMirOpPhi: {
778 char* ssaString = NULL;
779 if (cUnit->printMe) {
780 ssaString = oatGetSSAString(cUnit, mir->ssaRep);
781 }
782 op->flags.isNop = true;
783 newLIR1(cUnit, kPseudoSSARep, (int) ssaString);
784 break;
buzbeee3acd072012-02-25 17:03:10 -0800785 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700786 case kMirOpCopy: {
787 RegLocation rlSrc = oatGetSrc(cUnit, mir, 0);
788 RegLocation rlDest = oatGetDest(cUnit, mir, 0);
789 storeValue(cUnit, rlDest, rlSrc);
790 break;
791 }
792#if defined(TARGET_ARM)
793 case kMirOpFusedCmplFloat:
794 genFusedFPCmpBranch(cUnit, bb, mir, false /*gt bias*/, false /*double*/);
795 break;
796 case kMirOpFusedCmpgFloat:
797 genFusedFPCmpBranch(cUnit, bb, mir, true /*gt bias*/, false /*double*/);
798 break;
799 case kMirOpFusedCmplDouble:
800 genFusedFPCmpBranch(cUnit, bb, mir, false /*gt bias*/, true /*double*/);
801 break;
802 case kMirOpFusedCmpgDouble:
803 genFusedFPCmpBranch(cUnit, bb, mir, true /*gt bias*/, true /*double*/);
804 break;
805 case kMirOpFusedCmpLong:
806 genFusedLongCmpBranch(cUnit, bb, mir);
807 break;
808#endif
809 default:
810 break;
811 }
buzbeee3acd072012-02-25 17:03:10 -0800812}
813
814/* Handle the content in each basic block */
buzbee31a4a6f2012-02-28 15:36:15 -0800815bool methodBlockCodeGen(CompilationUnit* cUnit, BasicBlock* bb)
buzbeee3acd072012-02-25 17:03:10 -0800816{
Bill Buzbeea114add2012-05-03 15:00:40 -0700817 MIR* mir;
818 LIR* labelList = (LIR*) cUnit->blockLabelList;
819 int blockId = bb->id;
buzbeee3acd072012-02-25 17:03:10 -0800820
Bill Buzbeea114add2012-05-03 15:00:40 -0700821 cUnit->curBlock = bb;
822 labelList[blockId].operands[0] = bb->startOffset;
buzbeee3acd072012-02-25 17:03:10 -0800823
Bill Buzbeea114add2012-05-03 15:00:40 -0700824 /* Insert the block label */
825 labelList[blockId].opcode = kPseudoNormalBlockLabel;
826 oatAppendLIR(cUnit, (LIR*) &labelList[blockId]);
buzbeee3acd072012-02-25 17:03:10 -0800827
Bill Buzbeea114add2012-05-03 15:00:40 -0700828 /* Free temp registers and reset redundant store tracking */
829 oatResetRegPool(cUnit);
830 oatResetDefTracking(cUnit);
831
832 /*
833 * If control reached us from our immediate predecessor via
834 * fallthrough and we have no other incoming arcs we can
835 * reuse existing liveness. Otherwise, reset.
836 */
837 if (!bb->fallThroughTarget || bb->predecessors->numUsed != 1) {
838 oatClobberAllRegs(cUnit);
839 }
840
841 LIR* headLIR = NULL;
842
843 if (bb->blockType == kEntryBlock) {
844 genEntrySequence(cUnit, bb);
845 } else if (bb->blockType == kExitBlock) {
846 genExitSequence(cUnit, bb);
847 }
848
849 for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
850
buzbeee3acd072012-02-25 17:03:10 -0800851 oatResetRegPool(cUnit);
Bill Buzbeea114add2012-05-03 15:00:40 -0700852 if (cUnit->disableOpt & (1 << kTrackLiveTemps)) {
853 oatClobberAllRegs(cUnit);
buzbeee1965672012-03-11 18:39:19 -0700854 }
855
Bill Buzbeea114add2012-05-03 15:00:40 -0700856 if (cUnit->disableOpt & (1 << kSuppressLoads)) {
857 oatResetDefTracking(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800858 }
859
buzbee3d661942012-03-14 17:37:27 -0700860#ifndef NDEBUG
Bill Buzbeea114add2012-05-03 15:00:40 -0700861 /* Reset temp tracking sanity check */
862 cUnit->liveSReg = INVALID_SREG;
buzbee3d661942012-03-14 17:37:27 -0700863#endif
864
Bill Buzbeea114add2012-05-03 15:00:40 -0700865 cUnit->currentDalvikOffset = mir->offset;
buzbeee3acd072012-02-25 17:03:10 -0800866
Bill Buzbeea114add2012-05-03 15:00:40 -0700867 Instruction::Code dalvikOpcode = mir->dalvikInsn.opcode;
868 Instruction::Format dalvikFormat = Instruction::FormatOf(dalvikOpcode);
buzbeee3acd072012-02-25 17:03:10 -0800869
Bill Buzbeea114add2012-05-03 15:00:40 -0700870 LIR* boundaryLIR;
buzbeee3acd072012-02-25 17:03:10 -0800871
Bill Buzbeea114add2012-05-03 15:00:40 -0700872 /* Mark the beginning of a Dalvik instruction for line tracking */
873 char* instStr = cUnit->printMe ?
874 oatGetDalvikDisassembly(cUnit, mir->dalvikInsn, "") : NULL;
875 boundaryLIR = newLIR1(cUnit, kPseudoDalvikByteCodeBoundary,
876 (intptr_t) instStr);
877 cUnit->boundaryMap.Overwrite(mir->offset, boundaryLIR);
878 /* Remember the first LIR for this block */
879 if (headLIR == NULL) {
880 headLIR = boundaryLIR;
881 /* Set the first boundaryLIR as a scheduling barrier */
882 headLIR->defMask = ENCODE_ALL;
buzbeee3acd072012-02-25 17:03:10 -0800883 }
884
Bill Buzbeea114add2012-05-03 15:00:40 -0700885 /* If we're compiling for the debugger, generate an update callout */
886 if (cUnit->genDebugger) {
887 genDebuggerUpdate(cUnit, mir->offset);
buzbeee3acd072012-02-25 17:03:10 -0800888 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700889
890 /* Don't generate the SSA annotation unless verbose mode is on */
891 if (cUnit->printMe && mir->ssaRep) {
892 char* ssaString = oatGetSSAString(cUnit, mir->ssaRep);
893 newLIR1(cUnit, kPseudoSSARep, (int) ssaString);
894 }
895
896 if ((int)mir->dalvikInsn.opcode >= (int)kMirOpFirst) {
897 handleExtendedMethodMIR(cUnit, bb, mir);
898 continue;
899 }
900
901 bool notHandled = compileDalvikInstruction(cUnit, mir, bb, labelList);
902 if (notHandled) {
903 LOG(FATAL) << StringPrintf("%#06x: Opcode %#x (%s) / Fmt %d not handled",
904 mir->offset, dalvikOpcode,
905 Instruction::Name(dalvikOpcode), dalvikFormat);
906
907 }
908 }
909
910 if (headLIR) {
911 /*
912 * Eliminate redundant loads/stores and delay stores into later
913 * slots
914 */
915 oatApplyLocalOptimizations(cUnit, (LIR*) headLIR, cUnit->lastLIRInsn);
916
917 /*
918 * Generate an unconditional branch to the fallthrough block.
919 */
920 if (bb->fallThrough) {
921 opUnconditionalBranch(cUnit, &labelList[bb->fallThrough->id]);
922 }
923 }
924 return false;
buzbeee3acd072012-02-25 17:03:10 -0800925}
926
buzbee16da88c2012-03-20 10:38:17 -0700927/* Set basic block labels */
928bool labelBlocks(CompilationUnit* cUnit, BasicBlock* bb)
929{
Bill Buzbeea114add2012-05-03 15:00:40 -0700930 LIR* labelList = (LIR*) cUnit->blockLabelList;
931 int blockId = bb->id;
buzbee16da88c2012-03-20 10:38:17 -0700932
Bill Buzbeea114add2012-05-03 15:00:40 -0700933 cUnit->curBlock = bb;
934 labelList[blockId].operands[0] = bb->startOffset;
buzbee16da88c2012-03-20 10:38:17 -0700935
Bill Buzbeea114add2012-05-03 15:00:40 -0700936 /* Insert the block label */
937 labelList[blockId].opcode = kPseudoNormalBlockLabel;
938 return false;
buzbee16da88c2012-03-20 10:38:17 -0700939}
940
941void oatSpecialMIR2LIR(CompilationUnit* cUnit, SpecialCaseHandler specialCase)
942{
Bill Buzbeea114add2012-05-03 15:00:40 -0700943 /* Find the first DalvikByteCode block */
944 int numReachableBlocks = cUnit->numReachableBlocks;
945 const GrowableList *blockList = &cUnit->blockList;
946 BasicBlock*bb = NULL;
947 for (int idx = 0; idx < numReachableBlocks; idx++) {
948 int dfsIndex = cUnit->dfsOrder.elemList[idx];
949 bb = (BasicBlock*)oatGrowableListGetElement(blockList, dfsIndex);
950 if (bb->blockType == kDalvikByteCode) {
951 break;
buzbee16da88c2012-03-20 10:38:17 -0700952 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700953 }
954 if (bb == NULL) {
955 return;
956 }
957 DCHECK_EQ(bb->startOffset, 0);
958 DCHECK(bb->firstMIRInsn != 0);
buzbee16da88c2012-03-20 10:38:17 -0700959
Bill Buzbeea114add2012-05-03 15:00:40 -0700960 /* Get the first instruction */
961 MIR* mir = bb->firstMIRInsn;
buzbee16da88c2012-03-20 10:38:17 -0700962
Bill Buzbeea114add2012-05-03 15:00:40 -0700963 /* Free temp registers and reset redundant store tracking */
964 oatResetRegPool(cUnit);
965 oatResetDefTracking(cUnit);
966 oatClobberAllRegs(cUnit);
buzbee16da88c2012-03-20 10:38:17 -0700967
Bill Buzbeea114add2012-05-03 15:00:40 -0700968 genSpecialCase(cUnit, bb, mir, specialCase);
buzbee16da88c2012-03-20 10:38:17 -0700969}
970
buzbeee3acd072012-02-25 17:03:10 -0800971void oatMethodMIR2LIR(CompilationUnit* cUnit)
972{
Bill Buzbeea114add2012-05-03 15:00:40 -0700973 /* Used to hold the labels of each block */
974 cUnit->blockLabelList =
975 (void *) oatNew(cUnit, sizeof(LIR) * cUnit->numBlocks, true, kAllocLIR);
buzbeee3acd072012-02-25 17:03:10 -0800976
Bill Buzbeea114add2012-05-03 15:00:40 -0700977 oatDataFlowAnalysisDispatcher(cUnit, methodBlockCodeGen,
978 kPreOrderDFSTraversal, false /* Iterative */);
Ian Rogersab2b55d2012-03-18 00:06:11 -0700979
Bill Buzbeea114add2012-05-03 15:00:40 -0700980 handleSuspendLaunchpads(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800981
Bill Buzbeea114add2012-05-03 15:00:40 -0700982 handleThrowLaunchpads(cUnit);
buzbeee3acd072012-02-25 17:03:10 -0800983
Bill Buzbeea114add2012-05-03 15:00:40 -0700984 handleIntrinsicLaunchpads(cUnit);
buzbeefc9e6fa2012-03-23 15:14:29 -0700985
Bill Buzbeea114add2012-05-03 15:00:40 -0700986 if (!(cUnit->disableOpt & (1 << kSafeOptimizations))) {
987 removeRedundantBranches(cUnit);
988 }
buzbeee3acd072012-02-25 17:03:10 -0800989}
990
991/* Needed by the ld/st optmizatons */
buzbee31a4a6f2012-02-28 15:36:15 -0800992LIR* oatRegCopyNoInsert(CompilationUnit* cUnit, int rDest, int rSrc)
buzbeee3acd072012-02-25 17:03:10 -0800993{
Bill Buzbeea114add2012-05-03 15:00:40 -0700994 return opRegCopyNoInsert(cUnit, rDest, rSrc);
buzbeee3acd072012-02-25 17:03:10 -0800995}
996
997/* Needed by the register allocator */
998void oatRegCopy(CompilationUnit* cUnit, int rDest, int rSrc)
999{
Bill Buzbeea114add2012-05-03 15:00:40 -07001000 opRegCopy(cUnit, rDest, rSrc);
buzbeee3acd072012-02-25 17:03:10 -08001001}
1002
1003/* Needed by the register allocator */
1004void oatRegCopyWide(CompilationUnit* cUnit, int destLo, int destHi,
Bill Buzbeea114add2012-05-03 15:00:40 -07001005 int srcLo, int srcHi)
buzbeee3acd072012-02-25 17:03:10 -08001006{
Bill Buzbeea114add2012-05-03 15:00:40 -07001007 opRegCopyWide(cUnit, destLo, destHi, srcLo, srcHi);
buzbeee3acd072012-02-25 17:03:10 -08001008}
1009
1010void oatFlushRegImpl(CompilationUnit* cUnit, int rBase,
Bill Buzbeea114add2012-05-03 15:00:40 -07001011 int displacement, int rSrc, OpSize size)
buzbeee3acd072012-02-25 17:03:10 -08001012{
Bill Buzbeea114add2012-05-03 15:00:40 -07001013 storeBaseDisp(cUnit, rBase, displacement, rSrc, size);
buzbeee3acd072012-02-25 17:03:10 -08001014}
1015
1016void oatFlushRegWideImpl(CompilationUnit* cUnit, int rBase,
Bill Buzbeea114add2012-05-03 15:00:40 -07001017 int displacement, int rSrcLo, int rSrcHi)
buzbeee3acd072012-02-25 17:03:10 -08001018{
Bill Buzbeea114add2012-05-03 15:00:40 -07001019 storeBaseDispWide(cUnit, rBase, displacement, rSrcLo, rSrcHi);
buzbeee3acd072012-02-25 17:03:10 -08001020}
1021
1022} // namespace art