/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "oat/runtime/oat_support_entrypoints.h"
#include "../compiler_ir.h"
#include "ralloc_util.h"
#include "codegen_util.h"

namespace art {

/*
 * This source files contains "gen" codegen routines that should
 * be applicable to most targets.  Only mid-level support utilities
 * and "op" calls may be used here.
 */

/*
 * Generate an kPseudoBarrier marker to indicate the boundary of special
 * blocks.
 */
void Codegen::GenBarrier(CompilationUnit* cu)
{
  LIR* barrier = NewLIR0(cu, kPseudoBarrier);
  /* Mark all resources as being clobbered */
  barrier->def_mask = -1;
}

// FIXME: need to do some work to split out targets with
// condition codes and those without
LIR* Codegen::GenCheck(CompilationUnit* cu, ConditionCode c_code, ThrowKind kind)
{
  DCHECK_NE(cu->instruction_set, kMips);
  LIR* tgt = RawLIR(cu, 0, kPseudoThrowTarget, kind,
                    cu->current_dalvik_offset);
  LIR* branch = OpCondBranch(cu, c_code, tgt);
  // Remember branch target - will process later
  InsertGrowableList(cu, &cu->throw_launchpads, reinterpret_cast<uintptr_t>(tgt));
  return branch;
}

LIR* Codegen::GenImmedCheck(CompilationUnit* cu, ConditionCode c_code, int reg, int imm_val,
                            ThrowKind kind)
{
  LIR* tgt = RawLIR(cu, 0, kPseudoThrowTarget, kind,
                    cu->current_dalvik_offset);
  LIR* branch;
  if (c_code == kCondAl) {
    branch = OpUnconditionalBranch(cu, tgt);
  } else {
    branch = OpCmpImmBranch(cu, c_code, reg, imm_val, tgt);
  }
  // Remember branch target - will process later
  InsertGrowableList(cu, &cu->throw_launchpads, reinterpret_cast<uintptr_t>(tgt));
  return branch;
}

/* Perform null-check on a register.  */
LIR* Codegen::GenNullCheck(CompilationUnit* cu, int s_reg, int m_reg, int opt_flags)
{
  if (!(cu->disable_opt & (1 << kNullCheckElimination)) &&
    opt_flags & MIR_IGNORE_NULL_CHECK) {
    return NULL;
  }
  return GenImmedCheck(cu, kCondEq, m_reg, 0, kThrowNullPointer);
}

/* Perform check on two registers */
LIR* Codegen::GenRegRegCheck(CompilationUnit* cu, ConditionCode c_code, int reg1, int reg2,
                             ThrowKind kind)
{
  LIR* tgt = RawLIR(cu, 0, kPseudoThrowTarget, kind,
                    cu->current_dalvik_offset, reg1, reg2);
  LIR* branch = OpCmpBranch(cu, c_code, reg1, reg2, tgt);
  // Remember branch target - will process later
  InsertGrowableList(cu, &cu->throw_launchpads, reinterpret_cast<uintptr_t>(tgt));
  return branch;
}

// Convert relation of src1/src2 to src2/src1
ConditionCode FlipComparisonOrder(ConditionCode before) {
  ConditionCode res;
  switch (before) {
    case kCondEq: res = kCondEq; break;
    case kCondNe: res = kCondNe; break;
    case kCondLt: res = kCondGt; break;
    case kCondGt: res = kCondLt; break;
    case kCondLe: res = kCondGe; break;
    case kCondGe: res = kCondLe; break;
    default:
      res = static_cast<ConditionCode>(0);
      LOG(FATAL) << "Unexpected ccode " << before;
  }
  return res;
}

void Codegen::GenCompareAndBranch(CompilationUnit* cu, Instruction::Code opcode,
                                  RegLocation rl_src1, RegLocation rl_src2, LIR* taken,
                                  LIR* fall_through)
{
  ConditionCode cond;
  switch (opcode) {
    case Instruction::IF_EQ:
      cond = kCondEq;
      break;
    case Instruction::IF_NE:
      cond = kCondNe;
      break;
    case Instruction::IF_LT:
      cond = kCondLt;
      break;
    case Instruction::IF_GE:
      cond = kCondGe;
      break;
    case Instruction::IF_GT:
      cond = kCondGt;
      break;
    case Instruction::IF_LE:
      cond = kCondLe;
      break;
    default:
      cond = static_cast<ConditionCode>(0);
      LOG(FATAL) << "Unexpected opcode " << opcode;
  }

  // Normalize such that if either operand is constant, src2 will be constant
  if (rl_src1.is_const) {
    RegLocation rl_temp = rl_src1;
    rl_src1 = rl_src2;
    rl_src2 = rl_temp;
    cond = FlipComparisonOrder(cond);
  }

  rl_src1 = LoadValue(cu, rl_src1, kCoreReg);
  // Is this really an immediate comparison?
  if (rl_src2.is_const) {
    int immval = cu->constant_values[rl_src2.orig_sreg];
    // If it's already live in a register or not easily materialized, just keep going
    RegLocation rl_temp = UpdateLoc(cu, rl_src2);
    if ((rl_temp.location == kLocDalvikFrame) && InexpensiveConstant(rl_src1.low_reg, immval)) {
      // OK - convert this to a compare immediate and branch
      OpCmpImmBranch(cu, cond, rl_src1.low_reg, immval, taken);
      OpUnconditionalBranch(cu, fall_through);
      return;
    }
  }
  rl_src2 = LoadValue(cu, rl_src2, kCoreReg);
  OpCmpBranch(cu, cond, rl_src1.low_reg, rl_src2.low_reg, taken);
  OpUnconditionalBranch(cu, fall_through);
}

void Codegen::GenCompareZeroAndBranch(CompilationUnit* cu, Instruction::Code opcode,
                                      RegLocation rl_src, LIR* taken, LIR* fall_through)
{
  ConditionCode cond;
  rl_src = LoadValue(cu, rl_src, kCoreReg);
  switch (opcode) {
    case Instruction::IF_EQZ:
      cond = kCondEq;
      break;
    case Instruction::IF_NEZ:
      cond = kCondNe;
      break;
    case Instruction::IF_LTZ:
      cond = kCondLt;
      break;
    case Instruction::IF_GEZ:
      cond = kCondGe;
      break;
    case Instruction::IF_GTZ:
      cond = kCondGt;
      break;
    case Instruction::IF_LEZ:
      cond = kCondLe;
      break;
    default:
      cond = static_cast<ConditionCode>(0);
      LOG(FATAL) << "Unexpected opcode " << opcode;
  }
  OpCmpImmBranch(cu, cond, rl_src.low_reg, 0, taken);
  OpUnconditionalBranch(cu, fall_through);
}

void Codegen::GenIntToLong(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src)
{
  RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true);
  if (rl_src.location == kLocPhysReg) {
    OpRegCopy(cu, rl_result.low_reg, rl_src.low_reg);
  } else {
    LoadValueDirect(cu, rl_src, rl_result.low_reg);
  }
  OpRegRegImm(cu, kOpAsr, rl_result.high_reg, rl_result.low_reg, 31);
  StoreValueWide(cu, rl_dest, rl_result);
}

void Codegen::GenIntNarrowing(CompilationUnit* cu, Instruction::Code opcode, RegLocation rl_dest,
                              RegLocation rl_src)
{
   rl_src = LoadValue(cu, rl_src, kCoreReg);
   RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true);
   OpKind op = kOpInvalid;
   switch (opcode) {
     case Instruction::INT_TO_BYTE:
       op = kOp2Byte;
       break;
     case Instruction::INT_TO_SHORT:
        op = kOp2Short;
        break;
     case Instruction::INT_TO_CHAR:
        op = kOp2Char;
        break;
     default:
       LOG(ERROR) << "Bad int conversion type";
   }
   OpRegReg(cu, op, rl_result.low_reg, rl_src.low_reg);
   StoreValue(cu, rl_dest, rl_result);
}

/*
 * Let helper function take care of everything.  Will call
 * Array::AllocFromCode(type_idx, method, count);
 * Note: AllocFromCode will handle checks for errNegativeArraySize.
 */
void Codegen::GenNewArray(CompilationUnit* cu, uint32_t type_idx, RegLocation rl_dest,
                          RegLocation rl_src)
{
  FlushAllRegs(cu);  /* Everything to home location */
  int func_offset;
  if (cu->compiler->CanAccessTypeWithoutChecks(cu->method_idx,
                                                  *cu->dex_file,
                                                  type_idx)) {
    func_offset = ENTRYPOINT_OFFSET(pAllocArrayFromCode);
  } else {
    func_offset= ENTRYPOINT_OFFSET(pAllocArrayFromCodeWithAccessCheck);
  }
  CallRuntimeHelperImmMethodRegLocation(cu, func_offset, type_idx, rl_src, true);
  RegLocation rl_result = GetReturn(cu, false);
  StoreValue(cu, rl_dest, rl_result);
}

/*
 * Similar to GenNewArray, but with post-allocation initialization.
 * Verifier guarantees we're dealing with an array class.  Current
 * code throws runtime exception "bad Filled array req" for 'D' and 'J'.
 * Current code also throws internal unimp if not 'L', '[' or 'I'.
 */
