gen_common.cc revision feb2b4e2d1c6538777bb80b60f3a247537b6221d
1/*
2 * Copyright (C) 2012 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 "dex/compiler_ir.h"
18#include "dex/compiler_internals.h"
19#include "dex/quick/mir_to_lir-inl.h"
20#include "entrypoints/quick/quick_entrypoints.h"
21#include "mirror/array.h"
22#include "mirror/object-inl.h"
23#include "verifier/method_verifier.h"
24
25namespace art {
26
27/*
28 * This source files contains "gen" codegen routines that should
29 * be applicable to most targets.  Only mid-level support utilities
30 * and "op" calls may be used here.
31 */
32
33/*
34 * Generate a kPseudoBarrier marker to indicate the boundary of special
35 * blocks.
36 */
37void Mir2Lir::GenBarrier() {
38  LIR* barrier = NewLIR0(kPseudoBarrier);
39  /* Mark all resources as being clobbered */
40  DCHECK(!barrier->flags.use_def_invalid);
41  barrier->u.m.def_mask = ENCODE_ALL;
42}
43
44// TODO: need to do some work to split out targets with
45// condition codes and those without
46LIR* Mir2Lir::GenCheck(ConditionCode c_code, ThrowKind kind) {
47  DCHECK_NE(cu_->instruction_set, kMips);
48  LIR* tgt = RawLIR(0, kPseudoThrowTarget, kind, current_dalvik_offset_);
49  LIR* branch = OpCondBranch(c_code, tgt);
50  // Remember branch target - will process later
51  throw_launchpads_.Insert(tgt);
52  return branch;
53}
54
55LIR* Mir2Lir::GenImmedCheck(ConditionCode c_code, int reg, int imm_val, ThrowKind kind) {
56  LIR* tgt = RawLIR(0, kPseudoThrowTarget, kind, current_dalvik_offset_, reg, imm_val);
57  LIR* branch;
58  if (c_code == kCondAl) {
59    branch = OpUnconditionalBranch(tgt);
60  } else {
61    branch = OpCmpImmBranch(c_code, reg, imm_val, tgt);
62  }
63  // Remember branch target - will process later
64  throw_launchpads_.Insert(tgt);
65  return branch;
66}
67
68/* Perform null-check on a register.  */
69LIR* Mir2Lir::GenNullCheck(int s_reg, int m_reg, int opt_flags) {
70  if (!(cu_->disable_opt & (1 << kNullCheckElimination)) && (opt_flags & MIR_IGNORE_NULL_CHECK)) {
71    return NULL;
72  }
73  return GenImmedCheck(kCondEq, m_reg, 0, kThrowNullPointer);
74}
75
76/* Perform check on two registers */
77LIR* Mir2Lir::GenRegRegCheck(ConditionCode c_code, int reg1, int reg2,
78                             ThrowKind kind) {
79  LIR* tgt = RawLIR(0, kPseudoThrowTarget, kind, current_dalvik_offset_, reg1, reg2);
80  LIR* branch = OpCmpBranch(c_code, reg1, reg2, tgt);
81  // Remember branch target - will process later
82  throw_launchpads_.Insert(tgt);
83  return branch;
84}
85
86void Mir2Lir::GenCompareAndBranch(Instruction::Code opcode, RegLocation rl_src1,
87                                  RegLocation rl_src2, LIR* taken,
88                                  LIR* fall_through) {
89  ConditionCode cond;
90  switch (opcode) {
91    case Instruction::IF_EQ:
92      cond = kCondEq;
93      break;
94    case Instruction::IF_NE:
95      cond = kCondNe;
96      break;
97    case Instruction::IF_LT:
98      cond = kCondLt;
99      break;
100    case Instruction::IF_GE:
101      cond = kCondGe;
102      break;
103    case Instruction::IF_GT:
104      cond = kCondGt;
105      break;
106    case Instruction::IF_LE:
107      cond = kCondLe;
108      break;
109    default:
110      cond = static_cast<ConditionCode>(0);
111      LOG(FATAL) << "Unexpected opcode " << opcode;
112  }
113
114  // Normalize such that if either operand is constant, src2 will be constant
115  if (rl_src1.is_const) {
116    RegLocation rl_temp = rl_src1;
117    rl_src1 = rl_src2;
118    rl_src2 = rl_temp;
119    cond = FlipComparisonOrder(cond);
120  }
121
122  rl_src1 = LoadValue(rl_src1, kCoreReg);
123  // Is this really an immediate comparison?
124  if (rl_src2.is_const) {
125    // If it's already live in a register or not easily materialized, just keep going
126    RegLocation rl_temp = UpdateLoc(rl_src2);
127    if ((rl_temp.location == kLocDalvikFrame) &&
128        InexpensiveConstantInt(mir_graph_->ConstantValue(rl_src2))) {
129      // OK - convert this to a compare immediate and branch
130      OpCmpImmBranch(cond, rl_src1.low_reg, mir_graph_->ConstantValue(rl_src2), taken);
131      return;
132    }
133  }
134  rl_src2 = LoadValue(rl_src2, kCoreReg);
135  OpCmpBranch(cond, rl_src1.low_reg, rl_src2.low_reg, taken);
136}
137
138void Mir2Lir::GenCompareZeroAndBranch(Instruction::Code opcode, RegLocation rl_src, LIR* taken,
139                                      LIR* fall_through) {
140  ConditionCode cond;
141  rl_src = LoadValue(rl_src, kCoreReg);
142  switch (opcode) {
143    case Instruction::IF_EQZ:
144      cond = kCondEq;
145      break;
146    case Instruction::IF_NEZ:
147      cond = kCondNe;
148      break;
149    case Instruction::IF_LTZ:
150      cond = kCondLt;
151      break;
152    case Instruction::IF_GEZ:
153      cond = kCondGe;
154      break;
155    case Instruction::IF_GTZ:
156      cond = kCondGt;
157      break;
158    case Instruction::IF_LEZ:
159      cond = kCondLe;
160      break;
161    default:
162      cond = static_cast<ConditionCode>(0);
163      LOG(FATAL) << "Unexpected opcode " << opcode;
164  }
165  OpCmpImmBranch(cond, rl_src.low_reg, 0, taken);
166}
167
168void Mir2Lir::GenIntToLong(RegLocation rl_dest, RegLocation rl_src) {
169  RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
170  if (rl_src.location == kLocPhysReg) {
171    OpRegCopy(rl_result.low_reg, rl_src.low_reg);
172  } else {
173    LoadValueDirect(rl_src, rl_result.low_reg);
174  }
175  OpRegRegImm(kOpAsr, rl_result.high_reg, rl_result.low_reg, 31);
176  StoreValueWide(rl_dest, rl_result);
177}
178
179void Mir2Lir::GenIntNarrowing(Instruction::Code opcode, RegLocation rl_dest,
180                              RegLocation rl_src) {
181  rl_src = LoadValue(rl_src, kCoreReg);
182  RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
183  OpKind op = kOpInvalid;
184  switch (opcode) {
185    case Instruction::INT_TO_BYTE:
186      op = kOp2Byte;
187      break;
188    case Instruction::INT_TO_SHORT:
189       op = kOp2Short;
190       break;
191    case Instruction::INT_TO_CHAR:
192       op = kOp2Char;
193       break;
194    default:
195      LOG(ERROR) << "Bad int conversion type";
196  }
197  OpRegReg(op, rl_result.low_reg, rl_src.low_reg);
198  StoreValue(rl_dest, rl_result);
199}
200
201/*
202 * Let helper function take care of everything.  Will call
203 * Array::AllocFromCode(type_idx, method, count);
204 * Note: AllocFromCode will handle checks for errNegativeArraySize.
205 */
206void Mir2Lir::GenNewArray(uint32_t type_idx, RegLocation rl_dest,
207                          RegLocation rl_src) {
208  FlushAllRegs();  /* Everything to home location */
209  ThreadOffset func_offset(-1);
210  const DexFile* dex_file = cu_->dex_file;
211  CompilerDriver* driver = cu_->compiler_driver;
212  if (cu_->compiler_driver->CanAccessTypeWithoutChecks(cu_->method_idx, *dex_file,
213                                                       type_idx)) {
214    bool is_type_initialized;  // Ignored as an array does not have an initializer.
215    bool use_direct_type_ptr;
216    uintptr_t direct_type_ptr;
217    if (kEmbedClassInCode &&
218        driver->CanEmbedTypeInCode(*dex_file, type_idx,
219                                   &is_type_initialized, &use_direct_type_ptr, &direct_type_ptr)) {
220      // The fast path.
221      if (!use_direct_type_ptr) {
222        // Use the literal pool and a PC-relative load from a data word.
223        LIR* data_target = ScanLiteralPool(class_literal_list_, type_idx, 0);
224        if (data_target == nullptr) {
225          data_target = AddWordData(&class_literal_list_, type_idx);
226        }
227        LIR* load_pc_rel = OpPcRelLoad(TargetReg(kArg0), data_target);
228        AppendLIR(load_pc_rel);
229        func_offset = QUICK_ENTRYPOINT_OFFSET(pAllocArrayResolved);
230        CallRuntimeHelperRegMethodRegLocation(func_offset, TargetReg(kArg0), rl_src, true);
231      } else {
232        // Use the direct pointer.
233        func_offset = QUICK_ENTRYPOINT_OFFSET(pAllocArrayResolved);
234        CallRuntimeHelperImmMethodRegLocation(func_offset, direct_type_ptr, rl_src, true);
235      }
236    } else {
237      // The slow path.
238      DCHECK_EQ(func_offset.Int32Value(), -1);
239      func_offset = QUICK_ENTRYPOINT_OFFSET(pAllocArray);
240      CallRuntimeHelperImmMethodRegLocation(func_offset, type_idx, rl_src, true);
241    }
242    DCHECK_NE(func_offset.Int32Value(), -1);
243  } else {
244    func_offset= QUICK_ENTRYPOINT_OFFSET(pAllocArrayWithAccessCheck);
245    CallRuntimeHelperImmMethodRegLocation(func_offset, type_idx, rl_src, true);
246  }
247  RegLocation rl_result = GetReturn(false);
248  StoreValue(rl_dest, rl_result);
249}
250
251/*
252 * Similar to GenNewArray, but with post-allocation initialization.
253 * Verifier guarantees we're dealing with an array class.  Current
254 * code throws runtime exception "bad Filled array req" for 'D' and 'J'.
255 * Current code also throws internal unimp if not 'L', '[' or 'I'.
256 */
257void Mir2Lir::GenFilledNewArray(CallInfo* info) {
258  int elems = info->num_arg_words;
259  int type_idx = info->index;
260  FlushAllRegs();  /* Everything to home location */
261  ThreadOffset func_offset(-1);
262  if (cu_->compiler_driver->CanAccessTypeWithoutChecks(cu_->method_idx, *cu_->dex_file,
263                                                       type_idx)) {
264    func_offset = QUICK_ENTRYPOINT_OFFSET(pCheckAndAllocArray);
265  } else {
266    func_offset = QUICK_ENTRYPOINT_OFFSET(pCheckAndAllocArrayWithAccessCheck);
267  }
268  CallRuntimeHelperImmMethodImm(func_offset, type_idx, elems, true);
269  FreeTemp(TargetReg(kArg2));
270  FreeTemp(TargetReg(kArg1));
271  /*
272   * NOTE: the implicit target for Instruction::FILLED_NEW_ARRAY is the
273   * return region.  Because AllocFromCode placed the new array
274   * in kRet0, we'll just lock it into place.  When debugger support is
275   * added, it may be necessary to additionally copy all return
276   * values to a home location in thread-local storage
277   */
278  LockTemp(TargetReg(kRet0));
279
280  // TODO: use the correct component size, currently all supported types
281  // share array alignment with ints (see comment at head of function)
282  size_t component_size = sizeof(int32_t);
283
284  // Having a range of 0 is legal
285  if (info->is_range && (elems > 0)) {
286    /*
287     * Bit of ugliness here.  We're going generate a mem copy loop
288     * on the register range, but it is possible that some regs
289     * in the range have been promoted.  This is unlikely, but
290     * before generating the copy, we'll just force a flush
291     * of any regs in the source range that have been promoted to
292     * home location.
293     */
294    for (int i = 0; i < elems; i++) {
295      RegLocation loc = UpdateLoc(info->args[i]);
296      if (loc.location == kLocPhysReg) {
297        StoreBaseDisp(TargetReg(kSp), SRegOffset(loc.s_reg_low),
298                      loc.low_reg, kWord);
299      }
300    }
301    /*
302     * TUNING note: generated code here could be much improved, but
303     * this is an uncommon operation and isn't especially performance
304     * critical.
305     */
306    int r_src = AllocTemp();
307    int r_dst = AllocTemp();
308    int r_idx = AllocTemp();
309    int r_val = INVALID_REG;
310    switch (cu_->instruction_set) {
311      case kThumb2:
312        r_val = TargetReg(kLr);
313        break;
314      case kX86:
315        FreeTemp(TargetReg(kRet0));
316        r_val = AllocTemp();
317        break;
318      case kMips:
319        r_val = AllocTemp();
320        break;
321      default: LOG(FATAL) << "Unexpected instruction set: " << cu_->instruction_set;
322    }
323    // Set up source pointer
324    RegLocation rl_first = info->args[0];
325    OpRegRegImm(kOpAdd, r_src, TargetReg(kSp), SRegOffset(rl_first.s_reg_low));
326    // Set up the target pointer
327    OpRegRegImm(kOpAdd, r_dst, TargetReg(kRet0),
328                mirror::Array::DataOffset(component_size).Int32Value());
329    // Set up the loop counter (known to be > 0)
330    LoadConstant(r_idx, elems - 1);
331    // Generate the copy loop.  Going backwards for convenience
332    LIR* target = NewLIR0(kPseudoTargetLabel);
333    // Copy next element
334    LoadBaseIndexed(r_src, r_idx, r_val, 2, kWord);
335    StoreBaseIndexed(r_dst, r_idx, r_val, 2, kWord);
336    FreeTemp(r_val);
337    OpDecAndBranch(kCondGe, r_idx, target);
338    if (cu_->instruction_set == kX86) {
339      // Restore the target pointer
340      OpRegRegImm(kOpAdd, TargetReg(kRet0), r_dst,
341                  -mirror::Array::DataOffset(component_size).Int32Value());
342    }
343  } else if (!info->is_range) {
344    // TUNING: interleave
345    for (int i = 0; i < elems; i++) {
346      RegLocation rl_arg = LoadValue(info->args[i], kCoreReg);
347      StoreBaseDisp(TargetReg(kRet0),
348                    mirror::Array::DataOffset(component_size).Int32Value() +
349                    i * 4, rl_arg.low_reg, kWord);
350      // If the LoadValue caused a temp to be allocated, free it
351      if (IsTemp(rl_arg.low_reg)) {
352        FreeTemp(rl_arg.low_reg);
353      }
354    }
355  }
356  if (info->result.location != kLocInvalid) {
357    StoreValue(info->result, GetReturn(false /* not fp */));
358  }
359}
360
361void Mir2Lir::GenSput(uint32_t field_idx, RegLocation rl_src, bool is_long_or_double,
362                      bool is_object) {
363  int field_offset;
364  int storage_index;
365  bool is_volatile;
366  bool is_referrers_class;
367  bool is_initialized;
368  bool fast_path = cu_->compiler_driver->ComputeStaticFieldInfo(
369      field_idx, mir_graph_->GetCurrentDexCompilationUnit(), true,
370      &field_offset, &storage_index, &is_referrers_class, &is_volatile, &is_initialized);
371  if (fast_path && !SLOW_FIELD_PATH) {
372    DCHECK_GE(field_offset, 0);
373    int r_base;
374    if (is_referrers_class) {
375      // Fast path, static storage base is this method's class
376      RegLocation rl_method  = LoadCurrMethod();
377      r_base = AllocTemp();
378      LoadWordDisp(rl_method.low_reg,
379                   mirror::ArtMethod::DeclaringClassOffset().Int32Value(), r_base);
380      if (IsTemp(rl_method.low_reg)) {
381        FreeTemp(rl_method.low_reg);
382      }
383    } else {
384      // Medium path, static storage base in a different class which requires checks that the other
385      // class is initialized.
386      // TODO: remove initialized check now that we are initializing classes in the compiler driver.
387      DCHECK_GE(storage_index, 0);
388      // May do runtime call so everything to home locations.
389      FlushAllRegs();
390      // Using fixed register to sync with possible call to runtime support.
391      int r_method = TargetReg(kArg1);
392      LockTemp(r_method);
393      LoadCurrMethodDirect(r_method);
394      r_base = TargetReg(kArg0);
395      LockTemp(r_base);
396      LoadWordDisp(r_method,
397                   mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value(),
398                   r_base);
399      LoadWordDisp(r_base, mirror::Array::DataOffset(sizeof(mirror::Object*)).Int32Value() +
400                   sizeof(int32_t*) * storage_index, r_base);
401      // r_base now points at static storage (Class*) or NULL if the type is not yet resolved.
402      if (!is_initialized) {
403        // Check if r_base is NULL or a not yet initialized class.
404        // TUNING: fast path should fall through
405        LIR* unresolved_branch = OpCmpImmBranch(kCondEq, r_base, 0, NULL);
406        int r_tmp = TargetReg(kArg2);
407        LockTemp(r_tmp);
408        LIR* initialized_branch = OpCmpMemImmBranch(kCondGe, r_tmp, r_base,
409                                          mirror::Class::StatusOffset().Int32Value(),
410                                          mirror::Class::kStatusInitialized, NULL);
411
412        LIR* unresolved_target = NewLIR0(kPseudoTargetLabel);
413        unresolved_branch->target = unresolved_target;
414        CallRuntimeHelperImm(QUICK_ENTRYPOINT_OFFSET(pInitializeStaticStorage), storage_index,
415                             true);
416        // Copy helper's result into r_base, a no-op on all but MIPS.
417        OpRegCopy(r_base, TargetReg(kRet0));
418
419        LIR* initialized_target = NewLIR0(kPseudoTargetLabel);
420        initialized_branch->target = initialized_target;
421
422        FreeTemp(r_tmp);
423      }
424      FreeTemp(r_method);
425    }
426    // rBase now holds static storage base
427    if (is_long_or_double) {
428      rl_src = LoadValueWide(rl_src, kAnyReg);
429    } else {
430      rl_src = LoadValue(rl_src, kAnyReg);
431    }
432    if (is_volatile) {
433      GenMemBarrier(kStoreStore);
434    }
435    if (is_long_or_double) {
436      StoreBaseDispWide(r_base, field_offset, rl_src.low_reg,
437                        rl_src.high_reg);
438    } else {
439      StoreWordDisp(r_base, field_offset, rl_src.low_reg);
440    }
441    if (is_volatile) {
442      GenMemBarrier(kStoreLoad);
443    }
444    if (is_object && !mir_graph_->IsConstantNullRef(rl_src)) {
445      MarkGCCard(rl_src.low_reg, r_base);
446    }
447    FreeTemp(r_base);
448  } else {
449    FlushAllRegs();  // Everything to home locations
450    ThreadOffset setter_offset =
451        is_long_or_double ? QUICK_ENTRYPOINT_OFFSET(pSet64Static)
452                          : (is_object ? QUICK_ENTRYPOINT_OFFSET(pSetObjStatic)
453                                       : QUICK_ENTRYPOINT_OFFSET(pSet32Static));
454    CallRuntimeHelperImmRegLocation(setter_offset, field_idx, rl_src, true);
455  }
456}
457
458void Mir2Lir::GenSget(uint32_t field_idx, RegLocation rl_dest,
459                      bool is_long_or_double, bool is_object) {
460  int field_offset;
461  int storage_index;
462  bool is_volatile;
463  bool is_referrers_class;
464  bool is_initialized;
465  bool fast_path = cu_->compiler_driver->ComputeStaticFieldInfo(
466      field_idx, mir_graph_->GetCurrentDexCompilationUnit(), false,
467      &field_offset, &storage_index, &is_referrers_class, &is_volatile, &is_initialized);
468  if (fast_path && !SLOW_FIELD_PATH) {
469    DCHECK_GE(field_offset, 0);
470    int r_base;
471    if (is_referrers_class) {
472      // Fast path, static storage base is this method's class
473      RegLocation rl_method  = LoadCurrMethod();
474      r_base = AllocTemp();
475      LoadWordDisp(rl_method.low_reg,
476                   mirror::ArtMethod::DeclaringClassOffset().Int32Value(), r_base);
477    } else {
478      // Medium path, static storage base in a different class which requires checks that the other
479      // class is initialized
480      DCHECK_GE(storage_index, 0);
481      // May do runtime call so everything to home locations.
482      FlushAllRegs();
483      // Using fixed register to sync with possible call to runtime support.
484      int r_method = TargetReg(kArg1);
485      LockTemp(r_method);
486      LoadCurrMethodDirect(r_method);
487      r_base = TargetReg(kArg0);
488      LockTemp(r_base);
489      LoadWordDisp(r_method,
490                   mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value(),
491                   r_base);
492      LoadWordDisp(r_base, mirror::Array::DataOffset(sizeof(mirror::Object*)).Int32Value() +
493                   sizeof(int32_t*) * storage_index, r_base);
494      // r_base now points at static storage (Class*) or NULL if the type is not yet resolved.
495      if (!is_initialized) {
496        // Check if r_base is NULL or a not yet initialized class.
497        // TUNING: fast path should fall through
498        LIR* unresolved_branch = OpCmpImmBranch(kCondEq, r_base, 0, NULL);
499        int r_tmp = TargetReg(kArg2);
500        LockTemp(r_tmp);
501        LIR* initialized_branch = OpCmpMemImmBranch(kCondGe, r_tmp, r_base,
502                                          mirror::Class::StatusOffset().Int32Value(),
503                                          mirror::Class::kStatusInitialized, NULL);
504
505        LIR* unresolved_target = NewLIR0(kPseudoTargetLabel);
506        unresolved_branch->target = unresolved_target;
507        CallRuntimeHelperImm(QUICK_ENTRYPOINT_OFFSET(pInitializeStaticStorage), storage_index,
508                             true);
509        // Copy helper's result into r_base, a no-op on all but MIPS.
510        OpRegCopy(r_base, TargetReg(kRet0));
511
512        LIR* initialized_target = NewLIR0(kPseudoTargetLabel);
513        initialized_branch->target = initialized_target;
514
515        FreeTemp(r_tmp);
516      }
517      FreeTemp(r_method);
518    }
519    // r_base now holds static storage base
520    RegLocation rl_result = EvalLoc(rl_dest, kAnyReg, true);
521    if (is_volatile) {
522      GenMemBarrier(kLoadLoad);
523    }
524    if (is_long_or_double) {
525      LoadBaseDispWide(r_base, field_offset, rl_result.low_reg,
526                       rl_result.high_reg, INVALID_SREG);
527    } else {
528      LoadWordDisp(r_base, field_offset, rl_result.low_reg);
529    }
530    FreeTemp(r_base);
531    if (is_long_or_double) {
532      StoreValueWide(rl_dest, rl_result);
533    } else {
534      StoreValue(rl_dest, rl_result);
535    }
536  } else {
537    FlushAllRegs();  // Everything to home locations
538    ThreadOffset getterOffset =
539        is_long_or_double ? QUICK_ENTRYPOINT_OFFSET(pGet64Static)
540                          :(is_object ? QUICK_ENTRYPOINT_OFFSET(pGetObjStatic)
541                                      : QUICK_ENTRYPOINT_OFFSET(pGet32Static));
542    CallRuntimeHelperImm(getterOffset, field_idx, true);
543    if (is_long_or_double) {
544      RegLocation rl_result = GetReturnWide(rl_dest.fp);
545      StoreValueWide(rl_dest, rl_result);
546    } else {
547      RegLocation rl_result = GetReturn(rl_dest.fp);
548      StoreValue(rl_dest, rl_result);
549    }
550  }
551}
552
553void Mir2Lir::HandleSuspendLaunchPads() {
554  int num_elems = suspend_launchpads_.Size();
555  ThreadOffset helper_offset = QUICK_ENTRYPOINT_OFFSET(pTestSuspend);
556  for (int i = 0; i < num_elems; i++) {
557    ResetRegPool();
558    ResetDefTracking();
559    LIR* lab = suspend_launchpads_.Get(i);
560    LIR* resume_lab = reinterpret_cast<LIR*>(UnwrapPointer(lab->operands[0]));
561    current_dalvik_offset_ = lab->operands[1];
562    AppendLIR(lab);
563    int r_tgt = CallHelperSetup(helper_offset);
564    CallHelper(r_tgt, helper_offset, true /* MarkSafepointPC */);
565    OpUnconditionalBranch(resume_lab);
566  }
567}
568
569void Mir2Lir::HandleIntrinsicLaunchPads() {
570  int num_elems = intrinsic_launchpads_.Size();
571  for (int i = 0; i < num_elems; i++) {
572    ResetRegPool();
573    ResetDefTracking();
574    LIR* lab = intrinsic_launchpads_.Get(i);
575    CallInfo* info = reinterpret_cast<CallInfo*>(UnwrapPointer(lab->operands[0]));
576    current_dalvik_offset_ = info->offset;
577    AppendLIR(lab);
578    // NOTE: GenInvoke handles MarkSafepointPC
579    GenInvoke(info);
580    LIR* resume_lab = reinterpret_cast<LIR*>(UnwrapPointer(lab->operands[2]));
581    if (resume_lab != NULL) {
582      OpUnconditionalBranch(resume_lab);
583    }
584  }
585}
586
587void Mir2Lir::HandleThrowLaunchPads() {
588  int num_elems = throw_launchpads_.Size();
589  for (int i = 0; i < num_elems; i++) {
590    ResetRegPool();
591    ResetDefTracking();
592    LIR* lab = throw_launchpads_.Get(i);
593    current_dalvik_offset_ = lab->operands[1];
594    AppendLIR(lab);
595    ThreadOffset func_offset(-1);
596    int v1 = lab->operands[2];
597    int v2 = lab->operands[3];
598    bool target_x86 = (cu_->instruction_set == kX86);
599    switch (lab->operands[0]) {
600      case kThrowNullPointer:
601        func_offset = QUICK_ENTRYPOINT_OFFSET(pThrowNullPointer);
602        break;
603      case kThrowConstantArrayBounds:  // v1 is length reg (for Arm/Mips), v2 constant index
604        // v1 holds the constant array index.  Mips/Arm uses v2 for length, x86 reloads.
605        if (target_x86) {
606          OpRegMem(kOpMov, TargetReg(kArg1), v1, mirror::Array::LengthOffset().Int32Value());
607        } else {
608          OpRegCopy(TargetReg(kArg1), v1);
609        }
610        // Make sure the following LoadConstant doesn't mess with kArg1.
611        LockTemp(TargetReg(kArg1));
612        LoadConstant(TargetReg(kArg0), v2);
613        func_offset = QUICK_ENTRYPOINT_OFFSET(pThrowArrayBounds);
614        break;
615      case kThrowArrayBounds:
616        // Move v1 (array index) to kArg0 and v2 (array length) to kArg1
617        if (v2 != TargetReg(kArg0)) {
618          OpRegCopy(TargetReg(kArg0), v1);
619          if (target_x86) {
620            // x86 leaves the array pointer in v2, so load the array length that the handler expects
621            OpRegMem(kOpMov, TargetReg(kArg1), v2, mirror::Array::LengthOffset().Int32Value());
622          } else {
623            OpRegCopy(TargetReg(kArg1), v2);
624          }
625        } else {
626          if (v1 == TargetReg(kArg1)) {
627            // Swap v1 and v2, using kArg2 as a temp
628            OpRegCopy(TargetReg(kArg2), v1);
629            if (target_x86) {
630              // x86 leaves the array pointer in v2; load the array length that the handler expects
631              OpRegMem(kOpMov, TargetReg(kArg1), v2, mirror::Array::LengthOffset().Int32Value());
632            } else {
633              OpRegCopy(TargetReg(kArg1), v2);
634            }
635            OpRegCopy(TargetReg(kArg0), TargetReg(kArg2));
636          } else {
637            if (target_x86) {
638              // x86 leaves the array pointer in v2; load the array length that the handler expects
639              OpRegMem(kOpMov, TargetReg(kArg1), v2, mirror::Array::LengthOffset().Int32Value());
640            } else {
641              OpRegCopy(TargetReg(kArg1), v2);
642            }
643            OpRegCopy(TargetReg(kArg0), v1);
644          }
645        }
646        func_offset = QUICK_ENTRYPOINT_OFFSET(pThrowArrayBounds);
647        break;
648      case kThrowDivZero:
649        func_offset = QUICK_ENTRYPOINT_OFFSET(pThrowDivZero);
650        break;
651      case kThrowNoSuchMethod:
652        OpRegCopy(TargetReg(kArg0), v1);
653        func_offset =
654          QUICK_ENTRYPOINT_OFFSET(pThrowNoSuchMethod);
655        break;
656      case kThrowStackOverflow:
657        func_offset = QUICK_ENTRYPOINT_OFFSET(pThrowStackOverflow);
658        // Restore stack alignment
659        if (target_x86) {
660          OpRegImm(kOpAdd, TargetReg(kSp), frame_size_);
661        } else {
662          OpRegImm(kOpAdd, TargetReg(kSp), (num_core_spills_ + num_fp_spills_) * 4);
663        }
664        break;
665      default:
666        LOG(FATAL) << "Unexpected throw kind: " << lab->operands[0];
667    }
668    ClobberCallerSave();
669    int r_tgt = CallHelperSetup(func_offset);
670    CallHelper(r_tgt, func_offset, true /* MarkSafepointPC */);
671  }
672}
673
674void Mir2Lir::GenIGet(uint32_t field_idx, int opt_flags, OpSize size,
675                      RegLocation rl_dest, RegLocation rl_obj, bool is_long_or_double,
676                      bool is_object) {
677  int field_offset;
678  bool is_volatile;
679
680  bool fast_path = FastInstance(field_idx, false, &field_offset, &is_volatile);
681
682  if (fast_path && !SLOW_FIELD_PATH) {
683    RegLocation rl_result;
684    RegisterClass reg_class = oat_reg_class_by_size(size);
685    DCHECK_GE(field_offset, 0);
686    rl_obj = LoadValue(rl_obj, kCoreReg);
687    if (is_long_or_double) {
688      DCHECK(rl_dest.wide);
689      GenNullCheck(rl_obj.s_reg_low, rl_obj.low_reg, opt_flags);
690      if (cu_->instruction_set == kX86) {
691        rl_result = EvalLoc(rl_dest, reg_class, true);
692        GenNullCheck(rl_obj.s_reg_low, rl_obj.low_reg, opt_flags);
693        LoadBaseDispWide(rl_obj.low_reg, field_offset, rl_result.low_reg,
694                         rl_result.high_reg, rl_obj.s_reg_low);
695        if (is_volatile) {
696          GenMemBarrier(kLoadLoad);
697        }
698      } else {
699        int reg_ptr = AllocTemp();
700        OpRegRegImm(kOpAdd, reg_ptr, rl_obj.low_reg, field_offset);
701        rl_result = EvalLoc(rl_dest, reg_class, true);
702        LoadBaseDispWide(reg_ptr, 0, rl_result.low_reg, rl_result.high_reg, INVALID_SREG);
703        if (is_volatile) {
704          GenMemBarrier(kLoadLoad);
705        }
706        FreeTemp(reg_ptr);
707      }
708      StoreValueWide(rl_dest, rl_result);
709    } else {
710      rl_result = EvalLoc(rl_dest, reg_class, true);
711      GenNullCheck(rl_obj.s_reg_low, rl_obj.low_reg, opt_flags);
712      LoadBaseDisp(rl_obj.low_reg, field_offset, rl_result.low_reg,
713                   kWord, rl_obj.s_reg_low);
714      if (is_volatile) {
715        GenMemBarrier(kLoadLoad);
716      }
717      StoreValue(rl_dest, rl_result);
718    }
719  } else {
720    ThreadOffset getterOffset =
721        is_long_or_double ? QUICK_ENTRYPOINT_OFFSET(pGet64Instance)
722                          : (is_object ? QUICK_ENTRYPOINT_OFFSET(pGetObjInstance)
723                                       : QUICK_ENTRYPOINT_OFFSET(pGet32Instance));
724    CallRuntimeHelperImmRegLocation(getterOffset, field_idx, rl_obj, true);
725    if (is_long_or_double) {
726      RegLocation rl_result = GetReturnWide(rl_dest.fp);
727      StoreValueWide(rl_dest, rl_result);
728    } else {
729      RegLocation rl_result = GetReturn(rl_dest.fp);
730      StoreValue(rl_dest, rl_result);
731    }
732  }
733}
734
735void Mir2Lir::GenIPut(uint32_t field_idx, int opt_flags, OpSize size,
736                      RegLocation rl_src, RegLocation rl_obj, bool is_long_or_double,
737                      bool is_object) {
738  int field_offset;
739  bool is_volatile;
740
741  bool fast_path = FastInstance(field_idx, true, &field_offset, &is_volatile);
742  if (fast_path && !SLOW_FIELD_PATH) {
743    RegisterClass reg_class = oat_reg_class_by_size(size);
744    DCHECK_GE(field_offset, 0);
745    rl_obj = LoadValue(rl_obj, kCoreReg);
746    if (is_long_or_double) {
747      int reg_ptr;
748      rl_src = LoadValueWide(rl_src, kAnyReg);
749      GenNullCheck(rl_obj.s_reg_low, rl_obj.low_reg, opt_flags);
750      reg_ptr = AllocTemp();
751      OpRegRegImm(kOpAdd, reg_ptr, rl_obj.low_reg, field_offset);
752      if (is_volatile) {
753        GenMemBarrier(kStoreStore);
754      }
755      StoreBaseDispWide(reg_ptr, 0, rl_src.low_reg, rl_src.high_reg);
756      if (is_volatile) {
757        GenMemBarrier(kLoadLoad);
758      }
759      FreeTemp(reg_ptr);
760    } else {
761      rl_src = LoadValue(rl_src, reg_class);
762      GenNullCheck(rl_obj.s_reg_low, rl_obj.low_reg, opt_flags);
763      if (is_volatile) {
764        GenMemBarrier(kStoreStore);
765      }
766      StoreBaseDisp(rl_obj.low_reg, field_offset, rl_src.low_reg, kWord);
767      if (is_volatile) {
768        GenMemBarrier(kLoadLoad);
769      }
770      if (is_object && !mir_graph_->IsConstantNullRef(rl_src)) {
771        MarkGCCard(rl_src.low_reg, rl_obj.low_reg);
772      }
773    }
774  } else {
775    ThreadOffset setter_offset =
776        is_long_or_double ? QUICK_ENTRYPOINT_OFFSET(pSet64Instance)
777                          : (is_object ? QUICK_ENTRYPOINT_OFFSET(pSetObjInstance)
778                                       : QUICK_ENTRYPOINT_OFFSET(pSet32Instance));
779    CallRuntimeHelperImmRegLocationRegLocation(setter_offset, field_idx, rl_obj, rl_src, true);
780  }
781}
782
783void Mir2Lir::GenArrayObjPut(int opt_flags, RegLocation rl_array, RegLocation rl_index,
784                             RegLocation rl_src) {
785  bool needs_range_check = !(opt_flags & MIR_IGNORE_RANGE_CHECK);
786  bool needs_null_check = !((cu_->disable_opt & (1 << kNullCheckElimination)) &&
787      (opt_flags & MIR_IGNORE_NULL_CHECK));
788  ThreadOffset helper = needs_range_check
789      ? (needs_null_check ? QUICK_ENTRYPOINT_OFFSET(pAputObjectWithNullAndBoundCheck)
790                          : QUICK_ENTRYPOINT_OFFSET(pAputObjectWithBoundCheck))
791      : QUICK_ENTRYPOINT_OFFSET(pAputObject);
792  CallRuntimeHelperRegLocationRegLocationRegLocation(helper, rl_array, rl_index, rl_src, true);
793}
794
795void Mir2Lir::GenConstClass(uint32_t type_idx, RegLocation rl_dest) {
796  RegLocation rl_method = LoadCurrMethod();
797  int res_reg = AllocTemp();
798  RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
799  if (!cu_->compiler_driver->CanAccessTypeWithoutChecks(cu_->method_idx,
800                                                   *cu_->dex_file,
801                                                   type_idx)) {
802    // Call out to helper which resolves type and verifies access.
803    // Resolved type returned in kRet0.
804    CallRuntimeHelperImmReg(QUICK_ENTRYPOINT_OFFSET(pInitializeTypeAndVerifyAccess),
805                            type_idx, rl_method.low_reg, true);
806    RegLocation rl_result = GetReturn(false);
807    StoreValue(rl_dest, rl_result);
808  } else {
809    // We're don't need access checks, load type from dex cache
810    int32_t dex_cache_offset =
811        mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value();
812    LoadWordDisp(rl_method.low_reg, dex_cache_offset, res_reg);
813    int32_t offset_of_type =
814        mirror::Array::DataOffset(sizeof(mirror::Class*)).Int32Value() + (sizeof(mirror::Class*)
815                          * type_idx);
816    LoadWordDisp(res_reg, offset_of_type, rl_result.low_reg);
817    if (!cu_->compiler_driver->CanAssumeTypeIsPresentInDexCache(*cu_->dex_file,
818        type_idx) || SLOW_TYPE_PATH) {
819      // Slow path, at runtime test if type is null and if so initialize
820      FlushAllRegs();
821      LIR* branch1 = OpCmpImmBranch(kCondEq, rl_result.low_reg, 0, NULL);
822      // Resolved, store and hop over following code
823      StoreValue(rl_dest, rl_result);
824      /*
825       * Because we have stores of the target value on two paths,
826       * clobber temp tracking for the destination using the ssa name
827       */
828      ClobberSReg(rl_dest.s_reg_low);
829      LIR* branch2 = OpUnconditionalBranch(0);
830      // TUNING: move slow path to end & remove unconditional branch
831      LIR* target1 = NewLIR0(kPseudoTargetLabel);
832      // Call out to helper, which will return resolved type in kArg0
833      CallRuntimeHelperImmReg(QUICK_ENTRYPOINT_OFFSET(pInitializeType), type_idx,
834                              rl_method.low_reg, true);
835      RegLocation rl_result = GetReturn(false);
836      StoreValue(rl_dest, rl_result);
837      /*
838       * Because we have stores of the target value on two paths,
839       * clobber temp tracking for the destination using the ssa name
840       */
841      ClobberSReg(rl_dest.s_reg_low);
842      // Rejoin code paths
843      LIR* target2 = NewLIR0(kPseudoTargetLabel);
844      branch1->target = target1;
845      branch2->target = target2;
846    } else {
847      // Fast path, we're done - just store result
848      StoreValue(rl_dest, rl_result);
849    }
850  }
851}
852
853void Mir2Lir::GenConstString(uint32_t string_idx, RegLocation rl_dest) {
854  /* NOTE: Most strings should be available at compile time */
855  int32_t offset_of_string = mirror::Array::DataOffset(sizeof(mirror::String*)).Int32Value() +
856                 (sizeof(mirror::String*) * string_idx);
857  if (!cu_->compiler_driver->CanAssumeStringIsPresentInDexCache(
858      *cu_->dex_file, string_idx) || SLOW_STRING_PATH) {
859    // slow path, resolve string if not in dex cache
860    FlushAllRegs();
861    LockCallTemps();  // Using explicit registers
862
863    // If the Method* is already in a register, we can save a copy.
864    RegLocation rl_method = mir_graph_->GetMethodLoc();
865    int r_method;
866    if (rl_method.location == kLocPhysReg) {
867      // A temp would conflict with register use below.
868      DCHECK(!IsTemp(rl_method.low_reg));
869      r_method = rl_method.low_reg;
870    } else {
871      r_method = TargetReg(kArg2);
872      LoadCurrMethodDirect(r_method);
873    }
874    LoadWordDisp(r_method, mirror::ArtMethod::DexCacheStringsOffset().Int32Value(),
875                 TargetReg(kArg0));
876
877    // Might call out to helper, which will return resolved string in kRet0
878    int r_tgt = CallHelperSetup(QUICK_ENTRYPOINT_OFFSET(pResolveString));
879    LoadWordDisp(TargetReg(kArg0), offset_of_string, TargetReg(kRet0));
880    if (cu_->instruction_set == kThumb2) {
881      LoadConstant(TargetReg(kArg1), string_idx);
882      OpRegImm(kOpCmp, TargetReg(kRet0), 0);  // Is resolved?
883      GenBarrier();
884      // For testing, always force through helper
885      if (!EXERCISE_SLOWEST_STRING_PATH) {
886        OpIT(kCondEq, "T");
887      }
888      // The copy MUST generate exactly one instruction (for OpIT).
889      DCHECK_NE(TargetReg(kArg0), r_method);
890      OpRegCopy(TargetReg(kArg0), r_method);   // .eq
891
892      LIR* call_inst = OpReg(kOpBlx, r_tgt);    // .eq, helper(Method*, string_idx)
893      MarkSafepointPC(call_inst);
894      FreeTemp(r_tgt);
895    } else if (cu_->instruction_set == kMips) {
896      LIR* branch = OpCmpImmBranch(kCondNe, TargetReg(kRet0), 0, NULL);
897      LoadConstant(TargetReg(kArg1), string_idx);
898      OpRegCopy(TargetReg(kArg0), r_method);   // .eq
899      LIR* call_inst = OpReg(kOpBlx, r_tgt);
900      MarkSafepointPC(call_inst);
901      FreeTemp(r_tgt);
902      LIR* target = NewLIR0(kPseudoTargetLabel);
903      branch->target = target;
904    } else {
905      DCHECK_EQ(cu_->instruction_set, kX86);
906      LIR* branch = OpCmpImmBranch(kCondNe, TargetReg(kRet0), 0, NULL);
907      LoadConstant(TargetReg(kArg1), string_idx);
908      CallRuntimeHelperRegReg(QUICK_ENTRYPOINT_OFFSET(pResolveString), r_method,
909                              TargetReg(kArg1), true);
910      LIR* target = NewLIR0(kPseudoTargetLabel);
911      branch->target = target;
912    }
913    GenBarrier();
914    StoreValue(rl_dest, GetReturn(false));
915  } else {
916    RegLocation rl_method = LoadCurrMethod();
917    int res_reg = AllocTemp();
918    RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
919    LoadWordDisp(rl_method.low_reg,
920                 mirror::ArtMethod::DexCacheStringsOffset().Int32Value(), res_reg);
921    LoadWordDisp(res_reg, offset_of_string, rl_result.low_reg);
922    StoreValue(rl_dest, rl_result);
923  }
924}
925
926/*
927 * Let helper function take care of everything.  Will
928 * call Class::NewInstanceFromCode(type_idx, method);
929 */
930void Mir2Lir::GenNewInstance(uint32_t type_idx, RegLocation rl_dest) {
931  FlushAllRegs();  /* Everything to home location */
932  // alloc will always check for resolution, do we also need to verify
933  // access because the verifier was unable to?
934  ThreadOffset func_offset(-1);
935  const DexFile* dex_file = cu_->dex_file;
936  CompilerDriver* driver = cu_->compiler_driver;
937  if (driver->CanAccessInstantiableTypeWithoutChecks(
938      cu_->method_idx, *dex_file, type_idx)) {
939    bool is_type_initialized;
940    bool use_direct_type_ptr;
941    uintptr_t direct_type_ptr;
942    if (kEmbedClassInCode &&
943        driver->CanEmbedTypeInCode(*dex_file, type_idx,
944                                   &is_type_initialized, &use_direct_type_ptr, &direct_type_ptr)) {
945      // The fast path.
946      if (!use_direct_type_ptr) {
947        // Use the literal pool and a PC-relative load from a data word.
948        LIR* data_target = ScanLiteralPool(class_literal_list_, type_idx, 0);
949        if (data_target == nullptr) {
950          data_target = AddWordData(&class_literal_list_, type_idx);
951        }
952        LIR* load_pc_rel = OpPcRelLoad(TargetReg(kArg0), data_target);
953        AppendLIR(load_pc_rel);
954        if (!is_type_initialized) {
955          func_offset = QUICK_ENTRYPOINT_OFFSET(pAllocObjectResolved);
956          CallRuntimeHelperRegMethod(func_offset, TargetReg(kArg0), true);
957        } else {
958          func_offset = QUICK_ENTRYPOINT_OFFSET(pAllocObjectInitialized);
959          CallRuntimeHelperRegMethod(func_offset, TargetReg(kArg0), true);
960        }
961      } else {
962        // Use the direct pointer.
963        if (!is_type_initialized) {
964          func_offset = QUICK_ENTRYPOINT_OFFSET(pAllocObjectResolved);
965          CallRuntimeHelperImmMethod(func_offset, direct_type_ptr, true);
966        } else {
967          func_offset = QUICK_ENTRYPOINT_OFFSET(pAllocObjectInitialized);
968          CallRuntimeHelperImmMethod(func_offset, direct_type_ptr, true);
969        }
970      }
971    } else {
972      // The slow path.
973      DCHECK_EQ(func_offset.Int32Value(), -1);
974      func_offset = QUICK_ENTRYPOINT_OFFSET(pAllocObject);
975      CallRuntimeHelperImmMethod(func_offset, type_idx, true);
976    }
977    DCHECK_NE(func_offset.Int32Value(), -1);
978  } else {
979    func_offset = QUICK_ENTRYPOINT_OFFSET(pAllocObjectWithAccessCheck);
980    CallRuntimeHelperImmMethod(func_offset, type_idx, true);
981  }
982  RegLocation rl_result = GetReturn(false);
983  StoreValue(rl_dest, rl_result);
984}
985
986void Mir2Lir::GenThrow(RegLocation rl_src) {
987  FlushAllRegs();
988  CallRuntimeHelperRegLocation(QUICK_ENTRYPOINT_OFFSET(pDeliverException), rl_src, true);
989}
990
991// For final classes there are no sub-classes to check and so we can answer the instance-of
992// question with simple comparisons.
993void Mir2Lir::GenInstanceofFinal(bool use_declaring_class, uint32_t type_idx, RegLocation rl_dest,
994                                 RegLocation rl_src) {
995  // X86 has its own implementation.
996  DCHECK_NE(cu_->instruction_set, kX86);
997
998  RegLocation object = LoadValue(rl_src, kCoreReg);
999  RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
1000  int result_reg = rl_result.low_reg;
1001  if (result_reg == object.low_reg) {
1002    result_reg = AllocTypedTemp(false, kCoreReg);
1003  }
1004  LoadConstant(result_reg, 0);     // assume false
1005  LIR* null_branchover = OpCmpImmBranch(kCondEq, object.low_reg, 0, NULL);
1006
1007  int check_class = AllocTypedTemp(false, kCoreReg);
1008  int object_class = AllocTypedTemp(false, kCoreReg);
1009
1010  LoadCurrMethodDirect(check_class);
1011  if (use_declaring_class) {
1012    LoadWordDisp(check_class, mirror::ArtMethod::DeclaringClassOffset().Int32Value(),
1013                 check_class);
1014    LoadWordDisp(object.low_reg,  mirror::Object::ClassOffset().Int32Value(), object_class);
1015  } else {
1016    LoadWordDisp(check_class, mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value(),
1017                 check_class);
1018    LoadWordDisp(object.low_reg,  mirror::Object::ClassOffset().Int32Value(), object_class);
1019    int32_t offset_of_type =
1020      mirror::Array::DataOffset(sizeof(mirror::Class*)).Int32Value() +
1021      (sizeof(mirror::Class*) * type_idx);
1022    LoadWordDisp(check_class, offset_of_type, check_class);
1023  }
1024
1025  LIR* ne_branchover = NULL;
1026  if (cu_->instruction_set == kThumb2) {
1027    OpRegReg(kOpCmp, check_class, object_class);  // Same?
1028    OpIT(kCondEq, "");   // if-convert the test
1029    LoadConstant(result_reg, 1);     // .eq case - load true
1030  } else {
1031    ne_branchover = OpCmpBranch(kCondNe, check_class, object_class, NULL);
1032    LoadConstant(result_reg, 1);     // eq case - load true
1033  }
1034  LIR* target = NewLIR0(kPseudoTargetLabel);
1035  null_branchover->target = target;
1036  if (ne_branchover != NULL) {
1037    ne_branchover->target = target;
1038  }
1039  FreeTemp(object_class);
1040  FreeTemp(check_class);
1041  if (IsTemp(result_reg)) {
1042    OpRegCopy(rl_result.low_reg, result_reg);
1043    FreeTemp(result_reg);
1044  }
1045  StoreValue(rl_dest, rl_result);
1046}
1047
1048void Mir2Lir::GenInstanceofCallingHelper(bool needs_access_check, bool type_known_final,
1049                                         bool type_known_abstract, bool use_declaring_class,
1050                                         bool can_assume_type_is_in_dex_cache,
1051                                         uint32_t type_idx, RegLocation rl_dest,
1052                                         RegLocation rl_src) {
1053  FlushAllRegs();
1054  // May generate a call - use explicit registers
1055  LockCallTemps();
1056  LoadCurrMethodDirect(TargetReg(kArg1));  // kArg1 <= current Method*
1057  int class_reg = TargetReg(kArg2);  // kArg2 will hold the Class*
1058  if (needs_access_check) {
1059    // Check we have access to type_idx and if not throw IllegalAccessError,
1060    // returns Class* in kArg0
1061    CallRuntimeHelperImm(QUICK_ENTRYPOINT_OFFSET(pInitializeTypeAndVerifyAccess),
1062                         type_idx, true);
1063    OpRegCopy(class_reg, TargetReg(kRet0));  // Align usage with fast path
1064    LoadValueDirectFixed(rl_src, TargetReg(kArg0));  // kArg0 <= ref
1065  } else if (use_declaring_class) {
1066    LoadValueDirectFixed(rl_src, TargetReg(kArg0));  // kArg0 <= ref
1067    LoadWordDisp(TargetReg(kArg1),
1068                 mirror::ArtMethod::DeclaringClassOffset().Int32Value(), class_reg);
1069  } else {
1070    // Load dex cache entry into class_reg (kArg2)
1071    LoadValueDirectFixed(rl_src, TargetReg(kArg0));  // kArg0 <= ref
1072    LoadWordDisp(TargetReg(kArg1),
1073                 mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value(), class_reg);
1074    int32_t offset_of_type =
1075        mirror::Array::DataOffset(sizeof(mirror::Class*)).Int32Value() + (sizeof(mirror::Class*)
1076        * type_idx);
1077    LoadWordDisp(class_reg, offset_of_type, class_reg);
1078    if (!can_assume_type_is_in_dex_cache) {
1079      // Need to test presence of type in dex cache at runtime
1080      LIR* hop_branch = OpCmpImmBranch(kCondNe, class_reg, 0, NULL);
1081      // Not resolved
1082      // Call out to helper, which will return resolved type in kRet0
1083      CallRuntimeHelperImm(QUICK_ENTRYPOINT_OFFSET(pInitializeType), type_idx, true);
1084      OpRegCopy(TargetReg(kArg2), TargetReg(kRet0));  // Align usage with fast path
1085      LoadValueDirectFixed(rl_src, TargetReg(kArg0));  /* reload Ref */
1086      // Rejoin code paths
1087      LIR* hop_target = NewLIR0(kPseudoTargetLabel);
1088      hop_branch->target = hop_target;
1089    }
1090  }
1091  /* kArg0 is ref, kArg2 is class. If ref==null, use directly as bool result */
1092  RegLocation rl_result = GetReturn(false);
1093  if (cu_->instruction_set == kMips) {
1094    // On MIPS rArg0 != rl_result, place false in result if branch is taken.
1095    LoadConstant(rl_result.low_reg, 0);
1096  }
1097  LIR* branch1 = OpCmpImmBranch(kCondEq, TargetReg(kArg0), 0, NULL);
1098
1099  /* load object->klass_ */
1100  DCHECK_EQ(mirror::Object::ClassOffset().Int32Value(), 0);
1101  LoadWordDisp(TargetReg(kArg0),  mirror::Object::ClassOffset().Int32Value(), TargetReg(kArg1));
1102  /* kArg0 is ref, kArg1 is ref->klass_, kArg2 is class */
1103  LIR* branchover = NULL;
1104  if (type_known_final) {
1105    // rl_result == ref == null == 0.
1106    if (cu_->instruction_set == kThumb2) {
1107      OpRegReg(kOpCmp, TargetReg(kArg1), TargetReg(kArg2));  // Same?
1108      OpIT(kCondEq, "E");   // if-convert the test
1109      LoadConstant(rl_result.low_reg, 1);     // .eq case - load true
1110      LoadConstant(rl_result.low_reg, 0);     // .ne case - load false
1111    } else {
1112      LoadConstant(rl_result.low_reg, 0);     // ne case - load false
1113      branchover = OpCmpBranch(kCondNe, TargetReg(kArg1), TargetReg(kArg2), NULL);
1114      LoadConstant(rl_result.low_reg, 1);     // eq case - load true
1115    }
1116  } else {
1117    if (cu_->instruction_set == kThumb2) {
1118      int r_tgt = LoadHelper(QUICK_ENTRYPOINT_OFFSET(pInstanceofNonTrivial));
1119      if (!type_known_abstract) {
1120      /* Uses conditional nullification */
1121        OpRegReg(kOpCmp, TargetReg(kArg1), TargetReg(kArg2));  // Same?
1122        OpIT(kCondEq, "EE");   // if-convert the test
1123        LoadConstant(TargetReg(kArg0), 1);     // .eq case - load true
1124      }
1125      OpRegCopy(TargetReg(kArg0), TargetReg(kArg2));    // .ne case - arg0 <= class
1126      OpReg(kOpBlx, r_tgt);    // .ne case: helper(class, ref->class)
1127      FreeTemp(r_tgt);
1128    } else {
1129      if (!type_known_abstract) {
1130        /* Uses branchovers */
1131        LoadConstant(rl_result.low_reg, 1);     // assume true
1132        branchover = OpCmpBranch(kCondEq, TargetReg(kArg1), TargetReg(kArg2), NULL);
1133      }
1134      if (cu_->instruction_set != kX86) {
1135        int r_tgt = LoadHelper(QUICK_ENTRYPOINT_OFFSET(pInstanceofNonTrivial));
1136        OpRegCopy(TargetReg(kArg0), TargetReg(kArg2));    // .ne case - arg0 <= class
1137        OpReg(kOpBlx, r_tgt);    // .ne case: helper(class, ref->class)
1138        FreeTemp(r_tgt);
1139      } else {
1140        OpRegCopy(TargetReg(kArg0), TargetReg(kArg2));
1141        OpThreadMem(kOpBlx, QUICK_ENTRYPOINT_OFFSET(pInstanceofNonTrivial));
1142      }
1143    }
1144  }
1145  // TODO: only clobber when type isn't final?
1146  ClobberCallerSave();
1147  /* branch targets here */
1148  LIR* target = NewLIR0(kPseudoTargetLabel);
1149  StoreValue(rl_dest, rl_result);
1150  branch1->target = target;
1151  if (branchover != NULL) {
1152    branchover->target = target;
1153  }
1154}
1155
1156void Mir2Lir::GenInstanceof(uint32_t type_idx, RegLocation rl_dest, RegLocation rl_src) {
1157  bool type_known_final, type_known_abstract, use_declaring_class;
1158  bool needs_access_check = !cu_->compiler_driver->CanAccessTypeWithoutChecks(cu_->method_idx,
1159                                                                              *cu_->dex_file,
1160                                                                              type_idx,
1161                                                                              &type_known_final,
1162                                                                              &type_known_abstract,
1163                                                                              &use_declaring_class);
1164  bool can_assume_type_is_in_dex_cache = !needs_access_check &&
1165      cu_->compiler_driver->CanAssumeTypeIsPresentInDexCache(*cu_->dex_file, type_idx);
1166
1167  if ((use_declaring_class || can_assume_type_is_in_dex_cache) && type_known_final) {
1168    GenInstanceofFinal(use_declaring_class, type_idx, rl_dest, rl_src);
1169  } else {
1170    GenInstanceofCallingHelper(needs_access_check, type_known_final, type_known_abstract,
1171                               use_declaring_class, can_assume_type_is_in_dex_cache,
1172                               type_idx, rl_dest, rl_src);
1173  }
1174}
1175
1176void Mir2Lir::GenCheckCast(uint32_t insn_idx, uint32_t type_idx, RegLocation rl_src) {
1177  bool type_known_final, type_known_abstract, use_declaring_class;
1178  bool needs_access_check = !cu_->compiler_driver->CanAccessTypeWithoutChecks(cu_->method_idx,
1179                                                                              *cu_->dex_file,
1180                                                                              type_idx,
1181                                                                              &type_known_final,
1182                                                                              &type_known_abstract,
1183                                                                              &use_declaring_class);
1184  // Note: currently type_known_final is unused, as optimizing will only improve the performance
1185  // of the exception throw path.
1186  DexCompilationUnit* cu = mir_graph_->GetCurrentDexCompilationUnit();
1187  if (!needs_access_check && cu_->compiler_driver->IsSafeCast(cu, insn_idx)) {
1188    // Verifier type analysis proved this check cast would never cause an exception.
1189    return;
1190  }
1191  FlushAllRegs();
1192  // May generate a call - use explicit registers
1193  LockCallTemps();
1194  LoadCurrMethodDirect(TargetReg(kArg1));  // kArg1 <= current Method*
1195  int class_reg = TargetReg(kArg2);  // kArg2 will hold the Class*
1196  if (needs_access_check) {
1197    // Check we have access to type_idx and if not throw IllegalAccessError,
1198    // returns Class* in kRet0
1199    // InitializeTypeAndVerifyAccess(idx, method)
1200    CallRuntimeHelperImmReg(QUICK_ENTRYPOINT_OFFSET(pInitializeTypeAndVerifyAccess),
1201                            type_idx, TargetReg(kArg1), true);
1202    OpRegCopy(class_reg, TargetReg(kRet0));  // Align usage with fast path
1203  } else if (use_declaring_class) {
1204    LoadWordDisp(TargetReg(kArg1),
1205                 mirror::ArtMethod::DeclaringClassOffset().Int32Value(), class_reg);
1206  } else {
1207    // Load dex cache entry into class_reg (kArg2)
1208    LoadWordDisp(TargetReg(kArg1),
1209                 mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value(), class_reg);
1210    int32_t offset_of_type =
1211        mirror::Array::DataOffset(sizeof(mirror::Class*)).Int32Value() +
1212        (sizeof(mirror::Class*) * type_idx);
1213    LoadWordDisp(class_reg, offset_of_type, class_reg);
1214    if (!cu_->compiler_driver->CanAssumeTypeIsPresentInDexCache(*cu_->dex_file, type_idx)) {
1215      // Need to test presence of type in dex cache at runtime
1216      LIR* hop_branch = OpCmpImmBranch(kCondNe, class_reg, 0, NULL);
1217      // Not resolved
1218      // Call out to helper, which will return resolved type in kArg0
1219      // InitializeTypeFromCode(idx, method)
1220      CallRuntimeHelperImmReg(QUICK_ENTRYPOINT_OFFSET(pInitializeType), type_idx,
1221                              TargetReg(kArg1), true);
1222      OpRegCopy(class_reg, TargetReg(kRet0));  // Align usage with fast path
1223      // Rejoin code paths
1224      LIR* hop_target = NewLIR0(kPseudoTargetLabel);
1225      hop_branch->target = hop_target;
1226    }
1227  }
1228  // At this point, class_reg (kArg2) has class
1229  LoadValueDirectFixed(rl_src, TargetReg(kArg0));  // kArg0 <= ref
1230  /* Null is OK - continue */
1231  LIR* branch1 = OpCmpImmBranch(kCondEq, TargetReg(kArg0), 0, NULL);
1232  /* load object->klass_ */
1233  DCHECK_EQ(mirror::Object::ClassOffset().Int32Value(), 0);
1234  LoadWordDisp(TargetReg(kArg0), mirror::Object::ClassOffset().Int32Value(), TargetReg(kArg1));
1235  /* kArg1 now contains object->klass_ */
1236  LIR* branch2 = NULL;
1237  if (!type_known_abstract) {
1238    branch2 = OpCmpBranch(kCondEq, TargetReg(kArg1), class_reg, NULL);
1239  }
1240  CallRuntimeHelperRegReg(QUICK_ENTRYPOINT_OFFSET(pCheckCast), TargetReg(kArg2),
1241                          TargetReg(kArg1), true);
1242  /* branch target here */
1243  LIR* target = NewLIR0(kPseudoTargetLabel);
1244  branch1->target = target;
1245  if (branch2 != NULL) {
1246    branch2->target = target;
1247  }
1248}
1249
1250void Mir2Lir::GenLong3Addr(OpKind first_op, OpKind second_op, RegLocation rl_dest,
1251                           RegLocation rl_src1, RegLocation rl_src2) {
1252  RegLocation rl_result;
1253  if (cu_->instruction_set == kThumb2) {
1254    /*
1255     * NOTE:  This is the one place in the code in which we might have
1256     * as many as six live temporary registers.  There are 5 in the normal
1257     * set for Arm.  Until we have spill capabilities, temporarily add
1258     * lr to the temp set.  It is safe to do this locally, but note that
1259     * lr is used explicitly elsewhere in the code generator and cannot
1260     * normally be used as a general temp register.
1261     */
1262    MarkTemp(TargetReg(kLr));   // Add lr to the temp pool
1263    FreeTemp(TargetReg(kLr));   // and make it available
1264  }
1265  rl_src1 = LoadValueWide(rl_src1, kCoreReg);
1266  rl_src2 = LoadValueWide(rl_src2, kCoreReg);
1267  rl_result = EvalLoc(rl_dest, kCoreReg, true);
1268  // The longs may overlap - use intermediate temp if so
1269  if ((rl_result.low_reg == rl_src1.high_reg) || (rl_result.low_reg == rl_src2.high_reg)) {
1270    int t_reg = AllocTemp();
1271    OpRegRegReg(first_op, t_reg, rl_src1.low_reg, rl_src2.low_reg);
1272    OpRegRegReg(second_op, rl_result.high_reg, rl_src1.high_reg, rl_src2.high_reg);
1273    OpRegCopy(rl_result.low_reg, t_reg);
1274    FreeTemp(t_reg);
1275  } else {
1276    OpRegRegReg(first_op, rl_result.low_reg, rl_src1.low_reg, rl_src2.low_reg);
1277    OpRegRegReg(second_op, rl_result.high_reg, rl_src1.high_reg,
1278                rl_src2.high_reg);
1279  }
1280  /*
1281   * NOTE: If rl_dest refers to a frame variable in a large frame, the
1282   * following StoreValueWide might need to allocate a temp register.
1283   * To further work around the lack of a spill capability, explicitly
1284   * free any temps from rl_src1 & rl_src2 that aren't still live in rl_result.
1285   * Remove when spill is functional.
1286   */
1287  FreeRegLocTemps(rl_result, rl_src1);
1288  FreeRegLocTemps(rl_result, rl_src2);
1289  StoreValueWide(rl_dest, rl_result);
1290  if (cu_->instruction_set == kThumb2) {
1291    Clobber(TargetReg(kLr));
1292    UnmarkTemp(TargetReg(kLr));  // Remove lr from the temp pool
1293  }
1294}
1295
1296
1297void Mir2Lir::GenShiftOpLong(Instruction::Code opcode, RegLocation rl_dest,
1298                             RegLocation rl_src1, RegLocation rl_shift) {
1299  ThreadOffset func_offset(-1);
1300
1301  switch (opcode) {
1302    case Instruction::SHL_LONG:
1303    case Instruction::SHL_LONG_2ADDR:
1304      func_offset = QUICK_ENTRYPOINT_OFFSET(pShlLong);
1305      break;
1306    case Instruction::SHR_LONG:
1307    case Instruction::SHR_LONG_2ADDR:
1308      func_offset = QUICK_ENTRYPOINT_OFFSET(pShrLong);
1309      break;
1310    case Instruction::USHR_LONG:
1311    case Instruction::USHR_LONG_2ADDR:
1312      func_offset = QUICK_ENTRYPOINT_OFFSET(pUshrLong);
1313      break;
1314    default:
1315      LOG(FATAL) << "Unexpected case";
1316  }
1317  FlushAllRegs();   /* Send everything to home location */
1318  CallRuntimeHelperRegLocationRegLocation(func_offset, rl_src1, rl_shift, false);
1319  RegLocation rl_result = GetReturnWide(false);
1320  StoreValueWide(rl_dest, rl_result);
1321}
1322
1323
1324void Mir2Lir::GenArithOpInt(Instruction::Code opcode, RegLocation rl_dest,
1325                            RegLocation rl_src1, RegLocation rl_src2) {
1326  DCHECK_NE(cu_->instruction_set, kX86);
1327  OpKind op = kOpBkpt;
1328  bool is_div_rem = false;
1329  bool check_zero = false;
1330  bool unary = false;
1331  RegLocation rl_result;
1332  bool shift_op = false;
1333  switch (opcode) {
1334    case Instruction::NEG_INT:
1335      op = kOpNeg;
1336      unary = true;
1337      break;
1338    case Instruction::NOT_INT:
1339      op = kOpMvn;
1340      unary = true;
1341      break;
1342    case Instruction::ADD_INT:
1343    case Instruction::ADD_INT_2ADDR:
1344      op = kOpAdd;
1345      break;
1346    case Instruction::SUB_INT:
1347    case Instruction::SUB_INT_2ADDR:
1348      op = kOpSub;
1349      break;
1350    case Instruction::MUL_INT:
1351    case Instruction::MUL_INT_2ADDR:
1352      op = kOpMul;
1353      break;
1354    case Instruction::DIV_INT:
1355    case Instruction::DIV_INT_2ADDR:
1356      check_zero = true;
1357      op = kOpDiv;
1358      is_div_rem = true;
1359      break;
1360    /* NOTE: returns in kArg1 */
1361    case Instruction::REM_INT:
1362    case Instruction::REM_INT_2ADDR:
1363      check_zero = true;
1364      op = kOpRem;
1365      is_div_rem = true;
1366      break;
1367    case Instruction::AND_INT:
1368    case Instruction::AND_INT_2ADDR:
1369      op = kOpAnd;
1370      break;
1371    case Instruction::OR_INT:
1372    case Instruction::OR_INT_2ADDR:
1373      op = kOpOr;
1374      break;
1375    case Instruction::XOR_INT:
1376    case Instruction::XOR_INT_2ADDR:
1377      op = kOpXor;
1378      break;
1379    case Instruction::SHL_INT:
1380    case Instruction::SHL_INT_2ADDR:
1381      shift_op = true;
1382      op = kOpLsl;
1383      break;
1384    case Instruction::SHR_INT:
1385    case Instruction::SHR_INT_2ADDR:
1386      shift_op = true;
1387      op = kOpAsr;
1388      break;
1389    case Instruction::USHR_INT:
1390    case Instruction::USHR_INT_2ADDR:
1391      shift_op = true;
1392      op = kOpLsr;
1393      break;
1394    default:
1395      LOG(FATAL) << "Invalid word arith op: " << opcode;
1396  }
1397  if (!is_div_rem) {
1398    if (unary) {
1399      rl_src1 = LoadValue(rl_src1, kCoreReg);
1400      rl_result = EvalLoc(rl_dest, kCoreReg, true);
1401      OpRegReg(op, rl_result.low_reg, rl_src1.low_reg);
1402    } else {
1403      if (shift_op) {
1404        int t_reg = INVALID_REG;
1405        rl_src2 = LoadValue(rl_src2, kCoreReg);
1406        t_reg = AllocTemp();
1407        OpRegRegImm(kOpAnd, t_reg, rl_src2.low_reg, 31);
1408        rl_src1 = LoadValue(rl_src1, kCoreReg);
1409        rl_result = EvalLoc(rl_dest, kCoreReg, true);
1410        OpRegRegReg(op, rl_result.low_reg, rl_src1.low_reg, t_reg);
1411        FreeTemp(t_reg);
1412      } else {
1413        rl_src1 = LoadValue(rl_src1, kCoreReg);
1414        rl_src2 = LoadValue(rl_src2, kCoreReg);
1415        rl_result = EvalLoc(rl_dest, kCoreReg, true);
1416        OpRegRegReg(op, rl_result.low_reg, rl_src1.low_reg, rl_src2.low_reg);
1417      }
1418    }
1419    StoreValue(rl_dest, rl_result);
1420  } else {
1421    bool done = false;      // Set to true if we happen to find a way to use a real instruction.
1422    if (cu_->instruction_set == kMips) {
1423      rl_src1 = LoadValue(rl_src1, kCoreReg);
1424      rl_src2 = LoadValue(rl_src2, kCoreReg);
1425      if (check_zero) {
1426          GenImmedCheck(kCondEq, rl_src2.low_reg, 0, kThrowDivZero);
1427      }
1428      rl_result = GenDivRem(rl_dest, rl_src1.low_reg, rl_src2.low_reg, op == kOpDiv);
1429      done = true;
1430    } else if (cu_->instruction_set == kThumb2) {
1431      if (cu_->GetInstructionSetFeatures().HasDivideInstruction()) {
1432        // Use ARM SDIV instruction for division.  For remainder we also need to
1433        // calculate using a MUL and subtract.
1434        rl_src1 = LoadValue(rl_src1, kCoreReg);
1435        rl_src2 = LoadValue(rl_src2, kCoreReg);
1436        if (check_zero) {
1437            GenImmedCheck(kCondEq, rl_src2.low_reg, 0, kThrowDivZero);
1438        }
1439        rl_result = GenDivRem(rl_dest, rl_src1.low_reg, rl_src2.low_reg, op == kOpDiv);
1440        done = true;
1441      }
1442    }
1443
1444    // If we haven't already generated the code use the callout function.
1445    if (!done) {
1446      ThreadOffset func_offset = QUICK_ENTRYPOINT_OFFSET(pIdivmod);
1447      FlushAllRegs();   /* Send everything to home location */
1448      LoadValueDirectFixed(rl_src2, TargetReg(kArg1));
1449      int r_tgt = CallHelperSetup(func_offset);
1450      LoadValueDirectFixed(rl_src1, TargetReg(kArg0));
1451      if (check_zero) {
1452        GenImmedCheck(kCondEq, TargetReg(kArg1), 0, kThrowDivZero);
1453      }
1454      // NOTE: callout here is not a safepoint.
1455      CallHelper(r_tgt, func_offset, false /* not a safepoint */);
1456      if (op == kOpDiv)
1457        rl_result = GetReturn(false);
1458      else
1459        rl_result = GetReturnAlt();
1460    }
1461    StoreValue(rl_dest, rl_result);
1462  }
1463}
1464
1465/*
1466 * The following are the first-level codegen routines that analyze the format
1467 * of each bytecode then either dispatch special purpose codegen routines
1468 * or produce corresponding Thumb instructions directly.
1469 */
1470
1471// Returns true if no more than two bits are set in 'x'.
1472static bool IsPopCountLE2(unsigned int x) {
1473  x &= x - 1;
1474  return (x & (x - 1)) == 0;
1475}
1476
1477// Returns true if it added instructions to 'cu' to divide 'rl_src' by 'lit'
1478// and store the result in 'rl_dest'.
1479bool Mir2Lir::HandleEasyDivRem(Instruction::Code dalvik_opcode, bool is_div,
1480                               RegLocation rl_src, RegLocation rl_dest, int lit) {
1481  if ((lit < 2) || ((cu_->instruction_set != kThumb2) && !IsPowerOfTwo(lit))) {
1482    return false;
1483  }
1484  // No divide instruction for Arm, so check for more special cases
1485  if ((cu_->instruction_set == kThumb2) && !IsPowerOfTwo(lit)) {
1486    return SmallLiteralDivRem(dalvik_opcode, is_div, rl_src, rl_dest, lit);
1487  }
1488  int k = LowestSetBit(lit);
1489  if (k >= 30) {
1490    // Avoid special cases.
1491    return false;
1492  }
1493  rl_src = LoadValue(rl_src, kCoreReg);
1494  RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
1495  if (is_div) {
1496    int t_reg = AllocTemp();
1497    if (lit == 2) {
1498      // Division by 2 is by far the most common division by constant.
1499      OpRegRegImm(kOpLsr, t_reg, rl_src.low_reg, 32 - k);
1500      OpRegRegReg(kOpAdd, t_reg, t_reg, rl_src.low_reg);
1501      OpRegRegImm(kOpAsr, rl_result.low_reg, t_reg, k);
1502    } else {
1503      OpRegRegImm(kOpAsr, t_reg, rl_src.low_reg, 31);
1504      OpRegRegImm(kOpLsr, t_reg, t_reg, 32 - k);
1505      OpRegRegReg(kOpAdd, t_reg, t_reg, rl_src.low_reg);
1506      OpRegRegImm(kOpAsr, rl_result.low_reg, t_reg, k);
1507    }
1508  } else {
1509    int t_reg1 = AllocTemp();
1510    int t_reg2 = AllocTemp();
1511    if (lit == 2) {
1512      OpRegRegImm(kOpLsr, t_reg1, rl_src.low_reg, 32 - k);
1513      OpRegRegReg(kOpAdd, t_reg2, t_reg1, rl_src.low_reg);
1514      OpRegRegImm(kOpAnd, t_reg2, t_reg2, lit -1);
1515      OpRegRegReg(kOpSub, rl_result.low_reg, t_reg2, t_reg1);
1516    } else {
1517      OpRegRegImm(kOpAsr, t_reg1, rl_src.low_reg, 31);
1518      OpRegRegImm(kOpLsr, t_reg1, t_reg1, 32 - k);
1519      OpRegRegReg(kOpAdd, t_reg2, t_reg1, rl_src.low_reg);
1520      OpRegRegImm(kOpAnd, t_reg2, t_reg2, lit - 1);
1521      OpRegRegReg(kOpSub, rl_result.low_reg, t_reg2, t_reg1);
1522    }
1523  }
1524  StoreValue(rl_dest, rl_result);
1525  return true;
1526}
1527
1528// Returns true if it added instructions to 'cu' to multiply 'rl_src' by 'lit'
1529// and store the result in 'rl_dest'.
1530bool Mir2Lir::HandleEasyMultiply(RegLocation rl_src, RegLocation rl_dest, int lit) {
1531  // Can we simplify this multiplication?
1532  bool power_of_two = false;
1533  bool pop_count_le2 = false;
1534  bool power_of_two_minus_one = false;
1535  if (lit < 2) {
1536    // Avoid special cases.
1537    return false;
1538  } else if (IsPowerOfTwo(lit)) {
1539    power_of_two = true;
1540  } else if (IsPopCountLE2(lit)) {
1541    pop_count_le2 = true;
1542  } else if (IsPowerOfTwo(lit + 1)) {
1543    power_of_two_minus_one = true;
1544  } else {
1545    return false;
1546  }
1547  rl_src = LoadValue(rl_src, kCoreReg);
1548  RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
1549  if (power_of_two) {
1550    // Shift.
1551    OpRegRegImm(kOpLsl, rl_result.low_reg, rl_src.low_reg, LowestSetBit(lit));
1552  } else if (pop_count_le2) {
1553    // Shift and add and shift.
1554    int first_bit = LowestSetBit(lit);
1555    int second_bit = LowestSetBit(lit ^ (1 << first_bit));
1556    GenMultiplyByTwoBitMultiplier(rl_src, rl_result, lit, first_bit, second_bit);
1557  } else {
1558    // Reverse subtract: (src << (shift + 1)) - src.
1559    DCHECK(power_of_two_minus_one);
1560    // TUNING: rsb dst, src, src lsl#LowestSetBit(lit + 1)
1561    int t_reg = AllocTemp();
1562    OpRegRegImm(kOpLsl, t_reg, rl_src.low_reg, LowestSetBit(lit + 1));
1563    OpRegRegReg(kOpSub, rl_result.low_reg, t_reg, rl_src.low_reg);
1564  }
1565  StoreValue(rl_dest, rl_result);
1566  return true;
1567}
1568
1569void Mir2Lir::GenArithOpIntLit(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src,
1570                               int lit) {
1571  RegLocation rl_result;
1572  OpKind op = static_cast<OpKind>(0);    /* Make gcc happy */
1573  int shift_op = false;
1574  bool is_div = false;
1575
1576  switch (opcode) {
1577    case Instruction::RSUB_INT_LIT8:
1578    case Instruction::RSUB_INT: {
1579      rl_src = LoadValue(rl_src, kCoreReg);
1580      rl_result = EvalLoc(rl_dest, kCoreReg, true);
1581      if (cu_->instruction_set == kThumb2) {
1582        OpRegRegImm(kOpRsub, rl_result.low_reg, rl_src.low_reg, lit);
1583      } else {
1584        OpRegReg(kOpNeg, rl_result.low_reg, rl_src.low_reg);
1585        OpRegImm(kOpAdd, rl_result.low_reg, lit);
1586      }
1587      StoreValue(rl_dest, rl_result);
1588      return;
1589    }
1590
1591    case Instruction::SUB_INT:
1592    case Instruction::SUB_INT_2ADDR:
1593      lit = -lit;
1594      // Intended fallthrough
1595    case Instruction::ADD_INT:
1596    case Instruction::ADD_INT_2ADDR:
1597    case Instruction::ADD_INT_LIT8:
1598    case Instruction::ADD_INT_LIT16:
1599      op = kOpAdd;
1600      break;
1601    case Instruction::MUL_INT:
1602    case Instruction::MUL_INT_2ADDR:
1603    case Instruction::MUL_INT_LIT8:
1604    case Instruction::MUL_INT_LIT16: {
1605      if (HandleEasyMultiply(rl_src, rl_dest, lit)) {
1606        return;
1607      }
1608      op = kOpMul;
1609      break;
1610    }
1611    case Instruction::AND_INT:
1612    case Instruction::AND_INT_2ADDR:
1613    case Instruction::AND_INT_LIT8:
1614    case Instruction::AND_INT_LIT16:
1615      op = kOpAnd;
1616      break;
1617    case Instruction::OR_INT:
1618    case Instruction::OR_INT_2ADDR:
1619    case Instruction::OR_INT_LIT8:
1620    case Instruction::OR_INT_LIT16:
1621      op = kOpOr;
1622      break;
1623    case Instruction::XOR_INT:
1624    case Instruction::XOR_INT_2ADDR:
1625    case Instruction::XOR_INT_LIT8:
1626    case Instruction::XOR_INT_LIT16:
1627      op = kOpXor;
1628      break;
1629    case Instruction::SHL_INT_LIT8:
1630    case Instruction::SHL_INT:
1631    case Instruction::SHL_INT_2ADDR:
1632      lit &= 31;
1633      shift_op = true;
1634      op = kOpLsl;
1635      break;
1636    case Instruction::SHR_INT_LIT8:
1637    case Instruction::SHR_INT:
1638    case Instruction::SHR_INT_2ADDR:
1639      lit &= 31;
1640      shift_op = true;
1641      op = kOpAsr;
1642      break;
1643    case Instruction::USHR_INT_LIT8:
1644    case Instruction::USHR_INT:
1645    case Instruction::USHR_INT_2ADDR:
1646      lit &= 31;
1647      shift_op = true;
1648      op = kOpLsr;
1649      break;
1650
1651    case Instruction::DIV_INT:
1652    case Instruction::DIV_INT_2ADDR:
1653    case Instruction::DIV_INT_LIT8:
1654    case Instruction::DIV_INT_LIT16:
1655    case Instruction::REM_INT:
1656    case Instruction::REM_INT_2ADDR:
1657    case Instruction::REM_INT_LIT8:
1658    case Instruction::REM_INT_LIT16: {
1659      if (lit == 0) {
1660        GenImmedCheck(kCondAl, 0, 0, kThrowDivZero);
1661        return;
1662      }
1663      if ((opcode == Instruction::DIV_INT) ||
1664          (opcode == Instruction::DIV_INT_2ADDR) ||
1665          (opcode == Instruction::DIV_INT_LIT8) ||
1666          (opcode == Instruction::DIV_INT_LIT16)) {
1667        is_div = true;
1668      } else {
1669        is_div = false;
1670      }
1671      if (HandleEasyDivRem(opcode, is_div, rl_src, rl_dest, lit)) {
1672        return;
1673      }
1674
1675      bool done = false;
1676      if (cu_->instruction_set == kMips) {
1677        rl_src = LoadValue(rl_src, kCoreReg);
1678        rl_result = GenDivRemLit(rl_dest, rl_src.low_reg, lit, is_div);
1679        done = true;
1680      } else if (cu_->instruction_set == kX86) {
1681        rl_result = GenDivRemLit(rl_dest, rl_src, lit, is_div);
1682        done = true;
1683      } else if (cu_->instruction_set == kThumb2) {
1684        if (cu_->GetInstructionSetFeatures().HasDivideInstruction()) {
1685          // Use ARM SDIV instruction for division.  For remainder we also need to
1686          // calculate using a MUL and subtract.
1687          rl_src = LoadValue(rl_src, kCoreReg);
1688          rl_result = GenDivRemLit(rl_dest, rl_src.low_reg, lit, is_div);
1689          done = true;
1690        }
1691      }
1692
1693      if (!done) {
1694        FlushAllRegs();   /* Everything to home location. */
1695        LoadValueDirectFixed(rl_src, TargetReg(kArg0));
1696        Clobber(TargetReg(kArg0));
1697        ThreadOffset func_offset = QUICK_ENTRYPOINT_OFFSET(pIdivmod);
1698        CallRuntimeHelperRegImm(func_offset, TargetReg(kArg0), lit, false);
1699        if (is_div)
1700          rl_result = GetReturn(false);
1701        else
1702          rl_result = GetReturnAlt();
1703      }
1704      StoreValue(rl_dest, rl_result);
1705      return;
1706    }
1707    default:
1708      LOG(FATAL) << "Unexpected opcode " << opcode;
1709  }
1710  rl_src = LoadValue(rl_src, kCoreReg);
1711  rl_result = EvalLoc(rl_dest, kCoreReg, true);
1712  // Avoid shifts by literal 0 - no support in Thumb.  Change to copy.
1713  if (shift_op && (lit == 0)) {
1714    OpRegCopy(rl_result.low_reg, rl_src.low_reg);
1715  } else {
1716    OpRegRegImm(op, rl_result.low_reg, rl_src.low_reg, lit);
1717  }
1718  StoreValue(rl_dest, rl_result);
1719}
1720
1721void Mir2Lir::GenArithOpLong(Instruction::Code opcode, RegLocation rl_dest,
1722                             RegLocation rl_src1, RegLocation rl_src2) {
1723  RegLocation rl_result;
1724  OpKind first_op = kOpBkpt;
1725  OpKind second_op = kOpBkpt;
1726  bool call_out = false;
1727  bool check_zero = false;
1728  ThreadOffset func_offset(-1);
1729  int ret_reg = TargetReg(kRet0);
1730
1731  switch (opcode) {
1732    case Instruction::NOT_LONG:
1733      rl_src2 = LoadValueWide(rl_src2, kCoreReg);
1734      rl_result = EvalLoc(rl_dest, kCoreReg, true);
1735      // Check for destructive overlap
1736      if (rl_result.low_reg == rl_src2.high_reg) {
1737        int t_reg = AllocTemp();
1738        OpRegCopy(t_reg, rl_src2.high_reg);
1739        OpRegReg(kOpMvn, rl_result.low_reg, rl_src2.low_reg);
1740        OpRegReg(kOpMvn, rl_result.high_reg, t_reg);
1741        FreeTemp(t_reg);
1742      } else {
1743        OpRegReg(kOpMvn, rl_result.low_reg, rl_src2.low_reg);
1744        OpRegReg(kOpMvn, rl_result.high_reg, rl_src2.high_reg);
1745      }
1746      StoreValueWide(rl_dest, rl_result);
1747      return;
1748    case Instruction::ADD_LONG:
1749    case Instruction::ADD_LONG_2ADDR:
1750      if (cu_->instruction_set != kThumb2) {
1751        GenAddLong(opcode, rl_dest, rl_src1, rl_src2);
1752        return;
1753      }
1754      first_op = kOpAdd;
1755      second_op = kOpAdc;
1756      break;
1757    case Instruction::SUB_LONG:
1758    case Instruction::SUB_LONG_2ADDR:
1759      if (cu_->instruction_set != kThumb2) {
1760        GenSubLong(opcode, rl_dest, rl_src1, rl_src2);
1761        return;
1762      }
1763      first_op = kOpSub;
1764      second_op = kOpSbc;
1765      break;
1766    case Instruction::MUL_LONG:
1767    case Instruction::MUL_LONG_2ADDR:
1768      if (cu_->instruction_set != kMips) {
1769        GenMulLong(opcode, rl_dest, rl_src1, rl_src2);
1770        return;
1771      } else {
1772        call_out = true;
1773        ret_reg = TargetReg(kRet0);
1774        func_offset = QUICK_ENTRYPOINT_OFFSET(pLmul);
1775      }
1776      break;
1777    case Instruction::DIV_LONG:
1778    case Instruction::DIV_LONG_2ADDR:
1779      call_out = true;
1780      check_zero = true;
1781      ret_reg = TargetReg(kRet0);
1782      func_offset = QUICK_ENTRYPOINT_OFFSET(pLdiv);
1783      break;
1784    case Instruction::REM_LONG:
1785    case Instruction::REM_LONG_2ADDR:
1786      call_out = true;
1787      check_zero = true;
1788      func_offset = QUICK_ENTRYPOINT_OFFSET(pLmod);
1789      /* NOTE - for Arm, result is in kArg2/kArg3 instead of kRet0/kRet1 */
1790      ret_reg = (cu_->instruction_set == kThumb2) ? TargetReg(kArg2) : TargetReg(kRet0);
1791      break;
1792    case Instruction::AND_LONG_2ADDR:
1793    case Instruction::AND_LONG:
1794      if (cu_->instruction_set == kX86) {
1795        return GenAndLong(opcode, rl_dest, rl_src1, rl_src2);
1796      }
1797      first_op = kOpAnd;
1798      second_op = kOpAnd;
1799      break;
1800    case Instruction::OR_LONG:
1801    case Instruction::OR_LONG_2ADDR:
1802      if (cu_->instruction_set == kX86) {
1803        GenOrLong(opcode, rl_dest, rl_src1, rl_src2);
1804        return;
1805      }
1806      first_op = kOpOr;
1807      second_op = kOpOr;
1808      break;
1809    case Instruction::XOR_LONG:
1810    case Instruction::XOR_LONG_2ADDR:
1811      if (cu_->instruction_set == kX86) {
1812        GenXorLong(opcode, rl_dest, rl_src1, rl_src2);
1813        return;
1814      }
1815      first_op = kOpXor;
1816      second_op = kOpXor;
1817      break;
1818    case Instruction::NEG_LONG: {
1819      GenNegLong(rl_dest, rl_src2);
1820      return;
1821    }
1822    default:
1823      LOG(FATAL) << "Invalid long arith op";
1824  }
1825  if (!call_out) {
1826    GenLong3Addr(first_op, second_op, rl_dest, rl_src1, rl_src2);
1827  } else {
1828    FlushAllRegs();   /* Send everything to home location */
1829    if (check_zero) {
1830      LoadValueDirectWideFixed(rl_src2, TargetReg(kArg2), TargetReg(kArg3));
1831      int r_tgt = CallHelperSetup(func_offset);
1832      GenDivZeroCheck(TargetReg(kArg2), TargetReg(kArg3));
1833      LoadValueDirectWideFixed(rl_src1, TargetReg(kArg0), TargetReg(kArg1));
1834      // NOTE: callout here is not a safepoint
1835      CallHelper(r_tgt, func_offset, false /* not safepoint */);
1836    } else {
1837      CallRuntimeHelperRegLocationRegLocation(func_offset, rl_src1, rl_src2, false);
1838    }
1839    // Adjust return regs in to handle case of rem returning kArg2/kArg3
1840    if (ret_reg == TargetReg(kRet0))
1841      rl_result = GetReturnWide(false);
1842    else
1843      rl_result = GetReturnWideAlt();
1844    StoreValueWide(rl_dest, rl_result);
1845  }
1846}
1847
1848void Mir2Lir::GenConversionCall(ThreadOffset func_offset,
1849                                RegLocation rl_dest, RegLocation rl_src) {
1850  /*
1851   * Don't optimize the register usage since it calls out to support
1852   * functions
1853   */
1854  FlushAllRegs();   /* Send everything to home location */
1855  if (rl_src.wide) {
1856    LoadValueDirectWideFixed(rl_src, rl_src.fp ? TargetReg(kFArg0) : TargetReg(kArg0),
1857                             rl_src.fp ? TargetReg(kFArg1) : TargetReg(kArg1));
1858  } else {
1859    LoadValueDirectFixed(rl_src, rl_src.fp ? TargetReg(kFArg0) : TargetReg(kArg0));
1860  }
1861  CallRuntimeHelperRegLocation(func_offset, rl_src, false);
1862  if (rl_dest.wide) {
1863    RegLocation rl_result;
1864    rl_result = GetReturnWide(rl_dest.fp);
1865    StoreValueWide(rl_dest, rl_result);
1866  } else {
1867    RegLocation rl_result;
1868    rl_result = GetReturn(rl_dest.fp);
1869    StoreValue(rl_dest, rl_result);
1870  }
1871}
1872
1873/* Check if we need to check for pending suspend request */
1874void Mir2Lir::GenSuspendTest(int opt_flags) {
1875  if (NO_SUSPEND || (opt_flags & MIR_IGNORE_SUSPEND_CHECK)) {
1876    return;
1877  }
1878  FlushAllRegs();
1879  LIR* branch = OpTestSuspend(NULL);
1880  LIR* ret_lab = NewLIR0(kPseudoTargetLabel);
1881  LIR* target = RawLIR(current_dalvik_offset_, kPseudoSuspendTarget, WrapPointer(ret_lab),
1882                       current_dalvik_offset_);
1883  branch->target = target;
1884  suspend_launchpads_.Insert(target);
1885}
1886
1887/* Check if we need to check for pending suspend request */
1888void Mir2Lir::GenSuspendTestAndBranch(int opt_flags, LIR* target) {
1889  if (NO_SUSPEND || (opt_flags & MIR_IGNORE_SUSPEND_CHECK)) {
1890    OpUnconditionalBranch(target);
1891    return;
1892  }
1893  OpTestSuspend(target);
1894  LIR* launch_pad =
1895      RawLIR(current_dalvik_offset_, kPseudoSuspendTarget, WrapPointer(target),
1896             current_dalvik_offset_);
1897  FlushAllRegs();
1898  OpUnconditionalBranch(launch_pad);
1899  suspend_launchpads_.Insert(launch_pad);
1900}
1901
1902/* Call out to helper assembly routine that will null check obj and then lock it. */
1903void Mir2Lir::GenMonitorEnter(int opt_flags, RegLocation rl_src) {
1904  FlushAllRegs();
1905  CallRuntimeHelperRegLocation(QUICK_ENTRYPOINT_OFFSET(pLockObject), rl_src, true);
1906}
1907
1908/* Call out to helper assembly routine that will null check obj and then unlock it. */
1909void Mir2Lir::GenMonitorExit(int opt_flags, RegLocation rl_src) {
1910  FlushAllRegs();
1911  CallRuntimeHelperRegLocation(QUICK_ENTRYPOINT_OFFSET(pUnlockObject), rl_src, true);
1912}
1913
1914/* Generic code for generating a wide constant into a VR. */
1915void Mir2Lir::GenConstWide(RegLocation rl_dest, int64_t value) {
1916  RegLocation rl_result = EvalLoc(rl_dest, kAnyReg, true);
1917  LoadConstantWide(rl_result.low_reg, rl_result.high_reg, value);
1918  StoreValueWide(rl_dest, rl_result);
1919}
1920
1921}  // namespace art
1922