void Codegen::GenFilledNewArray(CompilationUnit* cu, CallInfo* info)
{
  int elems = info->num_arg_words;
  int type_idx = info->index;
  FlushAllRegs(cu);  /* Everything to home location */
  int func_offset;
  if (cu->compiler->CanAccessTypeWithoutChecks(cu->method_idx,
                                                  *cu->dex_file,
                                                  type_idx)) {
    func_offset = ENTRYPOINT_OFFSET(pCheckAndAllocArrayFromCode);
  } else {
    func_offset = ENTRYPOINT_OFFSET(pCheckAndAllocArrayFromCodeWithAccessCheck);
  }
  CallRuntimeHelperImmMethodImm(cu, func_offset, type_idx, elems, true);
  FreeTemp(cu, TargetReg(kArg2));
  FreeTemp(cu, TargetReg(kArg1));
  /*
   * NOTE: the implicit target for Instruction::FILLED_NEW_ARRAY is the
   * return region.  Because AllocFromCode placed the new array
   * in kRet0, we'll just lock it into place.  When debugger support is
   * added, it may be necessary to additionally copy all return
   * values to a home location in thread-local storage
   */
  LockTemp(cu, TargetReg(kRet0));

  // TODO: use the correct component size, currently all supported types
  // share array alignment with ints (see comment at head of function)
  size_t component_size = sizeof(int32_t);

  // Having a range of 0 is legal
  if (info->is_range && (elems > 0)) {
    /*
     * Bit of ugliness here.  We're going generate a mem copy loop
     * on the register range, but it is possible that some regs
     * in the range have been promoted.  This is unlikely, but
     * before generating the copy, we'll just force a flush
     * of any regs in the source range that have been promoted to
     * home location.
     */
    for (int i = 0; i < elems; i++) {
      RegLocation loc = UpdateLoc(cu, info->args[i]);
      if (loc.location == kLocPhysReg) {
        StoreBaseDisp(cu, TargetReg(kSp), SRegOffset(cu, loc.s_reg_low),
                      loc.low_reg, kWord);
      }
    }
    /*
     * TUNING note: generated code here could be much improved, but
     * this is an uncommon operation and isn't especially performance
     * critical.
     */
    int r_src = AllocTemp(cu);
    int r_dst = AllocTemp(cu);
    int r_idx = AllocTemp(cu);
    int r_val = INVALID_REG;
    switch(cu->instruction_set) {
      case kThumb2:
        r_val = TargetReg(kLr);
        break;
      case kX86:
        FreeTemp(cu, TargetReg(kRet0));
        r_val = AllocTemp(cu);
        break;
      case kMips:
        r_val = AllocTemp(cu);
        break;
      default: LOG(FATAL) << "Unexpected instruction set: " << cu->instruction_set;
    }
    // Set up source pointer
    RegLocation rl_first = info->args[0];
    OpRegRegImm(cu, kOpAdd, r_src, TargetReg(kSp),
                SRegOffset(cu, rl_first.s_reg_low));
    // Set up the target pointer
    OpRegRegImm(cu, kOpAdd, r_dst, TargetReg(kRet0),
                mirror::Array::DataOffset(component_size).Int32Value());
    // Set up the loop counter (known to be > 0)
    LoadConstant(cu, r_idx, elems - 1);
    // Generate the copy loop.  Going backwards for convenience
    LIR* target = NewLIR0(cu, kPseudoTargetLabel);
    // Copy next element
    LoadBaseIndexed(cu, r_src, r_idx, r_val, 2, kWord);
    StoreBaseIndexed(cu, r_dst, r_idx, r_val, 2, kWord);
    FreeTemp(cu, r_val);
    OpDecAndBranch(cu, kCondGe, r_idx, target);
    if (cu->instruction_set == kX86) {
      // Restore the target pointer
      OpRegRegImm(cu, kOpAdd, TargetReg(kRet0), r_dst,
                  -mirror::Array::DataOffset(component_size).Int32Value());
    }
  } else if (!info->is_range) {
    // TUNING: interleave
    for (int i = 0; i < elems; i++) {
      RegLocation rl_arg = LoadValue(cu, info->args[i], kCoreReg);
      StoreBaseDisp(cu, TargetReg(kRet0),
                    mirror::Array::DataOffset(component_size).Int32Value() +
                    i * 4, rl_arg.low_reg, kWord);
      // If the LoadValue caused a temp to be allocated, free it
      if (IsTemp(cu, rl_arg.low_reg)) {
        FreeTemp(cu, rl_arg.low_reg);
      }
    }
  }
  if (info->result.location != kLocInvalid) {
    StoreValue(cu, info->result, GetReturn(cu, false /* not fp */));
  }
}

void Codegen::GenSput(CompilationUnit* cu, uint32_t field_idx, RegLocation rl_src,
                      bool is_long_or_double, bool is_object)
{
  int field_offset;
  int ssb_index;
  bool is_volatile;
  bool is_referrers_class;

  OatCompilationUnit m_unit(cu->class_loader, cu->class_linker, *cu->dex_file, cu->code_item,
                            cu->class_def_idx, cu->method_idx, cu->access_flags);

  bool fast_path =
      cu->compiler->ComputeStaticFieldInfo(field_idx, &m_unit,
                                              field_offset, ssb_index,
                                              is_referrers_class, is_volatile,
                                              true);
  if (fast_path && !SLOW_FIELD_PATH) {
    DCHECK_GE(field_offset, 0);
    int rBase;
    if (is_referrers_class) {
      // Fast path, static storage base is this method's class
      RegLocation rl_method  = LoadCurrMethod(cu);
      rBase = AllocTemp(cu);
      LoadWordDisp(cu, rl_method.low_reg,
                   mirror::AbstractMethod::DeclaringClassOffset().Int32Value(), rBase);
      if (IsTemp(cu, rl_method.low_reg)) {
        FreeTemp(cu, rl_method.low_reg);
      }
    } else {
      // Medium path, static storage base in a different class which
      // requires checks that the other class is initialized.
      DCHECK_GE(ssb_index, 0);
      // May do runtime call so everything to home locations.
      FlushAllRegs(cu);
      // Using fixed register to sync with possible call to runtime
      // support.
      int r_method = TargetReg(kArg1);
      LockTemp(cu, r_method);
      LoadCurrMethodDirect(cu, r_method);
      rBase = TargetReg(kArg0);
      LockTemp(cu, rBase);
      LoadWordDisp(cu, r_method,
                   mirror::AbstractMethod::DexCacheInitializedStaticStorageOffset().Int32Value(),
                   rBase);
      LoadWordDisp(cu, rBase,
                   mirror::Array::DataOffset(sizeof(mirror::Object*)).Int32Value() +
                   sizeof(int32_t*) * ssb_index, rBase);
      // rBase now points at appropriate static storage base (Class*)
      // or NULL if not initialized. Check for NULL and call helper if NULL.
      // TUNING: fast path should fall through
      LIR* branch_over = OpCmpImmBranch(cu, kCondNe, rBase, 0, NULL);
      LoadConstant(cu, TargetReg(kArg0), ssb_index);
      CallRuntimeHelperImm(cu, ENTRYPOINT_OFFSET(pInitializeStaticStorage), ssb_index, true);
      if (cu->instruction_set == kMips) {
        // For Arm, kRet0 = kArg0 = rBase, for Mips, we need to copy
        OpRegCopy(cu, rBase, TargetReg(kRet0));
      }
      LIR* skip_target = NewLIR0(cu, kPseudoTargetLabel);
      branch_over->target = skip_target;
      FreeTemp(cu, r_method);
    }
    // rBase now holds static storage base
    if (is_long_or_double) {
      rl_src = LoadValueWide(cu, rl_src, kAnyReg);
    } else {
      rl_src = LoadValue(cu, rl_src, kAnyReg);
    }
    if (is_volatile) {
      GenMemBarrier(cu, kStoreStore);
    }
    if (is_long_or_double) {
      StoreBaseDispWide(cu, rBase, field_offset, rl_src.low_reg,
                        rl_src.high_reg);
    } else {
      StoreWordDisp(cu, rBase, field_offset, rl_src.low_reg);
    }
    if (is_volatile) {
      GenMemBarrier(cu, kStoreLoad);
    }
    if (is_object) {
      MarkGCCard(cu, rl_src.low_reg, rBase);
    }
    FreeTemp(cu, rBase);
  } else {
    FlushAllRegs(cu);  // Everything to home locations
    int setter_offset = is_long_or_double ? ENTRYPOINT_OFFSET(pSet64Static) :
        (is_object ? ENTRYPOINT_OFFSET(pSetObjStatic)
        : ENTRYPOINT_OFFSET(pSet32Static));
    CallRuntimeHelperImmRegLocation(cu, setter_offset, field_idx, rl_src, true);
  }
}

void Codegen::GenSget(CompilationUnit* cu, uint32_t field_idx, RegLocation rl_dest,
                      bool is_long_or_double, bool is_object)
{
  int field_offset;
  int ssb_index;
  bool is_volatile;
  bool is_referrers_class;

  OatCompilationUnit m_unit(cu->class_loader, cu->class_linker,
                            *cu->dex_file, cu->code_item,
                            cu->class_def_idx, cu->method_idx,
                            cu->access_flags);

  bool fast_path =
    cu->compiler->ComputeStaticFieldInfo(field_idx, &m_unit,
                                            field_offset, ssb_index,
                                            is_referrers_class, is_volatile,
                                            false);
  if (fast_path && !SLOW_FIELD_PATH) {
    DCHECK_GE(field_offset, 0);
    int rBase;
    if (is_referrers_class) {
      // Fast path, static storage base is this method's class
      RegLocation rl_method  = LoadCurrMethod(cu);
      rBase = AllocTemp(cu);
      LoadWordDisp(cu, rl_method.low_reg,
                   mirror::AbstractMethod::DeclaringClassOffset().Int32Value(), rBase);
    } else {
      // Medium path, static storage base in a different class which
      // requires checks that the other class is initialized
      DCHECK_GE(ssb_index, 0);
      // May do runtime call so everything to home locations.
      FlushAllRegs(cu);
      // Using fixed register to sync with possible call to runtime
      // support
      int r_method = TargetReg(kArg1);
      LockTemp(cu, r_method);
      LoadCurrMethodDirect(cu, r_method);
      rBase = TargetReg(kArg0);
      LockTemp(cu, rBase);
      LoadWordDisp(cu, r_method,
                   mirror::AbstractMethod::DexCacheInitializedStaticStorageOffset().Int32Value(),
                   rBase);
      LoadWordDisp(cu, rBase,
                   mirror::Array::DataOffset(sizeof(mirror::Object*)).Int32Value() +
                   sizeof(int32_t*) * ssb_index, rBase);
      // rBase now points at appropriate static storage base (Class*)
      // or NULL if not initialized. Check for NULL and call helper if NULL.
      // TUNING: fast path should fall through
      LIR* branch_over = OpCmpImmBranch(cu, kCondNe, rBase, 0, NULL);
      CallRuntimeHelperImm(cu, ENTRYPOINT_OFFSET(pInitializeStaticStorage), ssb_index, true);
      if (cu->instruction_set == kMips) {
        // For Arm, kRet0 = kArg0 = rBase, for Mips, we need to copy
        OpRegCopy(cu, rBase, TargetReg(kRet0));
      }
      LIR* skip_target = NewLIR0(cu, kPseudoTargetLabel);
      branch_over->target = skip_target;
      FreeTemp(cu, r_method);
    }
    // rBase now holds static storage base
    RegLocation rl_result = EvalLoc(cu, rl_dest, kAnyReg, true);
    if (is_volatile) {
      GenMemBarrier(cu, kLoadLoad);
    }
    if (is_long_or_double) {
      LoadBaseDispWide(cu, rBase, field_offset, rl_result.low_reg,
                       rl_result.high_reg, INVALID_SREG);
    } else {
      LoadWordDisp(cu, rBase, field_offset, rl_result.low_reg);
    }
    FreeTemp(cu, rBase);
    if (is_long_or_double) {
      StoreValueWide(cu, rl_dest, rl_result);
    } else {
      StoreValue(cu, rl_dest, rl_result);
    }
  } else {
    FlushAllRegs(cu);  // Everything to home locations
    int getterOffset = is_long_or_double ? ENTRYPOINT_OFFSET(pGet64Static) :
        (is_object ? ENTRYPOINT_OFFSET(pGetObjStatic)
        : ENTRYPOINT_OFFSET(pGet32Static));
    CallRuntimeHelperImm(cu, getterOffset, field_idx, true);
    if (is_long_or_double) {
      RegLocation rl_result = GetReturnWide(cu, rl_dest.fp);
      StoreValueWide(cu, rl_dest, rl_result);
    } else {
      RegLocation rl_result = GetReturn(cu, rl_dest.fp);
      StoreValue(cu, rl_dest, rl_result);
    }
  }
}


// Debugging routine - if null target, branch to DebugMe
void Codegen::GenShowTarget(CompilationUnit* cu)
{
  DCHECK_NE(cu->instruction_set, kX86) << "unimplemented GenShowTarget";
  LIR* branch_over = OpCmpImmBranch(cu, kCondNe, TargetReg(kInvokeTgt), 0, NULL);
  LoadWordDisp(cu, TargetReg(kSelf), ENTRYPOINT_OFFSET(pDebugMe), TargetReg(kInvokeTgt));
  LIR* target = NewLIR0(cu, kPseudoTargetLabel);
  branch_over->target = target;
}

void Codegen::HandleSuspendLaunchPads(CompilationUnit *cu)
{
  LIR** suspend_label = reinterpret_cast<LIR**>(cu->suspend_launchpads.elem_list);
  int num_elems = cu->suspend_launchpads.num_used;
  int helper_offset = ENTRYPOINT_OFFSET(pTestSuspendFromCode);
  for (int i = 0; i < num_elems; i++) {
    ResetRegPool(cu);
    ResetDefTracking(cu);
    LIR* lab = suspend_label[i];
    LIR* resume_lab = reinterpret_cast<LIR*>(lab->operands[0]);
    cu->current_dalvik_offset = lab->operands[1];
    AppendLIR(cu, lab);
    int r_tgt = CallHelperSetup(cu, helper_offset);
    CallHelper(cu, r_tgt, helper_offset, true /* MarkSafepointPC */);
    OpUnconditionalBranch(cu, resume_lab);
  }
}

void Codegen::HandleIntrinsicLaunchPads(CompilationUnit *cu)
{
  LIR** intrinsic_label = reinterpret_cast<LIR**>(cu->intrinsic_launchpads.elem_list);
  int num_elems = cu->intrinsic_launchpads.num_used;
  for (int i = 0; i < num_elems; i++) {
    ResetRegPool(cu);
    ResetDefTracking(cu);
    LIR* lab = intrinsic_label[i];
    CallInfo* info = reinterpret_cast<CallInfo*>(lab->operands[0]);
    cu->current_dalvik_offset = info->offset;
    AppendLIR(cu, lab);
    // NOTE: GenInvoke handles MarkSafepointPC
    GenInvoke(cu, info);
    LIR* resume_lab = reinterpret_cast<LIR*>(lab->operands[2]);
    if (resume_lab != NULL) {
      OpUnconditionalBranch(cu, resume_lab);
    }
  }
}

void Codegen::HandleThrowLaunchPads(CompilationUnit *cu)
{
  LIR** throw_label = reinterpret_cast<LIR**>(cu->throw_launchpads.elem_list);
  int num_elems = cu->throw_launchpads.num_used;
  for (int i = 0; i < num_elems; i++) {
    ResetRegPool(cu);
    ResetDefTracking(cu);
    LIR* lab = throw_label[i];
    cu->current_dalvik_offset = lab->operands[1];
    AppendLIR(cu, lab);
    int func_offset = 0;
    int v1 = lab->operands[2];
    int v2 = lab->operands[3];
    bool target_x86 = (cu->instruction_set == kX86);
    switch (lab->operands[0]) {
      case kThrowNullPointer:
        func_offset = ENTRYPOINT_OFFSET(pThrowNullPointerFromCode);
        break;
      case kThrowArrayBounds:
        // Move v1 (array index) to kArg0 and v2 (array length) to kArg1
        if (v2 != TargetReg(kArg0)) {
          OpRegCopy(cu, TargetReg(kArg0), v1);
          if (target_x86) {
            // x86 leaves the array pointer in v2, so load the array length that the handler expects
            OpRegMem(cu, kOpMov, TargetReg(kArg1), v2, mirror::Array::LengthOffset().Int32Value());
          } else {
            OpRegCopy(cu, TargetReg(kArg1), v2);
          }
        } else {
          if (v1 == TargetReg(kArg1)) {
            // Swap v1 and v2, using kArg2 as a temp
            OpRegCopy(cu, TargetReg(kArg2), v1);
            if (target_x86) {
              // x86 leaves the array pointer in v2; load the array length that the handler expects
              OpRegMem(cu, kOpMov, TargetReg(kArg1), v2, mirror::Array::LengthOffset().Int32Value());
            } else {
              OpRegCopy(cu, TargetReg(kArg1), v2);
            }
            OpRegCopy(cu, TargetReg(kArg0), TargetReg(kArg2));
          } else {
            if (target_x86) {
              // x86 leaves the array pointer in v2; load the array length that the handler expects
              OpRegMem(cu, kOpMov, TargetReg(kArg1), v2, mirror::Array::LengthOffset().Int32Value());
            } else {
              OpRegCopy(cu, TargetReg(kArg1), v2);
            }
            OpRegCopy(cu, TargetReg(kArg0), v1);
          }
        }
        func_offset = ENTRYPOINT_OFFSET(pThrowArrayBoundsFromCode);
        break;
      case kThrowDivZero:
        func_offset = ENTRYPOINT_OFFSET(pThrowDivZeroFromCode);
        break;
      case kThrowNoSuchMethod:
        OpRegCopy(cu, TargetReg(kArg0), v1);
        func_offset =
          ENTRYPOINT_OFFSET(pThrowNoSuchMethodFromCode);
        break;
      case kThrowStackOverflow:
        func_offset = ENTRYPOINT_OFFSET(pThrowStackOverflowFromCode);
        // Restore stack alignment
        if (target_x86) {
          OpRegImm(cu, kOpAdd, TargetReg(kSp), cu->frame_size);
        } else {
          OpRegImm(cu, kOpAdd, TargetReg(kSp), (cu->num_core_spills + cu->num_fp_spills) * 4);
        }
        break;
      default:
        LOG(FATAL) << "Unexpected throw kind: " << lab->operands[0];
    }
    ClobberCalleeSave(cu);
    int r_tgt = CallHelperSetup(cu, func_offset);
    CallHelper(cu, r_tgt, func_offset, true /* MarkSafepointPC */);
  }
}

void Codegen::GenIGet(CompilationUnit* cu, uint32_t field_idx, int opt_flags, OpSize size,
                      RegLocation rl_dest, RegLocation rl_obj, bool is_long_or_double,
                      bool is_object)
{
  int field_offset;
  bool is_volatile;

  bool fast_path = FastInstance(cu, field_idx, field_offset, is_volatile, false);

  if (fast_path && !SLOW_FIELD_PATH) {
    RegLocation rl_result;
    RegisterClass reg_class = oat_reg_class_by_size(size);
    DCHECK_GE(field_offset, 0);
    rl_obj = LoadValue(cu, rl_obj, kCoreReg);
    if (is_long_or_double) {
      DCHECK(rl_dest.wide);
      GenNullCheck(cu, rl_obj.s_reg_low, rl_obj.low_reg, opt_flags);
      if (cu->instruction_set == kX86) {
        rl_result = EvalLoc(cu, rl_dest, reg_class, true);
        GenNullCheck(cu, rl_obj.s_reg_low, rl_obj.low_reg, opt_flags);
        LoadBaseDispWide(cu, rl_obj.low_reg, field_offset, rl_result.low_reg,
                         rl_result.high_reg, rl_obj.s_reg_low);
        if (is_volatile) {
          GenMemBarrier(cu, kLoadLoad);
        }
      } else {
        int reg_ptr = AllocTemp(cu);
        OpRegRegImm(cu, kOpAdd, reg_ptr, rl_obj.low_reg, field_offset);
        rl_result = EvalLoc(cu, rl_dest, reg_class, true);
        LoadBaseDispWide(cu, reg_ptr, 0, rl_result.low_reg, rl_result.high_reg, INVALID_SREG);
        if (is_volatile) {
          GenMemBarrier(cu, kLoadLoad);
        }
        FreeTemp(cu, reg_ptr);
      }
      StoreValueWide(cu, rl_dest, rl_result);
    } else {
      rl_result = EvalLoc(cu, rl_dest, reg_class, true);
      GenNullCheck(cu, rl_obj.s_reg_low, rl_obj.low_reg, opt_flags);
      LoadBaseDisp(cu, rl_obj.low_reg, field_offset, rl_result.low_reg,
                   kWord, rl_obj.s_reg_low);
      if (is_volatile) {
        GenMemBarrier(cu, kLoadLoad);
      }
      StoreValue(cu, rl_dest, rl_result);
    }
  } else {
    int getterOffset = is_long_or_double ? ENTRYPOINT_OFFSET(pGet64Instance) :
        (is_object ? ENTRYPOINT_OFFSET(pGetObjInstance)
        : ENTRYPOINT_OFFSET(pGet32Instance));
    CallRuntimeHelperImmRegLocation(cu, getterOffset, field_idx, rl_obj, true);
    if (is_long_or_double) {
      RegLocation rl_result = GetReturnWide(cu, rl_dest.fp);
      StoreValueWide(cu, rl_dest, rl_result);
    } else {
      RegLocation rl_result = GetReturn(cu, rl_dest.fp);
      StoreValue(cu, rl_dest, rl_result);
    }
  }
}

void Codegen::GenIPut(CompilationUnit* cu, uint32_t field_idx, int opt_flags, OpSize size,
                      RegLocation rl_src, RegLocation rl_obj, bool is_long_or_double,
                      bool is_object)
{
  int field_offset;
  bool is_volatile;

  bool fast_path = FastInstance(cu, field_idx, field_offset, is_volatile,
                 true);
  if (fast_path && !SLOW_FIELD_PATH) {
    RegisterClass reg_class = oat_reg_class_by_size(size);
    DCHECK_GE(field_offset, 0);
    rl_obj = LoadValue(cu, rl_obj, kCoreReg);
    if (is_long_or_double) {
      int reg_ptr;
      rl_src = LoadValueWide(cu, rl_src, kAnyReg);
      GenNullCheck(cu, rl_obj.s_reg_low, rl_obj.low_reg, opt_flags);
      reg_ptr = AllocTemp(cu);
      OpRegRegImm(cu, kOpAdd, reg_ptr, rl_obj.low_reg, field_offset);
      if (is_volatile) {
        GenMemBarrier(cu, kStoreStore);
      }
      StoreBaseDispWide(cu, reg_ptr, 0, rl_src.low_reg, rl_src.high_reg);
      if (is_volatile) {
        GenMemBarrier(cu, kLoadLoad);
      }
      FreeTemp(cu, reg_ptr);
    } else {
      rl_src = LoadValue(cu, rl_src, reg_class);
      GenNullCheck(cu, rl_obj.s_reg_low, rl_obj.low_reg, opt_flags);
      if (is_volatile) {
        GenMemBarrier(cu, kStoreStore);
      }
      StoreBaseDisp(cu, rl_obj.low_reg, field_offset, rl_src.low_reg, kWord);
      if (is_volatile) {
        GenMemBarrier(cu, kLoadLoad);
      }
      if (is_object) {
        MarkGCCard(cu, rl_src.low_reg, rl_obj.low_reg);
      }
    }
  } else {
    int setter_offset = is_long_or_double ? ENTRYPOINT_OFFSET(pSet64Instance) :
        (is_object ? ENTRYPOINT_OFFSET(pSetObjInstance)
        : ENTRYPOINT_OFFSET(pSet32Instance));
    CallRuntimeHelperImmRegLocationRegLocation(cu, setter_offset, field_idx, rl_obj, rl_src, true);
  }
}

void Codegen::GenConstClass(CompilationUnit* cu, uint32_t type_idx, RegLocation rl_dest)
{
  RegLocation rl_method = LoadCurrMethod(cu);
  int res_reg = AllocTemp(cu);
  RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true);
  if (!cu->compiler->CanAccessTypeWithoutChecks(cu->method_idx,
                                                   *cu->dex_file,
                                                   type_idx)) {
    // Call out to helper which resolves type and verifies access.
    // Resolved type returned in kRet0.
    CallRuntimeHelperImmReg(cu, ENTRYPOINT_OFFSET(pInitializeTypeAndVerifyAccessFromCode),
                            type_idx, rl_method.low_reg, true);
    RegLocation rl_result = GetReturn(cu, false);
    StoreValue(cu, rl_dest, rl_result);
  } else {
    // We're don't need access checks, load type from dex cache
    int32_t dex_cache_offset =
        mirror::AbstractMethod::DexCacheResolvedTypesOffset().Int32Value();
    LoadWordDisp(cu, rl_method.low_reg, dex_cache_offset, res_reg);
    int32_t offset_of_type =
        mirror::Array::DataOffset(sizeof(mirror::Class*)).Int32Value() + (sizeof(mirror::Class*)
                          * type_idx);
    LoadWordDisp(cu, res_reg, offset_of_type, rl_result.low_reg);
    if (!cu->compiler->CanAssumeTypeIsPresentInDexCache(*cu->dex_file,
        type_idx) || SLOW_TYPE_PATH) {
      // Slow path, at runtime test if type is null and if so initialize
      FlushAllRegs(cu);
      LIR* branch1 = OpCmpImmBranch(cu, kCondEq, rl_result.low_reg, 0, NULL);
      // Resolved, store and hop over following code
      StoreValue(cu, rl_dest, rl_result);
      /*
       * Because we have stores of the target value on two paths,
       * clobber temp tracking for the destination using the ssa name
       */
      ClobberSReg(cu, rl_dest.s_reg_low);
      LIR* branch2 = OpUnconditionalBranch(cu,0);
      // TUNING: move slow path to end & remove unconditional branch
      LIR* target1 = NewLIR0(cu, kPseudoTargetLabel);
      // Call out to helper, which will return resolved type in kArg0
      CallRuntimeHelperImmReg(cu, ENTRYPOINT_OFFSET(pInitializeTypeFromCode), type_idx,
                              rl_method.low_reg, true);
      RegLocation rl_result = GetReturn(cu, false);
      StoreValue(cu, rl_dest, rl_result);
      /*
       * Because we have stores of the target value on two paths,
       * clobber temp tracking for the destination using the ssa name
       */
      ClobberSReg(cu, rl_dest.s_reg_low);
      // Rejoin code paths
      LIR* target2 = NewLIR0(cu, kPseudoTargetLabel);
      branch1->target = target1;
      branch2->target = target2;
    } else {
      // Fast path, we're done - just store result
      StoreValue(cu, rl_dest, rl_result);
    }
  }
}

void Codegen::GenConstString(CompilationUnit* cu, uint32_t string_idx, RegLocation rl_dest)
{
  /* NOTE: Most strings should be available at compile time */
  int32_t offset_of_string = mirror::Array::DataOffset(sizeof(mirror::String*)).Int32Value() +
                 (sizeof(mirror::String*) * string_idx);
  if (!cu->compiler->CanAssumeStringIsPresentInDexCache(
      *cu->dex_file, string_idx) || SLOW_STRING_PATH) {
    // slow path, resolve string if not in dex cache
    FlushAllRegs(cu);
    LockCallTemps(cu); // Using explicit registers
    LoadCurrMethodDirect(cu, TargetReg(kArg2));
    LoadWordDisp(cu, TargetReg(kArg2),
                 mirror::AbstractMethod::DexCacheStringsOffset().Int32Value(), TargetReg(kArg0));
    // Might call out to helper, which will return resolved string in kRet0
    int r_tgt = CallHelperSetup(cu, ENTRYPOINT_OFFSET(pResolveStringFromCode));
    LoadWordDisp(cu, TargetReg(kArg0), offset_of_string, TargetReg(kRet0));
    LoadConstant(cu, TargetReg(kArg1), string_idx);
    if (cu->instruction_set == kThumb2) {
      OpRegImm(cu, kOpCmp, TargetReg(kRet0), 0);  // Is resolved?
      GenBarrier(cu);
      // For testing, always force through helper
      if (!EXERCISE_SLOWEST_STRING_PATH) {
        OpIT(cu, kCondEq, "T");
      }
      OpRegCopy(cu, TargetReg(kArg0), TargetReg(kArg2));   // .eq
      LIR* call_inst = OpReg(cu, kOpBlx, r_tgt);    // .eq, helper(Method*, string_idx)
      MarkSafepointPC(cu, call_inst);
      FreeTemp(cu, r_tgt);
    } else if (cu->instruction_set == kMips) {
      LIR* branch = OpCmpImmBranch(cu, kCondNe, TargetReg(kRet0), 0, NULL);
      OpRegCopy(cu, TargetReg(kArg0), TargetReg(kArg2));   // .eq
      LIR* call_inst = OpReg(cu, kOpBlx, r_tgt);
      MarkSafepointPC(cu, call_inst);
      FreeTemp(cu, r_tgt);
      LIR* target = NewLIR0(cu, kPseudoTargetLabel);
      branch->target = target;
    } else {
      DCHECK_EQ(cu->instruction_set, kX86);
      CallRuntimeHelperRegReg(cu, ENTRYPOINT_OFFSET(pResolveStringFromCode), TargetReg(kArg2), TargetReg(kArg1), true);
    }
    GenBarrier(cu);
    StoreValue(cu, rl_dest, GetReturn(cu, false));
  } else {
    RegLocation rl_method = LoadCurrMethod(cu);
    int res_reg = AllocTemp(cu);
    RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true);
    LoadWordDisp(cu, rl_method.low_reg,
                 mirror::AbstractMethod::DexCacheStringsOffset().Int32Value(), res_reg);
    LoadWordDisp(cu, res_reg, offset_of_string, rl_result.low_reg);
    StoreValue(cu, rl_dest, rl_result);
  }
}

/*
 * Let helper function take care of everything.  Will
 * call Class::NewInstanceFromCode(type_idx, method);
 */
void Codegen::GenNewInstance(CompilationUnit* cu, uint32_t type_idx, RegLocation rl_dest)
{
  FlushAllRegs(cu);  /* Everything to home location */
  // alloc will always check for resolution, do we also need to verify
  // access because the verifier was unable to?
  int func_offset;
  if (cu->compiler->CanAccessInstantiableTypeWithoutChecks(
      cu->method_idx, *cu->dex_file, type_idx)) {
    func_offset = ENTRYPOINT_OFFSET(pAllocObjectFromCode);
  } else {
    func_offset = ENTRYPOINT_OFFSET(pAllocObjectFromCodeWithAccessCheck);
  }
  CallRuntimeHelperImmMethod(cu, func_offset, type_idx, true);
  RegLocation rl_result = GetReturn(cu, false);
  StoreValue(cu, rl_dest, rl_result);
}

void Codegen::GenThrow(CompilationUnit* cu, RegLocation rl_src)
{
  FlushAllRegs(cu);
  CallRuntimeHelperRegLocation(cu, ENTRYPOINT_OFFSET(pDeliverException), rl_src, true);
}

void Codegen::GenInstanceof(CompilationUnit* cu, uint32_t type_idx, RegLocation rl_dest,
                            RegLocation rl_src)
{
  FlushAllRegs(cu);
  // May generate a call - use explicit registers
  LockCallTemps(cu);
  LoadCurrMethodDirect(cu, TargetReg(kArg1));  // kArg1 <= current Method*
  int class_reg = TargetReg(kArg2);  // kArg2 will hold the Class*
  if (!cu->compiler->CanAccessTypeWithoutChecks(cu->method_idx,
                                                   *cu->dex_file,
                                                   type_idx)) {
    // Check we have access to type_idx and if not throw IllegalAccessError,
    // returns Class* in kArg0
    CallRuntimeHelperImm(cu, ENTRYPOINT_OFFSET(pInitializeTypeAndVerifyAccessFromCode),
                         type_idx, true);
    OpRegCopy(cu, class_reg, TargetReg(kRet0));  // Align usage with fast path
    LoadValueDirectFixed(cu, rl_src, TargetReg(kArg0));  // kArg0 <= ref
  } else {
    // Load dex cache entry into class_reg (kArg2)
    LoadValueDirectFixed(cu, rl_src, TargetReg(kArg0));  // kArg0 <= ref
    LoadWordDisp(cu, TargetReg(kArg1),
                 mirror::AbstractMethod::DexCacheResolvedTypesOffset().Int32Value(), class_reg);
    int32_t offset_of_type =
        mirror::Array::DataOffset(sizeof(mirror::Class*)).Int32Value() + (sizeof(mirror::Class*)
        * type_idx);
    LoadWordDisp(cu, class_reg, offset_of_type, class_reg);
    if (!cu->compiler->CanAssumeTypeIsPresentInDexCache(
        *cu->dex_file, type_idx)) {
      // Need to test presence of type in dex cache at runtime
      LIR* hop_branch = OpCmpImmBranch(cu, kCondNe, class_reg, 0, NULL);
      // Not resolved
      // Call out to helper, which will return resolved type in kRet0
      CallRuntimeHelperImm(cu, ENTRYPOINT_OFFSET(pInitializeTypeFromCode), type_idx, true);
      OpRegCopy(cu, TargetReg(kArg2), TargetReg(kRet0)); // Align usage with fast path
      LoadValueDirectFixed(cu, rl_src, TargetReg(kArg0));  /* reload Ref */
      // Rejoin code paths
      LIR* hop_target = NewLIR0(cu, kPseudoTargetLabel);
      hop_branch->target = hop_target;
    }
  }
  /* kArg0 is ref, kArg2 is class. If ref==null, use directly as bool result */
  RegLocation rl_result = GetReturn(cu, false);
  if (cu->instruction_set == kMips) {
    LoadConstant(cu, rl_result.low_reg, 0);  // store false result for if branch is taken
  }
  LIR* branch1 = OpCmpImmBranch(cu, kCondEq, TargetReg(kArg0), 0, NULL);
  /* load object->klass_ */
  DCHECK_EQ(mirror::Object::ClassOffset().Int32Value(), 0);
  LoadWordDisp(cu, TargetReg(kArg0),  mirror::Object::ClassOffset().Int32Value(), TargetReg(kArg1));
  /* kArg0 is ref, kArg1 is ref->klass_, kArg2 is class */
  LIR* call_inst;
  LIR* branchover = NULL;
  if (cu->instruction_set == kThumb2) {
    /* Uses conditional nullification */
    int r_tgt = LoadHelper(cu, ENTRYPOINT_OFFSET(pInstanceofNonTrivialFromCode));
    OpRegReg(cu, kOpCmp, TargetReg(kArg1), TargetReg(kArg2));  // Same?
    OpIT(cu, kCondEq, "EE");   // if-convert the test
    LoadConstant(cu, TargetReg(kArg0), 1);     // .eq case - load true
    OpRegCopy(cu, TargetReg(kArg0), TargetReg(kArg2));    // .ne case - arg0 <= class
    call_inst = OpReg(cu, kOpBlx, r_tgt);    // .ne case: helper(class, ref->class)
    FreeTemp(cu, r_tgt);
  } else {
    /* Uses branchovers */
    LoadConstant(cu, rl_result.low_reg, 1);     // assume true
    branchover = OpCmpBranch(cu, kCondEq, TargetReg(kArg1), TargetReg(kArg2), NULL);
    if (cu->instruction_set != kX86) {
      int r_tgt = LoadHelper(cu, ENTRYPOINT_OFFSET(pInstanceofNonTrivialFromCode));
      OpRegCopy(cu, TargetReg(kArg0), TargetReg(kArg2));    // .ne case - arg0 <= class
      call_inst = OpReg(cu, kOpBlx, r_tgt);    // .ne case: helper(class, ref->class)
      FreeTemp(cu, r_tgt);
    } else {
      OpRegCopy(cu, TargetReg(kArg0), TargetReg(kArg2));
      call_inst = OpThreadMem(cu, kOpBlx, ENTRYPOINT_OFFSET(pInstanceofNonTrivialFromCode));
    }
  }
  MarkSafepointPC(cu, call_inst);
  ClobberCalleeSave(cu);
  /* branch targets here */
  LIR* target = NewLIR0(cu, kPseudoTargetLabel);
  StoreValue(cu, rl_dest, rl_result);
  branch1->target = target;
  if (cu->instruction_set != kThumb2) {
    branchover->target = target;
  }
}

void Codegen::GenCheckCast(CompilationUnit* cu, uint32_t type_idx, RegLocation rl_src)
{
  FlushAllRegs(cu);
  // May generate a call - use explicit registers
  LockCallTemps(cu);
  LoadCurrMethodDirect(cu, TargetReg(kArg1));  // kArg1 <= current Method*
  int class_reg = TargetReg(kArg2);  // kArg2 will hold the Class*
  if (!cu->compiler->CanAccessTypeWithoutChecks(cu->method_idx,
                                                   *cu->dex_file,
                                                   type_idx)) {
    // Check we have access to type_idx and if not throw IllegalAccessError,
    // returns Class* in kRet0
    // InitializeTypeAndVerifyAccess(idx, method)
    CallRuntimeHelperImmReg(cu, ENTRYPOINT_OFFSET(pInitializeTypeAndVerifyAccessFromCode),
                            type_idx, TargetReg(kArg1), true);
    OpRegCopy(cu, class_reg, TargetReg(kRet0));  // Align usage with fast path
  } else {
    // Load dex cache entry into class_reg (kArg2)
    LoadWordDisp(cu, TargetReg(kArg1),
                 mirror::AbstractMethod::DexCacheResolvedTypesOffset().Int32Value(), class_reg);
    int32_t offset_of_type =
        mirror::Array::DataOffset(sizeof(mirror::Class*)).Int32Value() +
        (sizeof(mirror::Class*) * type_idx);
    LoadWordDisp(cu, class_reg, offset_of_type, class_reg);
    if (!cu->compiler->CanAssumeTypeIsPresentInDexCache(
        *cu->dex_file, type_idx)) {
      // Need to test presence of type in dex cache at runtime
      LIR* hop_branch = OpCmpImmBranch(cu, kCondNe, class_reg, 0, NULL);
      // Not resolved
      // Call out to helper, which will return resolved type in kArg0
      // InitializeTypeFromCode(idx, method)
      CallRuntimeHelperImmReg(cu, ENTRYPOINT_OFFSET(pInitializeTypeFromCode), type_idx, TargetReg(kArg1),
                              true);
      OpRegCopy(cu, class_reg, TargetReg(kRet0)); // Align usage with fast path
      // Rejoin code paths
      LIR* hop_target = NewLIR0(cu, kPseudoTargetLabel);
      hop_branch->target = hop_target;
    }
  }
  // At this point, class_reg (kArg2) has class
  LoadValueDirectFixed(cu, rl_src, TargetReg(kArg0));  // kArg0 <= ref
  /* Null is OK - continue */
  LIR* branch1 = OpCmpImmBranch(cu, kCondEq, TargetReg(kArg0), 0, NULL);
  /* load object->klass_ */
  DCHECK_EQ(mirror::Object::ClassOffset().Int32Value(), 0);
  LoadWordDisp(cu, TargetReg(kArg0), mirror::Object::ClassOffset().Int32Value(), TargetReg(kArg1));
  /* kArg1 now contains object->klass_ */
  LIR* branch2;
  if (cu->instruction_set == kThumb2) {
    int r_tgt = LoadHelper(cu, ENTRYPOINT_OFFSET(pCheckCastFromCode));
    OpRegReg(cu, kOpCmp, TargetReg(kArg1), class_reg);
    branch2 = OpCondBranch(cu, kCondEq, NULL); /* If eq, trivial yes */
    OpRegCopy(cu, TargetReg(kArg0), TargetReg(kArg1));
    OpRegCopy(cu, TargetReg(kArg1), TargetReg(kArg2));
    ClobberCalleeSave(cu);
    LIR* call_inst = OpReg(cu, kOpBlx, r_tgt);
    MarkSafepointPC(cu, call_inst);
    FreeTemp(cu, r_tgt);
  } else {
    branch2 = OpCmpBranch(cu, kCondEq, TargetReg(kArg1), class_reg, NULL);
    CallRuntimeHelperRegReg(cu, ENTRYPOINT_OFFSET(pCheckCastFromCode), TargetReg(kArg1), TargetReg(kArg2), true);
  }
  /* branch target here */
  LIR* target = NewLIR0(cu, kPseudoTargetLabel);
  branch1->target = target;
  branch2->target = target;
}

void Codegen::GenLong3Addr(CompilationUnit* cu, OpKind first_op, OpKind second_op,
                           RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2)
{
  RegLocation rl_result;
  if (cu->instruction_set == kThumb2) {
    /*
     * NOTE:  This is the one place in the code in which we might have
     * as many as six live temporary registers.  There are 5 in the normal
     * set for Arm.  Until we have spill capabilities, temporarily add
     * lr to the temp set.  It is safe to do this locally, but note that
     * lr is used explicitly elsewhere in the code generator and cannot
     * normally be used as a general temp register.
     */
    MarkTemp(cu, TargetReg(kLr));   // Add lr to the temp pool
    FreeTemp(cu, TargetReg(kLr));   // and make it available
  }
  rl_src1 = LoadValueWide(cu, rl_src1, kCoreReg);
  rl_src2 = LoadValueWide(cu, rl_src2, kCoreReg);
  rl_result = EvalLoc(cu, rl_dest, kCoreReg, true);
  // The longs may overlap - use intermediate temp if so
  if ((rl_result.low_reg == rl_src1.high_reg) || (rl_result.low_reg == rl_src2.high_reg)){
    int t_reg = AllocTemp(cu);
    OpRegRegReg(cu, first_op, t_reg, rl_src1.low_reg, rl_src2.low_reg);
    OpRegRegReg(cu, second_op, rl_result.high_reg, rl_src1.high_reg, rl_src2.high_reg);
    OpRegCopy(cu, rl_result.low_reg, t_reg);
    FreeTemp(cu, t_reg);
  } else {
    OpRegRegReg(cu, first_op, rl_result.low_reg, rl_src1.low_reg, rl_src2.low_reg);
    OpRegRegReg(cu, second_op, rl_result.high_reg, rl_src1.high_reg,
                rl_src2.high_reg);
  }
  /*
   * NOTE: If rl_dest refers to a frame variable in a large frame, the
   * following StoreValueWide might need to allocate a temp register.
   * To further work around the lack of a spill capability, explicitly
   * free any temps from rl_src1 & rl_src2 that aren't still live in rl_result.
   * Remove when spill is functional.
   */
  FreeRegLocTemps(cu, rl_result, rl_src1);
  FreeRegLocTemps(cu, rl_result, rl_src2);
  StoreValueWide(cu, rl_dest, rl_result);
  if (cu->instruction_set == kThumb2) {
    Clobber(cu, TargetReg(kLr));
    UnmarkTemp(cu, TargetReg(kLr));  // Remove lr from the temp pool
  }
}


bool Codegen::GenShiftOpLong(CompilationUnit* cu, Instruction::Code opcode, RegLocation rl_dest,
                             RegLocation rl_src1, RegLocation rl_shift)
{
  int func_offset;

  switch (opcode) {
    case Instruction::SHL_LONG:
    case Instruction::SHL_LONG_2ADDR:
      func_offset = ENTRYPOINT_OFFSET(pShlLong);
      break;
    case Instruction::SHR_LONG:
    case Instruction::SHR_LONG_2ADDR:
      func_offset = ENTRYPOINT_OFFSET(pShrLong);
      break;
    case Instruction::USHR_LONG:
    case Instruction::USHR_LONG_2ADDR:
      func_offset = ENTRYPOINT_OFFSET(pUshrLong);
      break;
    default:
      LOG(FATAL) << "Unexpected case";
      return true;
  }
  FlushAllRegs(cu);   /* Send everything to home location */
  CallRuntimeHelperRegLocationRegLocation(cu, func_offset, rl_src1, rl_shift, false);
  RegLocation rl_result = GetReturnWide(cu, false);
  StoreValueWide(cu, rl_dest, rl_result);
  return false;
}


bool Codegen::GenArithOpInt(CompilationUnit* cu, Instruction::Code opcode, RegLocation rl_dest,
                            RegLocation rl_src1, RegLocation rl_src2)
{
  OpKind op = kOpBkpt;
  bool is_div_rem = false;
  bool check_zero = false;
  bool unary = false;
  RegLocation rl_result;
  bool shift_op = false;
  switch (opcode) {
    case Instruction::NEG_INT:
      op = kOpNeg;
      unary = true;
      break;
    case Instruction::NOT_INT:
      op = kOpMvn;
      unary = true;
      break;
    case Instruction::ADD_INT:
    case Instruction::ADD_INT_2ADDR:
      op = kOpAdd;
      break;
    case Instruction::SUB_INT:
    case Instruction::SUB_INT_2ADDR:
      op = kOpSub;
      break;
    case Instruction::MUL_INT:
    case Instruction::MUL_INT_2ADDR:
      op = kOpMul;
      break;
    case Instruction::DIV_INT:
    case Instruction::DIV_INT_2ADDR:
      check_zero = true;
      op = kOpDiv;
      is_div_rem = true;
      break;
    /* NOTE: returns in kArg1 */
    case Instruction::REM_INT:
    case Instruction::REM_INT_2ADDR:
      check_zero = true;
      op = kOpRem;
      is_div_rem = true;
      break;
    case Instruction::AND_INT:
    case Instruction::AND_INT_2ADDR:
      op = kOpAnd;
      break;
    case Instruction::OR_INT:
    case Instruction::OR_INT_2ADDR:
      op = kOpOr;
      break;
    case Instruction::XOR_INT:
    case Instruction::XOR_INT_2ADDR:
      op = kOpXor;
      break;
    case Instruction::SHL_INT:
    case Instruction::SHL_INT_2ADDR:
      shift_op = true;
      op = kOpLsl;
      break;
    case Instruction::SHR_INT:
    case Instruction::SHR_INT_2ADDR:
      shift_op = true;
      op = kOpAsr;
      break;
    case Instruction::USHR_INT:
    case Instruction::USHR_INT_2ADDR:
      shift_op = true;
      op = kOpLsr;
      break;
    default:
      LOG(FATAL) << "Invalid word arith op: " << opcode;
  }
  if (!is_div_rem) {
    if (unary) {
      rl_src1 = LoadValue(cu, rl_src1, kCoreReg);
      rl_result = EvalLoc(cu, rl_dest, kCoreReg, true);
      OpRegReg(cu, op, rl_result.low_reg, rl_src1.low_reg);
    } else {
      if (shift_op) {
        int t_reg = INVALID_REG;
        if (cu->instruction_set == kX86) {
          // X86 doesn't require masking and must use ECX
          t_reg = TargetReg(kCount);  // rCX
          LoadValueDirectFixed(cu, rl_src2, t_reg);
        } else {
          rl_src2 = LoadValue(cu, rl_src2, kCoreReg);
          t_reg = AllocTemp(cu);
          OpRegRegImm(cu, kOpAnd, t_reg, rl_src2.low_reg, 31);
        }
        rl_src1 = LoadValue(cu, rl_src1, kCoreReg);
        rl_result = EvalLoc(cu, rl_dest, kCoreReg, true);
        OpRegRegReg(cu, op, rl_result.low_reg, rl_src1.low_reg, t_reg);
        FreeTemp(cu, t_reg);
      } else {
        rl_src1 = LoadValue(cu, rl_src1, kCoreReg);
        rl_src2 = LoadValue(cu, rl_src2, kCoreReg);
        rl_result = EvalLoc(cu, rl_dest, kCoreReg, true);
        OpRegRegReg(cu, op, rl_result.low_reg, rl_src1.low_reg, rl_src2.low_reg);
      }
    }
    StoreValue(cu, rl_dest, rl_result);
  } else {
    if (cu->instruction_set == kMips) {
      rl_src1 = LoadValue(cu, rl_src1, kCoreReg);
      rl_src2 = LoadValue(cu, rl_src2, kCoreReg);
      if (check_zero) {
          GenImmedCheck(cu, kCondEq, rl_src2.low_reg, 0, kThrowDivZero);
      }
      rl_result = GenDivRem(cu, rl_dest, rl_src1.low_reg, rl_src2.low_reg, op == kOpDiv);
    } else {
      int func_offset = ENTRYPOINT_OFFSET(pIdivmod);
      FlushAllRegs(cu);   /* Send everything to home location */
      LoadValueDirectFixed(cu, rl_src2, TargetReg(kArg1));
      int r_tgt = CallHelperSetup(cu, func_offset);
      LoadValueDirectFixed(cu, rl_src1, TargetReg(kArg0));
      if (check_zero) {
        GenImmedCheck(cu, kCondEq, TargetReg(kArg1), 0, kThrowDivZero);
      }
      // NOTE: callout here is not a safepoint
      CallHelper(cu, r_tgt, func_offset, false /* not a safepoint */ );
      if (op == kOpDiv)
        rl_result = GetReturn(cu, false);
      else
        rl_result = GetReturnAlt(cu);
    }
    StoreValue(cu, rl_dest, rl_result);
  }
  return false;
}

/*
 * The following are the first-level codegen routines that analyze the format
 * of each bytecode then either dispatch special purpose codegen routines
 * or produce corresponding Thumb instructions directly.
 */

static bool IsPowerOfTwo(int x)
{
  return (x & (x - 1)) == 0;
}

// Returns true if no more than two bits are set in 'x'.
static bool IsPopCountLE2(unsigned int x)
{
  x &= x - 1;
  return (x & (x - 1)) == 0;
}

// Returns the index of the lowest set bit in 'x'.
static int LowestSetBit(unsigned int x) {
  int bit_posn = 0;
  while ((x & 0xf) == 0) {
    bit_posn += 4;
    x >>= 4;
  }
  while ((x & 1) == 0) {
    bit_posn++;
    x >>= 1;
  }
  return bit_posn;
}

// Returns true if it added instructions to 'cu' to divide 'rl_src' by 'lit'
// and store the result in 'rl_dest'.
static bool HandleEasyDivide(CompilationUnit* cu, Instruction::Code dalvik_opcode,
                             RegLocation rl_src, RegLocation rl_dest, int lit)
{
  if ((lit < 2) || ((cu->instruction_set != kThumb2) && !IsPowerOfTwo(lit))) {
    return false;
  }
  Codegen* cg = cu->cg.get();
  // No divide instruction for Arm, so check for more special cases
  if ((cu->instruction_set == kThumb2) && !IsPowerOfTwo(lit)) {
    return cg->SmallLiteralDivide(cu, dalvik_opcode, rl_src, rl_dest, lit);
  }
  int k = LowestSetBit(lit);
  if (k >= 30) {
    // Avoid special cases.
    return false;
  }
  bool div = (dalvik_opcode == Instruction::DIV_INT_LIT8 ||
      dalvik_opcode == Instruction::DIV_INT_LIT16);
  rl_src = cg->LoadValue(cu, rl_src, kCoreReg);
  RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true);
  if (div) {
    int t_reg = AllocTemp(cu);
    if (lit == 2) {
      // Division by 2 is by far the most common division by constant.
      cg->OpRegRegImm(cu, kOpLsr, t_reg, rl_src.low_reg, 32 - k);
      cg->OpRegRegReg(cu, kOpAdd, t_reg, t_reg, rl_src.low_reg);
      cg->OpRegRegImm(cu, kOpAsr, rl_result.low_reg, t_reg, k);
    } else {
      cg->OpRegRegImm(cu, kOpAsr, t_reg, rl_src.low_reg, 31);
      cg->OpRegRegImm(cu, kOpLsr, t_reg, t_reg, 32 - k);
      cg->OpRegRegReg(cu, kOpAdd, t_reg, t_reg, rl_src.low_reg);
      cg->OpRegRegImm(cu, kOpAsr, rl_result.low_reg, t_reg, k);
    }
  } else {
    int t_reg1 = AllocTemp(cu);
    int t_reg2 = AllocTemp(cu);
    if (lit == 2) {
      cg->OpRegRegImm(cu, kOpLsr, t_reg1, rl_src.low_reg, 32 - k);
      cg->OpRegRegReg(cu, kOpAdd, t_reg2, t_reg1, rl_src.low_reg);
      cg->OpRegRegImm(cu, kOpAnd, t_reg2, t_reg2, lit -1);
      cg->OpRegRegReg(cu, kOpSub, rl_result.low_reg, t_reg2, t_reg1);
    } else {
      cg->OpRegRegImm(cu, kOpAsr, t_reg1, rl_src.low_reg, 31);
      cg->OpRegRegImm(cu, kOpLsr, t_reg1, t_reg1, 32 - k);
      cg->OpRegRegReg(cu, kOpAdd, t_reg2, t_reg1, rl_src.low_reg);
      cg->OpRegRegImm(cu, kOpAnd, t_reg2, t_reg2, lit - 1);
      cg->OpRegRegReg(cu, kOpSub, rl_result.low_reg, t_reg2, t_reg1);
    }
  }
  cg->StoreValue(cu, rl_dest, rl_result);
  return true;
}

// Returns true if it added instructions to 'cu' to multiply 'rl_src' by 'lit'
// and store the result in 'rl_dest'.
static bool HandleEasyMultiply(CompilationUnit* cu, RegLocation rl_src,
                               RegLocation rl_dest, int lit)
{
  // Can we simplify this multiplication?
  bool power_of_two = false;
  bool pop_count_le2 = false;
  bool power_of_two_minus_one = false;
  if (lit < 2) {
    // Avoid special cases.
    return false;
  } else if (IsPowerOfTwo(lit)) {
    power_of_two = true;
  } else if (IsPopCountLE2(lit)) {
    pop_count_le2 = true;
  } else if (IsPowerOfTwo(lit + 1)) {
    power_of_two_minus_one = true;
  } else {
    return false;
  }
  Codegen* cg = cu->cg.get();
  rl_src = cg->LoadValue(cu, rl_src, kCoreReg);
  RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true);
  if (power_of_two) {
    // Shift.
    cg->OpRegRegImm(cu, kOpLsl, rl_result.low_reg, rl_src.low_reg, LowestSetBit(lit));
  } else if (pop_count_le2) {
    // Shift and add and shift.
    int first_bit = LowestSetBit(lit);
    int second_bit = LowestSetBit(lit ^ (1 << first_bit));
    cg->GenMultiplyByTwoBitMultiplier(cu, rl_src, rl_result, lit, first_bit, second_bit);
  } else {
    // Reverse subtract: (src << (shift + 1)) - src.
    DCHECK(power_of_two_minus_one);
    // TUNING: rsb dst, src, src lsl#LowestSetBit(lit + 1)
    int t_reg = AllocTemp(cu);
    cg->OpRegRegImm(cu, kOpLsl, t_reg, rl_src.low_reg, LowestSetBit(lit + 1));
    cg->OpRegRegReg(cu, kOpSub, rl_result.low_reg, t_reg, rl_src.low_reg);
  }
  cg->StoreValue(cu, rl_dest, rl_result);
  return true;
}

bool Codegen::GenArithOpIntLit(CompilationUnit* cu, Instruction::Code opcode,
                               RegLocation rl_dest, RegLocation rl_src, int lit)
{
  RegLocation rl_result;
  OpKind op = static_cast<OpKind>(0);    /* Make gcc happy */
  int shift_op = false;
  bool is_div = false;

  switch (opcode) {
    case Instruction::RSUB_INT_LIT8:
    case Instruction::RSUB_INT: {
      int t_reg;
      //TUNING: add support for use of Arm rsub op
      rl_src = LoadValue(cu, rl_src, kCoreReg);
      t_reg = AllocTemp(cu);
      LoadConstant(cu, t_reg, lit);
      rl_result = EvalLoc(cu, rl_dest, kCoreReg, true);
      OpRegRegReg(cu, kOpSub, rl_result.low_reg, t_reg, rl_src.low_reg);
      StoreValue(cu, rl_dest, rl_result);
      return false;
      break;
    }

    case Instruction::SUB_INT:
    case Instruction::SUB_INT_2ADDR:
      lit = -lit;
      // Intended fallthrough
    case Instruction::ADD_INT:
    case Instruction::ADD_INT_2ADDR:
    case Instruction::ADD_INT_LIT8:
    case Instruction::ADD_INT_LIT16:
      op = kOpAdd;
      break;
    case Instruction::MUL_INT:
    case Instruction::MUL_INT_2ADDR:
    case Instruction::MUL_INT_LIT8:
    case Instruction::MUL_INT_LIT16: {
      if (HandleEasyMultiply(cu, rl_src, rl_dest, lit)) {
        return false;
      }
      op = kOpMul;
      break;
    }
    case Instruction::AND_INT:
    case Instruction::AND_INT_2ADDR:
    case Instruction::AND_INT_LIT8:
    case Instruction::AND_INT_LIT16:
      op = kOpAnd;
      break;
    case Instruction::OR_INT:
    case Instruction::OR_INT_2ADDR:
    case Instruction::OR_INT_LIT8:
    case Instruction::OR_INT_LIT16:
      op = kOpOr;
      break;
    case Instruction::XOR_INT:
    case Instruction::XOR_INT_2ADDR:
    case Instruction::XOR_INT_LIT8:
    case Instruction::XOR_INT_LIT16:
      op = kOpXor;
      break;
    case Instruction::SHL_INT_LIT8:
    case Instruction::SHL_INT:
    case Instruction::SHL_INT_2ADDR:
      lit &= 31;
      shift_op = true;
      op = kOpLsl;
      break;
    case Instruction::SHR_INT_LIT8:
    case Instruction::SHR_INT:
    case Instruction::SHR_INT_2ADDR:
      lit &= 31;
      shift_op = true;
      op = kOpAsr;
      break;
    case Instruction::USHR_INT_LIT8:
    case Instruction::USHR_INT:
    case Instruction::USHR_INT_2ADDR:
      lit &= 31;
      shift_op = true;
      op = kOpLsr;
      break;

    case Instruction::DIV_INT:
    case Instruction::DIV_INT_2ADDR:
    case Instruction::DIV_INT_LIT8:
    case Instruction::DIV_INT_LIT16:
    case Instruction::REM_INT:
    case Instruction::REM_INT_2ADDR:
    case Instruction::REM_INT_LIT8:
    case Instruction::REM_INT_LIT16: {
      if (lit == 0) {
        GenImmedCheck(cu, kCondAl, 0, 0, kThrowDivZero);
        return false;
      }
      if (HandleEasyDivide(cu, opcode, rl_src, rl_dest, lit)) {
        return false;
      }
      if ((opcode == Instruction::DIV_INT_LIT8) ||
          (opcode == Instruction::DIV_INT) ||
          (opcode == Instruction::DIV_INT_2ADDR) ||
          (opcode == Instruction::DIV_INT_LIT16)) {
        is_div = true;
      } else {
        is_div = false;
      }
      if (cu->instruction_set == kMips) {
        rl_src = LoadValue(cu, rl_src, kCoreReg);
        rl_result = GenDivRemLit(cu, rl_dest, rl_src.low_reg, lit, is_div);
      } else {
        FlushAllRegs(cu);   /* Everything to home location */
        LoadValueDirectFixed(cu, rl_src, TargetReg(kArg0));
        Clobber(cu, TargetReg(kArg0));
        int func_offset = ENTRYPOINT_OFFSET(pIdivmod);
        CallRuntimeHelperRegImm(cu, func_offset, TargetReg(kArg0), lit, false);
        if (is_div)
          rl_result = GetReturn(cu, false);
        else
          rl_result = GetReturnAlt(cu);
      }
      StoreValue(cu, rl_dest, rl_result);
      return false;
      break;
    }
    default:
      LOG(FATAL) << "Unexpected opcode " << opcode;
  }
  rl_src = LoadValue(cu, rl_src, kCoreReg);
  rl_result = EvalLoc(cu, rl_dest, kCoreReg, true);
  // Avoid shifts by literal 0 - no support in Thumb.  Change to copy
  if (shift_op && (lit == 0)) {
    OpRegCopy(cu, rl_result.low_reg, rl_src.low_reg);
  } else {
    OpRegRegImm(cu, op, rl_result.low_reg, rl_src.low_reg, lit);
  }
  StoreValue(cu, rl_dest, rl_result);
  return false;
}

bool Codegen::GenArithOpLong(CompilationUnit* cu, Instruction::Code opcode, RegLocation rl_dest,
                             RegLocation rl_src1, RegLocation rl_src2)
{
  RegLocation rl_result;
  OpKind first_op = kOpBkpt;
  OpKind second_op = kOpBkpt;
  bool call_out = false;
  bool check_zero = false;
  int func_offset;
  int ret_reg = TargetReg(kRet0);

  switch (opcode) {
    case Instruction::NOT_LONG:
      rl_src2 = LoadValueWide(cu, rl_src2, kCoreReg);
      rl_result = EvalLoc(cu, rl_dest, kCoreReg, true);
      // Check for destructive overlap
      if (rl_result.low_reg == rl_src2.high_reg) {
        int t_reg = AllocTemp(cu);
        OpRegCopy(cu, t_reg, rl_src2.high_reg);
        OpRegReg(cu, kOpMvn, rl_result.low_reg, rl_src2.low_reg);
        OpRegReg(cu, kOpMvn, rl_result.high_reg, t_reg);
        FreeTemp(cu, t_reg);
      } else {
        OpRegReg(cu, kOpMvn, rl_result.low_reg, rl_src2.low_reg);
        OpRegReg(cu, kOpMvn, rl_result.high_reg, rl_src2.high_reg);
      }
      StoreValueWide(cu, rl_dest, rl_result);
      return false;
      break;
    case Instruction::ADD_LONG:
    case Instruction::ADD_LONG_2ADDR:
      if (cu->instruction_set != kThumb2) {
        return GenAddLong(cu, rl_dest, rl_src1, rl_src2);
      }
      first_op = kOpAdd;
      second_op = kOpAdc;
      break;
    case Instruction::SUB_LONG:
    case Instruction::SUB_LONG_2ADDR:
      if (cu->instruction_set != kThumb2) {
        return GenSubLong(cu, rl_dest, rl_src1, rl_src2);
      }
      first_op = kOpSub;
      second_op = kOpSbc;
      break;
    case Instruction::MUL_LONG:
    case Instruction::MUL_LONG_2ADDR:
      call_out = true;
      ret_reg = TargetReg(kRet0);
      func_offset = ENTRYPOINT_OFFSET(pLmul);
      break;
    case Instruction::DIV_LONG:
    case Instruction::DIV_LONG_2ADDR:
      call_out = true;
      check_zero = true;
      ret_reg = TargetReg(kRet0);
      func_offset = ENTRYPOINT_OFFSET(pLdiv);
      break;
    case Instruction::REM_LONG:
    case Instruction::REM_LONG_2ADDR:
      call_out = true;
      check_zero = true;
      func_offset = ENTRYPOINT_OFFSET(pLdivmod);
      /* NOTE - for Arm, result is in kArg2/kArg3 instead of kRet0/kRet1 */
      ret_reg = (cu->instruction_set == kThumb2) ? TargetReg(kArg2) : TargetReg(kRet0);
      break;
    case Instruction::AND_LONG_2ADDR:
    case Instruction::AND_LONG:
      if (cu->instruction_set == kX86) {
        return GenAndLong(cu, rl_dest, rl_src1, rl_src2);
      }
      first_op = kOpAnd;
      second_op = kOpAnd;
      break;
    case Instruction::OR_LONG:
    case Instruction::OR_LONG_2ADDR:
      if (cu->instruction_set == kX86) {
        return GenOrLong(cu, rl_dest, rl_src1, rl_src2);
      }
      first_op = kOpOr;
      second_op = kOpOr;
      break;
    case Instruction::XOR_LONG:
    case Instruction::XOR_LONG_2ADDR:
      if (cu->instruction_set == kX86) {
        return GenXorLong(cu, rl_dest, rl_src1, rl_src2);
      }
      first_op = kOpXor;
      second_op = kOpXor;
      break;
    case Instruction::NEG_LONG: {
      return GenNegLong(cu, rl_dest, rl_src2);
    }
    default:
      LOG(FATAL) << "Invalid long arith op";
  }
  if (!call_out) {
    GenLong3Addr(cu, first_op, second_op, rl_dest, rl_src1, rl_src2);
  } else {
    FlushAllRegs(cu);   /* Send everything to home location */
    if (check_zero) {
      LoadValueDirectWideFixed(cu, rl_src2, TargetReg(kArg2), TargetReg(kArg3));
      int r_tgt = CallHelperSetup(cu, func_offset);
      GenDivZeroCheck(cu, TargetReg(kArg2), TargetReg(kArg3));
      LoadValueDirectWideFixed(cu, rl_src1, TargetReg(kArg0), TargetReg(kArg1));
      // NOTE: callout here is not a safepoint
      CallHelper(cu, r_tgt, func_offset, false /* not safepoint */);
    } else {
      CallRuntimeHelperRegLocationRegLocation(cu, func_offset,
                          rl_src1, rl_src2, false);
    }
    // Adjust return regs in to handle case of rem returning kArg2/kArg3
    if (ret_reg == TargetReg(kRet0))
      rl_result = GetReturnWide(cu, false);
    else
      rl_result = GetReturnWideAlt(cu);
    StoreValueWide(cu, rl_dest, rl_result);
  }
  return false;
}

bool Codegen::GenConversionCall(CompilationUnit* cu, int func_offset,
                                RegLocation rl_dest, RegLocation rl_src)
{
  /*
   * Don't optimize the register usage since it calls out to support
   * functions
   */
  FlushAllRegs(cu);   /* Send everything to home location */
  if (rl_src.wide) {
    LoadValueDirectWideFixed(cu, rl_src, rl_src.fp ? TargetReg(kFArg0) : TargetReg(kArg0),
                             rl_src.fp ? TargetReg(kFArg1) : TargetReg(kArg1));
  } else {
    LoadValueDirectFixed(cu, rl_src, rl_src.fp ? TargetReg(kFArg0) : TargetReg(kArg0));
  }
  CallRuntimeHelperRegLocation(cu, func_offset, rl_src, false);
  if (rl_dest.wide) {
    RegLocation rl_result;
    rl_result = GetReturnWide(cu, rl_dest.fp);
    StoreValueWide(cu, rl_dest, rl_result);
  } else {
    RegLocation rl_result;
    rl_result = GetReturn(cu, rl_dest.fp);
    StoreValue(cu, rl_dest, rl_result);
  }
  return false;
}

/* Check if we need to check for pending suspend request */
void Codegen::GenSuspendTest(CompilationUnit* cu, int opt_flags)
{
  if (NO_SUSPEND || (opt_flags & MIR_IGNORE_SUSPEND_CHECK)) {
    return;
  }
  FlushAllRegs(cu);
  LIR* branch = OpTestSuspend(cu, NULL);
  LIR* ret_lab = NewLIR0(cu, kPseudoTargetLabel);
  LIR* target = RawLIR(cu, cu->current_dalvik_offset, kPseudoSuspendTarget,
                       reinterpret_cast<uintptr_t>(ret_lab), cu->current_dalvik_offset);
  branch->target = target;
  InsertGrowableList(cu, &cu->suspend_launchpads, reinterpret_cast<uintptr_t>(target));
}

/* Check if we need to check for pending suspend request */
void Codegen::GenSuspendTestAndBranch(CompilationUnit* cu, int opt_flags, LIR* target)
{
  if (NO_SUSPEND || (opt_flags & MIR_IGNORE_SUSPEND_CHECK)) {
    OpUnconditionalBranch(cu, target);
    return;
  }
  OpTestSuspend(cu, target);
  LIR* launch_pad =
      RawLIR(cu, cu->current_dalvik_offset, kPseudoSuspendTarget,
             reinterpret_cast<uintptr_t>(target), cu->current_dalvik_offset);
  FlushAllRegs(cu);
  OpUnconditionalBranch(cu, launch_pad);
  InsertGrowableList(cu, &cu->suspend_launchpads, reinterpret_cast<uintptr_t>(launch_pad));
}

}  // namespace art
