/*
 * 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 "codegen_util.h"
#include "compiler/dex/compiler_ir.h"
#include "invoke_type.h"
#include "oat/runtime/oat_support_entrypoints.h"
#include "ralloc_util.h"
#include "x86/codegen_x86.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.
 */

/*
 * To save scheduling time, helper calls are broken into two parts: generation of
 * the helper target address, and the actuall call to the helper.  Because x86
 * has a memory call operation, part 1 is a NOP for x86.  For other targets,
 * load arguments between the two parts.
 */
int Codegen::CallHelperSetup(CompilationUnit* cu, int helper_offset)
{
  return (cu->instruction_set == kX86) ? 0 : LoadHelper(cu, helper_offset);
}

/* NOTE: if r_tgt is a temp, it will be freed following use */
LIR* Codegen::CallHelper(CompilationUnit* cu, int r_tgt, int helper_offset, bool safepoint_pc)
{
  LIR* call_inst;
  if (cu->instruction_set == kX86) {
    call_inst = OpThreadMem(cu, kOpBlx, helper_offset);
  } else {
    call_inst = OpReg(cu, kOpBlx, r_tgt);
    FreeTemp(cu, r_tgt);
  }
  if (safepoint_pc) {
    MarkSafepointPC(cu, call_inst);
  }
  return call_inst;
}

void Codegen::CallRuntimeHelperImm(CompilationUnit* cu, int helper_offset, int arg0,
                                   bool safepoint_pc) {
  int r_tgt = CallHelperSetup(cu, helper_offset);
  LoadConstant(cu, TargetReg(kArg0), arg0);
  ClobberCalleeSave(cu);
  CallHelper(cu, r_tgt, helper_offset, safepoint_pc);
}

void Codegen::CallRuntimeHelperReg(CompilationUnit* cu, int helper_offset, int arg0,
                                   bool safepoint_pc) {
  int r_tgt = CallHelperSetup(cu, helper_offset);
  OpRegCopy(cu, TargetReg(kArg0), arg0);
  ClobberCalleeSave(cu);
  CallHelper(cu, r_tgt, helper_offset, safepoint_pc);
}

void Codegen::CallRuntimeHelperRegLocation(CompilationUnit* cu, int helper_offset, RegLocation arg0,
                                          bool safepoint_pc) {
  int r_tgt = CallHelperSetup(cu, helper_offset);
  if (arg0.wide == 0) {
    LoadValueDirectFixed(cu, arg0, TargetReg(kArg0));
  } else {
    LoadValueDirectWideFixed(cu, arg0, TargetReg(kArg0), TargetReg(kArg1));
  }
  ClobberCalleeSave(cu);
  CallHelper(cu, r_tgt, helper_offset, safepoint_pc);
}

void Codegen::CallRuntimeHelperImmImm(CompilationUnit* cu, int helper_offset, int arg0, int arg1,
                                      bool safepoint_pc) {
  int r_tgt = CallHelperSetup(cu, helper_offset);
  LoadConstant(cu, TargetReg(kArg0), arg0);
  LoadConstant(cu, TargetReg(kArg1), arg1);
  ClobberCalleeSave(cu);
  CallHelper(cu, r_tgt, helper_offset, safepoint_pc);
}

void Codegen::CallRuntimeHelperImmRegLocation(CompilationUnit* cu, int helper_offset, int arg0,
                                              RegLocation arg1, bool safepoint_pc) {
  int r_tgt = CallHelperSetup(cu, helper_offset);
  if (arg1.wide == 0) {
    LoadValueDirectFixed(cu, arg1, TargetReg(kArg1));
  } else {
    LoadValueDirectWideFixed(cu, arg1, TargetReg(kArg1), TargetReg(kArg2));
  }
  LoadConstant(cu, TargetReg(kArg0), arg0);
  ClobberCalleeSave(cu);
  CallHelper(cu, r_tgt, helper_offset, safepoint_pc);
}

void Codegen::CallRuntimeHelperRegLocationImm(CompilationUnit* cu, int helper_offset,
                                              RegLocation arg0, int arg1, bool safepoint_pc) {
  int r_tgt = CallHelperSetup(cu, helper_offset);
  LoadValueDirectFixed(cu, arg0, TargetReg(kArg0));
  LoadConstant(cu, TargetReg(kArg1), arg1);
  ClobberCalleeSave(cu);
  CallHelper(cu, r_tgt, helper_offset, safepoint_pc);
}

void Codegen::CallRuntimeHelperImmReg(CompilationUnit* cu, int helper_offset, int arg0, int arg1,
                                      bool safepoint_pc) {
  int r_tgt = CallHelperSetup(cu, helper_offset);
  OpRegCopy(cu, TargetReg(kArg1), arg1);
  LoadConstant(cu, TargetReg(kArg0), arg0);
  ClobberCalleeSave(cu);
  CallHelper(cu, r_tgt, helper_offset, safepoint_pc);
}

void Codegen::CallRuntimeHelperRegImm(CompilationUnit* cu, int helper_offset, int arg0, int arg1,
                             bool safepoint_pc) {
  int r_tgt = CallHelperSetup(cu, helper_offset);
  OpRegCopy(cu, TargetReg(kArg0), arg0);
  LoadConstant(cu, TargetReg(kArg1), arg1);
  ClobberCalleeSave(cu);
  CallHelper(cu, r_tgt, helper_offset, safepoint_pc);
}

void Codegen::CallRuntimeHelperImmMethod(CompilationUnit* cu, int helper_offset, int arg0,
                                         bool safepoint_pc) {
  int r_tgt = CallHelperSetup(cu, helper_offset);
  LoadCurrMethodDirect(cu, TargetReg(kArg1));
  LoadConstant(cu, TargetReg(kArg0), arg0);
  ClobberCalleeSave(cu);
  CallHelper(cu, r_tgt, helper_offset, safepoint_pc);
}

void Codegen::CallRuntimeHelperRegLocationRegLocation(CompilationUnit* cu, int helper_offset,
                                                      RegLocation arg0, RegLocation arg1,
                                                      bool safepoint_pc) {
  int r_tgt = CallHelperSetup(cu, helper_offset);
  if (arg0.wide == 0) {
    LoadValueDirectFixed(cu, arg0, arg0.fp ? TargetReg(kFArg0) : TargetReg(kArg0));
    if (arg1.wide == 0) {
      if (cu->instruction_set == kMips) {
        LoadValueDirectFixed(cu, arg1, arg1.fp ? TargetReg(kFArg2) : TargetReg(kArg1));
      } else {
        LoadValueDirectFixed(cu, arg1, TargetReg(kArg1));
      }
    } else {
      if (cu->instruction_set == kMips) {
        LoadValueDirectWideFixed(cu, arg1, arg1.fp ? TargetReg(kFArg2) : TargetReg(kArg1), arg1.fp ? TargetReg(kFArg3) : TargetReg(kArg2));
      } else {
        LoadValueDirectWideFixed(cu, arg1, TargetReg(kArg1), TargetReg(kArg2));
      }
    }
  } else {
    LoadValueDirectWideFixed(cu, arg0, arg0.fp ? TargetReg(kFArg0) : TargetReg(kArg0), arg0.fp ? TargetReg(kFArg1) : TargetReg(kArg1));
    if (arg1.wide == 0) {
      LoadValueDirectFixed(cu, arg1, arg1.fp ? TargetReg(kFArg2) : TargetReg(kArg2));
    } else {
      LoadValueDirectWideFixed(cu, arg1, arg1.fp ? TargetReg(kFArg2) : TargetReg(kArg2), arg1.fp ? TargetReg(kFArg3) : TargetReg(kArg3));
    }
  }
  ClobberCalleeSave(cu);
  CallHelper(cu, r_tgt, helper_offset, safepoint_pc);
}

void Codegen::CallRuntimeHelperRegReg(CompilationUnit* cu, int helper_offset, int arg0, int arg1,
                                      bool safepoint_pc) {
  int r_tgt = CallHelperSetup(cu, helper_offset);
  DCHECK_NE(TargetReg(kArg0), arg1);  // check copy into arg0 won't clobber arg1
  OpRegCopy(cu, TargetReg(kArg0), arg0);
  OpRegCopy(cu, TargetReg(kArg1), arg1);
  ClobberCalleeSave(cu);
  CallHelper(cu, r_tgt, helper_offset, safepoint_pc);
}

void Codegen::CallRuntimeHelperRegRegImm(CompilationUnit* cu, int helper_offset, int arg0, int arg1,
                                         int arg2, bool safepoint_pc) {
  int r_tgt = CallHelperSetup(cu, helper_offset);
  DCHECK_NE(TargetReg(kArg0), arg1);  // check copy into arg0 won't clobber arg1
  OpRegCopy(cu, TargetReg(kArg0), arg0);
  OpRegCopy(cu, TargetReg(kArg1), arg1);
  LoadConstant(cu, TargetReg(kArg2), arg2);
  ClobberCalleeSave(cu);
  CallHelper(cu, r_tgt, helper_offset, safepoint_pc);
}

void Codegen::CallRuntimeHelperImmMethodRegLocation(CompilationUnit* cu, int helper_offset,
                                                    int arg0, RegLocation arg2, bool safepoint_pc) {
  int r_tgt = CallHelperSetup(cu, helper_offset);
  LoadValueDirectFixed(cu, arg2, TargetReg(kArg2));
  LoadCurrMethodDirect(cu, TargetReg(kArg1));
  LoadConstant(cu, TargetReg(kArg0), arg0);
  ClobberCalleeSave(cu);
  CallHelper(cu, r_tgt, helper_offset, safepoint_pc);
}

void Codegen::CallRuntimeHelperImmMethodImm(CompilationUnit* cu, int helper_offset, int arg0,
                                            int arg2, bool safepoint_pc) {
  int r_tgt = CallHelperSetup(cu, helper_offset);
  LoadCurrMethodDirect(cu, TargetReg(kArg1));
  LoadConstant(cu, TargetReg(kArg2), arg2);
  LoadConstant(cu, TargetReg(kArg0), arg0);
  ClobberCalleeSave(cu);
  CallHelper(cu, r_tgt, helper_offset, safepoint_pc);
}

void Codegen::CallRuntimeHelperImmRegLocationRegLocation(CompilationUnit* cu, int helper_offset,
                                                         int arg0, RegLocation arg1,
                                                         RegLocation arg2, bool safepoint_pc) {
  int r_tgt = CallHelperSetup(cu, helper_offset);
  LoadValueDirectFixed(cu, arg1, TargetReg(kArg1));
  if (arg2.wide == 0) {
    LoadValueDirectFixed(cu, arg2, TargetReg(kArg2));
  } else {
    LoadValueDirectWideFixed(cu, arg2, TargetReg(kArg2), TargetReg(kArg3));
  }
  LoadConstant(cu, TargetReg(kArg0), arg0);
  ClobberCalleeSave(cu);
  CallHelper(cu, r_tgt, helper_offset, safepoint_pc);
}

/*
 * If there are any ins passed in registers that have not been promoted
 * to a callee-save register, flush them to the frame.  Perform intial
 * assignment of promoted arguments.
 *
 * ArgLocs is an array of location records describing the incoming arguments
 * with one location record per word of argument.
 */
void Codegen::FlushIns(CompilationUnit* cu, RegLocation* ArgLocs, RegLocation rl_method)
{
  /*
   * Dummy up a RegLocation for the incoming Method*
   * It will attempt to keep kArg0 live (or copy it to home location
   * if promoted).
   */
  RegLocation rl_src = rl_method;
  rl_src.location = kLocPhysReg;
  rl_src.low_reg = TargetReg(kArg0);
  rl_src.home = false;
  MarkLive(cu, rl_src.low_reg, rl_src.s_reg_low);
  StoreValue(cu, rl_method, rl_src);
  // If Method* has been promoted, explicitly flush
  if (rl_method.location == kLocPhysReg) {
    StoreWordDisp(cu, TargetReg(kSp), 0, TargetReg(kArg0));
  }

  if (cu->num_ins == 0)
    return;
  const int num_arg_regs = 3;
  static SpecialTargetRegister arg_regs[] = {kArg1, kArg2, kArg3};
  int start_vreg = cu->num_dalvik_registers - cu->num_ins;
  /*
   * Copy incoming arguments to their proper home locations.
   * NOTE: an older version of dx had an issue in which
   * it would reuse static method argument registers.
   * This could result in the same Dalvik virtual register
   * being promoted to both core and fp regs. To account for this,
   * we only copy to the corresponding promoted physical register
   * if it matches the type of the SSA name for the incoming
   * argument.  It is also possible that long and double arguments
   * end up half-promoted.  In those cases, we must flush the promoted
   * half to memory as well.
   */
  for (int i = 0; i < cu->num_ins; i++) {
    PromotionMap* v_map = &cu->promotion_map[start_vreg + i];
    if (i < num_arg_regs) {
      // If arriving in register
      bool need_flush = true;
      RegLocation* t_loc = &ArgLocs[i];
      if ((v_map->core_location == kLocPhysReg) && !t_loc->fp) {
        OpRegCopy(cu, v_map->core_reg, TargetReg(arg_regs[i]));
        need_flush = false;
      } else if ((v_map->fp_location == kLocPhysReg) && t_loc->fp) {
        OpRegCopy(cu, v_map->FpReg, TargetReg(arg_regs[i]));
        need_flush = false;
      } else {
        need_flush = true;
      }

      // For wide args, force flush if only half is promoted
      if (t_loc->wide) {
        PromotionMap* p_map = v_map + (t_loc->high_word ? -1 : +1);
        need_flush |= (p_map->core_location != v_map->core_location) ||
            (p_map->fp_location != v_map->fp_location);
      }
      if (need_flush) {
        StoreBaseDisp(cu, TargetReg(kSp), SRegOffset(cu, start_vreg + i),
                      TargetReg(arg_regs[i]), kWord);
      }
    } else {
      // If arriving in frame & promoted
      if (v_map->core_location == kLocPhysReg) {
        LoadWordDisp(cu, TargetReg(kSp), SRegOffset(cu, start_vreg + i),
                     v_map->core_reg);
      }
      if (v_map->fp_location == kLocPhysReg) {
        LoadWordDisp(cu, TargetReg(kSp), SRegOffset(cu, start_vreg + i),
                     v_map->FpReg);
      }
    }
  }
}

/*
 * Bit of a hack here - in the absence of a real scheduling pass,
 * emit the next instruction in static & direct invoke sequences.
 */
static int NextSDCallInsn(CompilationUnit* cu, CallInfo* info,
                          int state, uint32_t dex_idx, uint32_t unused,
                          uintptr_t direct_code, uintptr_t direct_method,
                          InvokeType type)
{
  Codegen* cg = cu->cg.get();
  if (cu->instruction_set != kThumb2) {
    // Disable sharpening
    direct_code = 0;
    direct_method = 0;
  }
  if (direct_code != 0 && direct_method != 0) {
    switch (state) {
    case 0:  // Get the current Method* [sets kArg0]
      if (direct_code != static_cast<unsigned int>(-1)) {
        cg->LoadConstant(cu, cg->TargetReg(kInvokeTgt), direct_code);
      } else {
        LIR* data_target = ScanLiteralPool(cu->code_literal_list, dex_idx, 0);
        if (data_target == NULL) {
          data_target = AddWordData(cu, &cu->code_literal_list, dex_idx);
          data_target->operands[1] = type;
        }
        LIR* load_pc_rel = cg->OpPcRelLoad(cu, cg->TargetReg(kInvokeTgt), data_target);
        AppendLIR(cu, load_pc_rel);
        DCHECK_EQ(cu->instruction_set, kThumb2) << reinterpret_cast<void*>(data_target);
      }
      if (direct_method != static_cast<unsigned int>(-1)) {
        cg->LoadConstant(cu, cg->TargetReg(kArg0), direct_method);
      } else {
        LIR* data_target = ScanLiteralPool(cu->method_literal_list, dex_idx, 0);
        if (data_target == NULL) {
          data_target = AddWordData(cu, &cu->method_literal_list, dex_idx);
          data_target->operands[1] = type;
        }
        LIR* load_pc_rel = cg->OpPcRelLoad(cu, cg->TargetReg(kArg0), data_target);
        AppendLIR(cu, load_pc_rel);
        DCHECK_EQ(cu->instruction_set, kThumb2) << reinterpret_cast<void*>(data_target);
      }
      break;
    default:
      return -1;
    }
  } else {
    switch (state) {
    case 0:  // Get the current Method* [sets kArg0]
      // TUNING: we can save a reg copy if Method* has been promoted.
      cg->LoadCurrMethodDirect(cu, cg->TargetReg(kArg0));
      break;
    case 1:  // Get method->dex_cache_resolved_methods_
      cg->LoadWordDisp(cu, cg->TargetReg(kArg0),
        mirror::AbstractMethod::DexCacheResolvedMethodsOffset().Int32Value(), cg->TargetReg(kArg0));
      // Set up direct code if known.
      if (direct_code != 0) {
        if (direct_code != static_cast<unsigned int>(-1)) {
          cg->LoadConstant(cu, cg->TargetReg(kInvokeTgt), direct_code);
        } else {
          LIR* data_target = ScanLiteralPool(cu->code_literal_list, dex_idx, 0);
          if (data_target == NULL) {
            data_target = AddWordData(cu, &cu->code_literal_list, dex_idx);
            data_target->operands[1] = type;
          }
          LIR* load_pc_rel = cg->OpPcRelLoad(cu, cg->TargetReg(kInvokeTgt), data_target);
          AppendLIR(cu, load_pc_rel);
          DCHECK_EQ(cu->instruction_set, kThumb2) << reinterpret_cast<void*>(data_target);
        }
      }
      break;
    case 2:  // Grab target method*
      cg->LoadWordDisp(cu, cg->TargetReg(kArg0),
                       mirror::Array::DataOffset(sizeof(mirror::Object*)).Int32Value() + dex_idx * 4,
                       cg-> TargetReg(kArg0));
      break;
    case 3:  // Grab the code from the method*
      if (cu->instruction_set != kX86) {
        if (direct_code == 0) {
          cg->LoadWordDisp(cu, cg->TargetReg(kArg0),
                           mirror::AbstractMethod::GetCodeOffset().Int32Value(),
                           cg->TargetReg(kInvokeTgt));
        }
        break;
      }
      // Intentional fallthrough for x86
    default:
      return -1;
    }
  }
  return state + 1;
}

/*
 * Bit of a hack here - in the absence of a real scheduling pass,
 * emit the next instruction in a virtual invoke sequence.
 * We can use kLr as a temp prior to target address loading
 * Note also that we'll load the first argument ("this") into
 * kArg1 here rather than the standard LoadArgRegs.
 */
static int NextVCallInsn(CompilationUnit* cu, CallInfo* info,
                         int state, uint32_t dex_idx, uint32_t method_idx,
                         uintptr_t unused, uintptr_t unused2, InvokeType unused3)
{
  Codegen* cg = cu->cg.get();
  /*
   * This is the fast path in which the target virtual method is
   * fully resolved at compile time.
   */
  switch (state) {
    case 0: {  // Get "this" [set kArg1]
      RegLocation  rl_arg = info->args[0];
      cg->LoadValueDirectFixed(cu, rl_arg, cg->TargetReg(kArg1));
      break;
    }
    case 1: // Is "this" null? [use kArg1]
      cg->GenNullCheck(cu, info->args[0].s_reg_low, cg->TargetReg(kArg1), info->opt_flags);
      // get this->klass_ [use kArg1, set kInvokeTgt]
      cg->LoadWordDisp(cu, cg->TargetReg(kArg1), mirror::Object::ClassOffset().Int32Value(),
                       cg->TargetReg(kInvokeTgt));
      break;
    case 2: // Get this->klass_->vtable [usr kInvokeTgt, set kInvokeTgt]
      cg->LoadWordDisp(cu, cg->TargetReg(kInvokeTgt), mirror::Class::VTableOffset().Int32Value(),
                       cg->TargetReg(kInvokeTgt));
      break;
    case 3: // Get target method [use kInvokeTgt, set kArg0]
      cg->LoadWordDisp(cu, cg->TargetReg(kInvokeTgt), (method_idx * 4) +
                       mirror::Array::DataOffset(sizeof(mirror::Object*)).Int32Value(),
                       cg->TargetReg(kArg0));
      break;
    case 4: // Get the compiled code address [uses kArg0, sets kInvokeTgt]
      if (cu->instruction_set != kX86) {
        cg->LoadWordDisp(cu, cg->TargetReg(kArg0),
                         mirror::AbstractMethod::GetCodeOffset().Int32Value(),
                         cg->TargetReg(kInvokeTgt));
        break;
      }
      // Intentional fallthrough for X86
    default:
      return -1;
  }
  return state + 1;
}

/*
 * All invoke-interface calls bounce off of art_quick_invoke_interface_trampoline,
 * which will locate the target and continue on via a tail call.
 */
static int NextInterfaceCallInsn(CompilationUnit* cu, CallInfo* info, int state,
                                 uint32_t dex_idx, uint32_t unused, uintptr_t unused2,
                                 uintptr_t direct_method, InvokeType unused4)
{
  Codegen* cg = cu->cg.get();
  if (cu->instruction_set != kThumb2) {
    // Disable sharpening
    direct_method = 0;
  }
  int trampoline = (cu->instruction_set == kX86) ? 0
      : ENTRYPOINT_OFFSET(pInvokeInterfaceTrampoline);

  if (direct_method != 0) {
    switch (state) {
      case 0:  // Load the trampoline target [sets kInvokeTgt].
        if (cu->instruction_set != kX86) {
          cg->LoadWordDisp(cu, cg->TargetReg(kSelf), trampoline, cg->TargetReg(kInvokeTgt));
        }
        // Get the interface Method* [sets kArg0]
        if (direct_method != static_cast<unsigned int>(-1)) {
          cg->LoadConstant(cu, cg->TargetReg(kArg0), direct_method);
        } else {
          LIR* data_target = ScanLiteralPool(cu->method_literal_list, dex_idx, 0);
          if (data_target == NULL) {
            data_target = AddWordData(cu, &cu->method_literal_list, dex_idx);
            data_target->operands[1] = kInterface;
          }
          LIR* load_pc_rel = cg->OpPcRelLoad(cu, cg->TargetReg(kArg0), data_target);
          AppendLIR(cu, load_pc_rel);
          DCHECK_EQ(cu->instruction_set, kThumb2) << reinterpret_cast<void*>(data_target);
        }
        break;
      default:
        return -1;
    }
  } else {
    switch (state) {
      case 0:
        // Get the current Method* [sets kArg0] - TUNING: remove copy of method if it is promoted.
        cg->LoadCurrMethodDirect(cu, cg->TargetReg(kArg0));
        // Load the trampoline target [sets kInvokeTgt].
        if (cu->instruction_set != kX86) {
          cg->LoadWordDisp(cu, cg->TargetReg(kSelf), trampoline, cg->TargetReg(kInvokeTgt));
        }
        break;
    case 1:  // Get method->dex_cache_resolved_methods_ [set/use kArg0]
      cg->LoadWordDisp(cu, cg->TargetReg(kArg0),
                       mirror::AbstractMethod::DexCacheResolvedMethodsOffset().Int32Value(),
                       cg->TargetReg(kArg0));
      break;
    case 2:  // Grab target method* [set/use kArg0]
      cg->LoadWordDisp(cu, cg->TargetReg(kArg0),
                       mirror::Array::DataOffset(sizeof(mirror::Object*)).Int32Value() + dex_idx * 4,
                       cg->TargetReg(kArg0));
      break;
    default:
      return -1;
    }
  }
  return state + 1;
}

static int NextInvokeInsnSP(CompilationUnit* cu, CallInfo* info, int trampoline,
                            int state, uint32_t dex_idx, uint32_t method_idx)
{
  Codegen* cg = cu->cg.get();
  /*
   * This handles the case in which the base method is not fully
   * resolved at compile time, we bail to a runtime helper.
   */
  if (state == 0) {
    if (cu->instruction_set != kX86) {
      // Load trampoline target
      cg->LoadWordDisp(cu, cg->TargetReg(kSelf), trampoline, cg->TargetReg(kInvokeTgt));
    }
    // Load kArg0 with method index
    cg->LoadConstant(cu, cg->TargetReg(kArg0), dex_idx);
    return 1;
  }
  return -1;
}

static int NextStaticCallInsnSP(CompilationUnit* cu, CallInfo* info,
                                int state, uint32_t dex_idx, uint32_t method_idx,
                                uintptr_t unused, uintptr_t unused2,
                         InvokeType unused3)
{
  int trampoline = ENTRYPOINT_OFFSET(pInvokeStaticTrampolineWithAccessCheck);
  return NextInvokeInsnSP(cu, info, trampoline, state, dex_idx, 0);
}

static int NextDirectCallInsnSP(CompilationUnit* cu, CallInfo* info, int state,
                                uint32_t dex_idx, uint32_t method_idx, uintptr_t unused,
                                uintptr_t unused2, InvokeType unused3)
{
  int trampoline = ENTRYPOINT_OFFSET(pInvokeDirectTrampolineWithAccessCheck);
  return NextInvokeInsnSP(cu, info, trampoline, state, dex_idx, 0);
}

static int NextSuperCallInsnSP(CompilationUnit* cu, CallInfo* info, int state,
                               uint32_t dex_idx, uint32_t method_idx, uintptr_t unused,
                        uintptr_t unused2, InvokeType unused3)
{
  int trampoline = ENTRYPOINT_OFFSET(pInvokeSuperTrampolineWithAccessCheck);
  return NextInvokeInsnSP(cu, info, trampoline, state, dex_idx, 0);
}

static int NextVCallInsnSP(CompilationUnit* cu, CallInfo* info, int state,
                           uint32_t dex_idx, uint32_t method_idx, uintptr_t unused,
                           uintptr_t unused2, InvokeType unused3)
{
  int trampoline = ENTRYPOINT_OFFSET(pInvokeVirtualTrampolineWithAccessCheck);
  return NextInvokeInsnSP(cu, info, trampoline, state, dex_idx, 0);
}

static int NextInterfaceCallInsnWithAccessCheck(CompilationUnit* cu,
                                                CallInfo* info, int state,
                                         uint32_t dex_idx, uint32_t unused,
                                         uintptr_t unused2, uintptr_t unused3,
                                         InvokeType unused4)
{
  int trampoline = ENTRYPOINT_OFFSET(pInvokeInterfaceTrampolineWithAccessCheck);
  return NextInvokeInsnSP(cu, info, trampoline, state, dex_idx, 0);
}

static int LoadArgRegs(CompilationUnit* cu, CallInfo* info, int call_state,
                       NextCallInsn next_call_insn, uint32_t dex_idx,
                       uint32_t method_idx, uintptr_t direct_code,
                       uintptr_t direct_method, InvokeType type, bool skip_this)
{
  Codegen* cg = cu->cg.get();
  int last_arg_reg = cg->TargetReg(kArg3);
  int next_reg = cg->TargetReg(kArg1);
  int next_arg = 0;
  if (skip_this) {
    next_reg++;
    next_arg++;
  }
  for (; (next_reg <= last_arg_reg) && (next_arg < info->num_arg_words); next_reg++) {
    RegLocation rl_arg = info->args[next_arg++];
    rl_arg = UpdateRawLoc(cu, rl_arg);
    if (rl_arg.wide && (next_reg <= cg->TargetReg(kArg2))) {
      cg->LoadValueDirectWideFixed(cu, rl_arg, next_reg, next_reg + 1);
      next_reg++;
      next_arg++;
    } else {
      if (rl_arg.wide) {
        rl_arg.wide = false;
        rl_arg.is_const = false;
      }
      cg->LoadValueDirectFixed(cu, rl_arg, next_reg);
    }
    call_state = next_call_insn(cu, info, call_state, dex_idx, method_idx,
                 direct_code, direct_method, type);
  }
  return call_state;
}

/*
 * Load up to 5 arguments, the first three of which will be in
 * kArg1 .. kArg3.  On entry kArg0 contains the current method pointer,
 * and as part of the load sequence, it must be replaced with
 * the target method pointer.  Note, this may also be called
 * for "range" variants if the number of arguments is 5 or fewer.
 */
int Codegen::GenDalvikArgsNoRange(CompilationUnit* cu, CallInfo* info,
                                  int call_state, LIR** pcrLabel, NextCallInsn next_call_insn,
                                  uint32_t dex_idx, uint32_t method_idx, uintptr_t direct_code,
                                  uintptr_t direct_method, InvokeType type, bool skip_this)
{
  RegLocation rl_arg;

  /* If no arguments, just return */
  if (info->num_arg_words == 0)
    return call_state;

  call_state = next_call_insn(cu, info, call_state, dex_idx, method_idx,
                           direct_code, direct_method, type);

  DCHECK_LE(info->num_arg_words, 5);
  if (info->num_arg_words > 3) {
    int32_t next_use = 3;
    //Detect special case of wide arg spanning arg3/arg4
    RegLocation rl_use0 = info->args[0];
    RegLocation rl_use1 = info->args[1];
    RegLocation rl_use2 = info->args[2];
    if (((!rl_use0.wide && !rl_use1.wide) || rl_use0.wide) &&
      rl_use2.wide) {
      int reg = -1;
      // Wide spans, we need the 2nd half of uses[2].
      rl_arg = UpdateLocWide(cu, rl_use2);
      if (rl_arg.location == kLocPhysReg) {
        reg = rl_arg.high_reg;
      } else {
        // kArg2 & rArg3 can safely be used here
        reg = TargetReg(kArg3);
        LoadWordDisp(cu, TargetReg(kSp), SRegOffset(cu, rl_arg.s_reg_low) + 4, reg);
        call_state = next_call_insn(cu, info, call_state, dex_idx,
                                 method_idx, direct_code, direct_method, type);
      }
      StoreBaseDisp(cu, TargetReg(kSp), (next_use + 1) * 4, reg, kWord);
      StoreBaseDisp(cu, TargetReg(kSp), 16 /* (3+1)*4 */, reg, kWord);
      call_state = next_call_insn(cu, info, call_state, dex_idx, method_idx,
                               direct_code, direct_method, type);
      next_use++;
    }
    // Loop through the rest
    while (next_use < info->num_arg_words) {
      int low_reg;
      int high_reg = -1;
      rl_arg = info->args[next_use];
      rl_arg = UpdateRawLoc(cu, rl_arg);
      if (rl_arg.location == kLocPhysReg) {
        low_reg = rl_arg.low_reg;
        high_reg = rl_arg.high_reg;
      } else {
        low_reg = TargetReg(kArg2);
        if (rl_arg.wide) {
          high_reg = TargetReg(kArg3);
          LoadValueDirectWideFixed(cu, rl_arg, low_reg, high_reg);
        } else {
          LoadValueDirectFixed(cu, rl_arg, low_reg);
        }
        call_state = next_call_insn(cu, info, call_state, dex_idx,
                                 method_idx, direct_code, direct_method, type);
      }
      int outs_offset = (next_use + 1) * 4;
      if (rl_arg.wide) {
        StoreBaseDispWide(cu, TargetReg(kSp), outs_offset, low_reg, high_reg);
        next_use += 2;
      } else {
        StoreWordDisp(cu, TargetReg(kSp), outs_offset, low_reg);
        next_use++;
      }
      call_state = next_call_insn(cu, info, call_state, dex_idx, method_idx,
                               direct_code, direct_method, type);
    }
  }

  call_state = LoadArgRegs(cu, info, call_state, next_call_insn,
                          dex_idx, method_idx, direct_code, direct_method,
                          type, skip_this);

  if (pcrLabel) {
    *pcrLabel = GenNullCheck(cu, info->args[0].s_reg_low, TargetReg(kArg1), info->opt_flags);
  }
  return call_state;
}

/*
 * May have 0+ arguments (also used for jumbo).  Note that
 * source virtual registers may be in physical registers, so may
 * need to be flushed to home location before copying.  This
 * applies to arg3 and above (see below).
 *
 * Two general strategies:
 *    If < 20 arguments
 *       Pass args 3-18 using vldm/vstm block copy
 *       Pass arg0, arg1 & arg2 in kArg1-kArg3
 *    If 20+ arguments
 *       Pass args arg19+ using memcpy block copy
 *       Pass arg0, arg1 & arg2 in kArg1-kArg3
 *
 */
int Codegen::GenDalvikArgsRange(CompilationUnit* cu, CallInfo* info, int call_state,
                                LIR** pcrLabel, NextCallInsn next_call_insn, uint32_t dex_idx,
                                uint32_t method_idx, uintptr_t direct_code, uintptr_t direct_method,
                                InvokeType type, bool skip_this)
{

  // If we can treat it as non-range (Jumbo ops will use range form)
  if (info->num_arg_words <= 5)
    return GenDalvikArgsNoRange(cu, info, call_state, pcrLabel,
                                next_call_insn, dex_idx, method_idx,
                                direct_code, direct_method, type, skip_this);
  /*
   * First load the non-register arguments.  Both forms expect all
   * of the source arguments to be in their home frame location, so
   * scan the s_reg names and flush any that have been promoted to
   * frame backing storage.
   */
  // Scan the rest of the args - if in phys_reg flush to memory
  for (int next_arg = 0; next_arg < info->num_arg_words;) {
    RegLocation loc = info->args[next_arg];
    if (loc.wide) {
      loc = UpdateLocWide(cu, loc);
      if ((next_arg >= 2) && (loc.location == kLocPhysReg)) {
        StoreBaseDispWide(cu, TargetReg(kSp), SRegOffset(cu, loc.s_reg_low),
                          loc.low_reg, loc.high_reg);
      }
      next_arg += 2;
    } else {
      loc = UpdateLoc(cu, loc);
      if ((next_arg >= 3) && (loc.location == kLocPhysReg)) {
        StoreBaseDisp(cu, TargetReg(kSp), SRegOffset(cu, loc.s_reg_low),
                      loc.low_reg, kWord);
      }
      next_arg++;
    }
  }

  int start_offset = SRegOffset(cu, info->args[3].s_reg_low);
  int outs_offset = 4 /* Method* */ + (3 * 4);
  if (cu->instruction_set != kThumb2) {
    // Generate memcpy
    OpRegRegImm(cu, kOpAdd, TargetReg(kArg0), TargetReg(kSp), outs_offset);
    OpRegRegImm(cu, kOpAdd, TargetReg(kArg1), TargetReg(kSp), start_offset);
    CallRuntimeHelperRegRegImm(cu, ENTRYPOINT_OFFSET(pMemcpy), TargetReg(kArg0),
                               TargetReg(kArg1), (info->num_arg_words - 3) * 4, false);
  } else {
    if (info->num_arg_words >= 20) {
      // Generate memcpy
      OpRegRegImm(cu, kOpAdd, TargetReg(kArg0), TargetReg(kSp), outs_offset);
      OpRegRegImm(cu, kOpAdd, TargetReg(kArg1), TargetReg(kSp), start_offset);
      CallRuntimeHelperRegRegImm(cu, ENTRYPOINT_OFFSET(pMemcpy), TargetReg(kArg0),
                                 TargetReg(kArg1), (info->num_arg_words - 3) * 4, false);
    } else {
      // Use vldm/vstm pair using kArg3 as a temp
      int regs_left = std::min(info->num_arg_words - 3, 16);
      call_state = next_call_insn(cu, info, call_state, dex_idx, method_idx,
                               direct_code, direct_method, type);
      OpRegRegImm(cu, kOpAdd, TargetReg(kArg3), TargetReg(kSp), start_offset);
      LIR* ld = OpVldm(cu, TargetReg(kArg3), regs_left);
      //TUNING: loosen barrier
      ld->def_mask = ENCODE_ALL;
      SetMemRefType(cu, ld, true /* is_load */, kDalvikReg);
      call_state = next_call_insn(cu, info, call_state, dex_idx, method_idx,
                               direct_code, direct_method, type);
      OpRegRegImm(cu, kOpAdd, TargetReg(kArg3), TargetReg(kSp), 4 /* Method* */ + (3 * 4));
      call_state = next_call_insn(cu, info, call_state, dex_idx, method_idx,
                               direct_code, direct_method, type);
      LIR* st = OpVstm(cu, TargetReg(kArg3), regs_left);
      SetMemRefType(cu, st, false /* is_load */, kDalvikReg);
      st->def_mask = ENCODE_ALL;
      call_state = next_call_insn(cu, info, call_state, dex_idx, method_idx,
                               direct_code, direct_method, type);
    }
  }

  call_state = LoadArgRegs(cu, info, call_state, next_call_insn,
                          dex_idx, method_idx, direct_code, direct_method,
                          type, skip_this);

  call_state = next_call_insn(cu, info, call_state, dex_idx, method_idx,
                           direct_code, direct_method, type);
  if (pcrLabel) {
    *pcrLabel = GenNullCheck(cu, info->args[0].s_reg_low, TargetReg(kArg1),
                             info->opt_flags);
  }
  return call_state;
}

RegLocation Codegen::InlineTarget(CompilationUnit* cu, CallInfo* info)
{
  RegLocation res;
  if (info->result.location == kLocInvalid) {
    res = GetReturn(cu, false);
  } else {
    res = info->result;
  }
  return res;
}

RegLocation Codegen::InlineTargetWide(CompilationUnit* cu, CallInfo* info)
{
  RegLocation res;
  if (info->result.location == kLocInvalid) {
    res = GetReturnWide(cu, false);
  } else {
    res = info->result;
  }
  return res;
}

bool Codegen::GenInlinedCharAt(CompilationUnit* cu, CallInfo* info)
{
  if (cu->instruction_set == kMips) {
    // TODO - add Mips implementation
    return false;
  }
  // Location of reference to data array
  int value_offset = mirror::String::ValueOffset().Int32Value();
  // Location of count
  int count_offset = mirror::String::CountOffset().Int32Value();
  // Starting offset within data array
  int offset_offset = mirror::String::OffsetOffset().Int32Value();
  // Start of char data with array_
  int data_offset = mirror::Array::DataOffset(sizeof(uint16_t)).Int32Value();

  RegLocation rl_obj = info->args[0];
  RegLocation rl_idx = info->args[1];
  rl_obj = LoadValue(cu, rl_obj, kCoreReg);
  rl_idx = LoadValue(cu, rl_idx, kCoreReg);
  int reg_max;
  GenNullCheck(cu, rl_obj.s_reg_low, rl_obj.low_reg, info->opt_flags);
  bool range_check = (!(info->opt_flags & MIR_IGNORE_RANGE_CHECK));
  LIR* launch_pad = NULL;
  int reg_off = INVALID_REG;
  int reg_ptr = INVALID_REG;
  if (cu->instruction_set != kX86) {
    reg_off = AllocTemp(cu);
    reg_ptr = AllocTemp(cu);
    if (range_check) {
      reg_max = AllocTemp(cu);
      LoadWordDisp(cu, rl_obj.low_reg, count_offset, reg_max);
    }
    LoadWordDisp(cu, rl_obj.low_reg, offset_offset, reg_off);
    LoadWordDisp(cu, rl_obj.low_reg, value_offset, reg_ptr);
    if (range_check) {
      // Set up a launch pad to allow retry in case of bounds violation */
      launch_pad = RawLIR(cu, 0, kPseudoIntrinsicRetry, reinterpret_cast<uintptr_t>(info));
      InsertGrowableList(cu, &cu->intrinsic_launchpads,
                            reinterpret_cast<uintptr_t>(launch_pad));
      OpRegReg(cu, kOpCmp, rl_idx.low_reg, reg_max);
      FreeTemp(cu, reg_max);
      OpCondBranch(cu, kCondCs, launch_pad);
   }
  } else {
    if (range_check) {
      reg_max = AllocTemp(cu);
      LoadWordDisp(cu, rl_obj.low_reg, count_offset, reg_max);
      // Set up a launch pad to allow retry in case of bounds violation */
      launch_pad = RawLIR(cu, 0, kPseudoIntrinsicRetry, reinterpret_cast<uintptr_t>(info));
      InsertGrowableList(cu, &cu->intrinsic_launchpads,
                            reinterpret_cast<uintptr_t>(launch_pad));
      OpRegReg(cu, kOpCmp, rl_idx.low_reg, reg_max);
      FreeTemp(cu, reg_max);
      OpCondBranch(cu, kCondCc, launch_pad);
    }
    reg_off = AllocTemp(cu);
    reg_ptr = AllocTemp(cu);
    LoadWordDisp(cu, rl_obj.low_reg, offset_offset, reg_off);
    LoadWordDisp(cu, rl_obj.low_reg, value_offset, reg_ptr);
  }
  OpRegImm(cu, kOpAdd, reg_ptr, data_offset);
  OpRegReg(cu, kOpAdd, reg_off, rl_idx.low_reg);
  FreeTemp(cu, rl_obj.low_reg);
  FreeTemp(cu, rl_idx.low_reg);
  RegLocation rl_dest = InlineTarget(cu, info);
  RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true);
  LoadBaseIndexed(cu, reg_ptr, reg_off, rl_result.low_reg, 1, kUnsignedHalf);
  FreeTemp(cu, reg_off);
  FreeTemp(cu, reg_ptr);
  StoreValue(cu, rl_dest, rl_result);
  if (range_check) {
    launch_pad->operands[2] = 0;  // no resumption
  }
  // Record that we've already inlined & null checked
  info->opt_flags |= (MIR_INLINED | MIR_IGNORE_NULL_CHECK);
  return true;
}

// Generates an inlined String.is_empty or String.length.
bool Codegen::GenInlinedStringIsEmptyOrLength(CompilationUnit* cu, CallInfo* info, bool is_empty)
{
  if (cu->instruction_set == kMips) {
    // TODO - add Mips implementation
    return false;
  }
  // dst = src.length();
  RegLocation rl_obj = info->args[0];
  rl_obj = LoadValue(cu, rl_obj, kCoreReg);
  RegLocation rl_dest = InlineTarget(cu, info);
  RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true);
  GenNullCheck(cu, rl_obj.s_reg_low, rl_obj.low_reg, info->opt_flags);
  LoadWordDisp(cu, rl_obj.low_reg, mirror::String::CountOffset().Int32Value(),
               rl_result.low_reg);
  if (is_empty) {
    // dst = (dst == 0);
    if (cu->instruction_set == kThumb2) {
      int t_reg = AllocTemp(cu);
      OpRegReg(cu, kOpNeg, t_reg, rl_result.low_reg);
      OpRegRegReg(cu, kOpAdc, rl_result.low_reg, rl_result.low_reg, t_reg);
    } else {
      DCHECK_EQ(cu->instruction_set, kX86);
      OpRegImm(cu, kOpSub, rl_result.low_reg, 1);
      OpRegImm(cu, kOpLsr, rl_result.low_reg, 31);
    }
  }
  StoreValue(cu, rl_dest, rl_result);
  return true;
}

bool Codegen::GenInlinedAbsInt(CompilationUnit *cu, CallInfo* info)
{
  if (cu->instruction_set == kMips) {
    // TODO - add Mips implementation
    return false;
  }
  RegLocation rl_src = info->args[0];
  rl_src = LoadValue(cu, rl_src, kCoreReg);
  RegLocation rl_dest = InlineTarget(cu, info);
  RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true);
  int sign_reg = AllocTemp(cu);
  // abs(x) = y<=x>>31, (x+y)^y.
  OpRegRegImm(cu, kOpAsr, sign_reg, rl_src.low_reg, 31);
  OpRegRegReg(cu, kOpAdd, rl_result.low_reg, rl_src.low_reg, sign_reg);
  OpRegReg(cu, kOpXor, rl_result.low_reg, sign_reg);
  StoreValue(cu, rl_dest, rl_result);
  return true;
}

bool Codegen::GenInlinedAbsLong(CompilationUnit *cu, CallInfo* info)
{
  if (cu->instruction_set == kMips) {
    // TODO - add Mips implementation
    return false;
  }
  if (cu->instruction_set == kThumb2) {
    RegLocation rl_src = info->args[0];
    rl_src = LoadValueWide(cu, rl_src, kCoreReg);
    RegLocation rl_dest = InlineTargetWide(cu, info);
    RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true);
    int sign_reg = AllocTemp(cu);
    // abs(x) = y<=x>>31, (x+y)^y.
    OpRegRegImm(cu, kOpAsr, sign_reg, rl_src.high_reg, 31);
    OpRegRegReg(cu, kOpAdd, rl_result.low_reg, rl_src.low_reg, sign_reg);
    OpRegRegReg(cu, kOpAdc, rl_result.high_reg, rl_src.high_reg, sign_reg);
    OpRegReg(cu, kOpXor, rl_result.low_reg, sign_reg);
    OpRegReg(cu, kOpXor, rl_result.high_reg, sign_reg);
    StoreValueWide(cu, rl_dest, rl_result);
    return true;
  } else {
    DCHECK_EQ(cu->instruction_set, kX86);
    // Reuse source registers to avoid running out of temps
    RegLocation rl_src = info->args[0];
    rl_src = LoadValueWide(cu, rl_src, kCoreReg);
    RegLocation rl_dest = InlineTargetWide(cu, info);
    RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true);
    OpRegCopyWide(cu, rl_result.low_reg, rl_result.high_reg, rl_src.low_reg, rl_src.high_reg);
    FreeTemp(cu, rl_src.low_reg);
    FreeTemp(cu, rl_src.high_reg);
    int sign_reg = AllocTemp(cu);
    // abs(x) = y<=x>>31, (x+y)^y.
    OpRegRegImm(cu, kOpAsr, sign_reg, rl_result.high_reg, 31);
    OpRegReg(cu, kOpAdd, rl_result.low_reg, sign_reg);
    OpRegReg(cu, kOpAdc, rl_result.high_reg, sign_reg);
    OpRegReg(cu, kOpXor, rl_result.low_reg, sign_reg);
    OpRegReg(cu, kOpXor, rl_result.high_reg, sign_reg);
    StoreValueWide(cu, rl_dest, rl_result);
    return true;
  }
}

bool Codegen::GenInlinedFloatCvt(CompilationUnit *cu, CallInfo* info)
{
  if (cu->instruction_set == kMips) {
    // TODO - add Mips implementation
    return false;
  }
  RegLocation rl_src = info->args[0];
  RegLocation rl_dest = InlineTarget(cu, info);
  StoreValue(cu, rl_dest, rl_src);
  return true;
}

bool Codegen::GenInlinedDoubleCvt(CompilationUnit *cu, CallInfo* info)
{
  if (cu->instruction_set == kMips) {
    // TODO - add Mips implementation
    return false;
  }
  RegLocation rl_src = info->args[0];
  RegLocation rl_dest = InlineTargetWide(cu, info);
  StoreValueWide(cu, rl_dest, rl_src);
  return true;
}

/*
 * Fast string.index_of(I) & (II).  Tests for simple case of char <= 0xffff,
 * otherwise bails to standard library code.
 */
bool Codegen::GenInlinedIndexOf(CompilationUnit* cu, CallInfo* info, bool zero_based)
{
  if (cu->instruction_set == kMips) {
    // TODO - add Mips implementation
    return false;
  }
  ClobberCalleeSave(cu);
  LockCallTemps(cu);  // Using fixed registers
  int reg_ptr = TargetReg(kArg0);
  int reg_char = TargetReg(kArg1);
  int reg_start = TargetReg(kArg2);

  RegLocation rl_obj = info->args[0];
  RegLocation rl_char = info->args[1];
  RegLocation rl_start = info->args[2];
  LoadValueDirectFixed(cu, rl_obj, reg_ptr);
  LoadValueDirectFixed(cu, rl_char, reg_char);
  if (zero_based) {
    LoadConstant(cu, reg_start, 0);
  } else {
    LoadValueDirectFixed(cu, rl_start, reg_start);
  }
  int r_tgt = (cu->instruction_set != kX86) ? LoadHelper(cu, ENTRYPOINT_OFFSET(pIndexOf)) : 0;
  GenNullCheck(cu, rl_obj.s_reg_low, reg_ptr, info->opt_flags);
  LIR* launch_pad = RawLIR(cu, 0, kPseudoIntrinsicRetry, reinterpret_cast<uintptr_t>(info));
  InsertGrowableList(cu, &cu->intrinsic_launchpads, reinterpret_cast<uintptr_t>(launch_pad));
  OpCmpImmBranch(cu, kCondGt, reg_char, 0xFFFF, launch_pad);
  // NOTE: not a safepoint
  if (cu->instruction_set != kX86) {
    OpReg(cu, kOpBlx, r_tgt);
  } else {
    OpThreadMem(cu, kOpBlx, ENTRYPOINT_OFFSET(pIndexOf));
  }
  LIR* resume_tgt = NewLIR0(cu, kPseudoTargetLabel);
  launch_pad->operands[2] = reinterpret_cast<uintptr_t>(resume_tgt);
  // Record that we've already inlined & null checked
  info->opt_flags |= (MIR_INLINED | MIR_IGNORE_NULL_CHECK);
  RegLocation rl_return = GetReturn(cu, false);
  RegLocation rl_dest = InlineTarget(cu, info);
  StoreValue(cu, rl_dest, rl_return);
  return true;
}

/* Fast string.compareTo(Ljava/lang/string;)I. */
bool Codegen::GenInlinedStringCompareTo(CompilationUnit* cu, CallInfo* info)
{
  if (cu->instruction_set == kMips) {
    // TODO - add Mips implementation
    return false;
  }
  ClobberCalleeSave(cu);
  LockCallTemps(cu);  // Using fixed registers
  int reg_this = TargetReg(kArg0);
  int reg_cmp = TargetReg(kArg1);

  RegLocation rl_this = info->args[0];
  RegLocation rl_cmp = info->args[1];
  LoadValueDirectFixed(cu, rl_this, reg_this);
  LoadValueDirectFixed(cu, rl_cmp, reg_cmp);
  int r_tgt = (cu->instruction_set != kX86) ?
      LoadHelper(cu, ENTRYPOINT_OFFSET(pStringCompareTo)) : 0;
  GenNullCheck(cu, rl_this.s_reg_low, reg_this, info->opt_flags);
  //TUNING: check if rl_cmp.s_reg_low is already null checked
  LIR* launch_pad = RawLIR(cu, 0, kPseudoIntrinsicRetry, reinterpret_cast<uintptr_t>(info));
  InsertGrowableList(cu, &cu->intrinsic_launchpads, reinterpret_cast<uintptr_t>(launch_pad));
  OpCmpImmBranch(cu, kCondEq, reg_cmp, 0, launch_pad);
  // NOTE: not a safepoint
  if (cu->instruction_set != kX86) {
    OpReg(cu, kOpBlx, r_tgt);
  } else {
    OpThreadMem(cu, kOpBlx, ENTRYPOINT_OFFSET(pStringCompareTo));
  }
  launch_pad->operands[2] = 0;  // No return possible
  // Record that we've already inlined & null checked
  info->opt_flags |= (MIR_INLINED | MIR_IGNORE_NULL_CHECK);
  RegLocation rl_return = GetReturn(cu, false);
  RegLocation rl_dest = InlineTarget(cu, info);
  StoreValue(cu, rl_dest, rl_return);
  return true;
}

bool Codegen::GenInlinedCurrentThread(CompilationUnit* cu, CallInfo* info) {
  RegLocation rl_dest = InlineTarget(cu, info);
  RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true);
  int offset = Thread::PeerOffset().Int32Value();
  if (cu->instruction_set == kThumb2 || cu->instruction_set == kMips) {
    LoadWordDisp(cu, TargetReg(kSelf), offset, rl_result.low_reg);
  } else {
    CHECK(cu->instruction_set == kX86);
    ((X86Codegen*)this)->OpRegThreadMem(cu, kOpMov, rl_result.low_reg, offset);
  }
  StoreValue(cu, rl_dest, rl_result);
  return true;
}

bool Codegen::GenInlinedUnsafeGet(CompilationUnit* cu, CallInfo* info,
                                  bool is_long, bool is_volatile) {
  if (cu->instruction_set == kMips) {
    // TODO - add Mips implementation
    return false;
  }
  // Unused - RegLocation rl_src_unsafe = info->args[0];
  RegLocation rl_src_obj = info->args[1];  // Object
  RegLocation rl_src_offset = info->args[2];  // long low
  rl_src_offset.wide = 0;  // ignore high half in info->args[3]
  RegLocation rl_dest = InlineTarget(cu, info);  // result reg
  if (is_volatile) {
    GenMemBarrier(cu, kLoadLoad);
  }
  RegLocation rl_object = LoadValue(cu, rl_src_obj, kCoreReg);
  RegLocation rl_offset = LoadValue(cu, rl_src_offset, kCoreReg);
  RegLocation rl_result = EvalLoc(cu, rl_dest, kCoreReg, true);
  if (is_long) {
    OpRegReg(cu, kOpAdd, rl_object.low_reg, rl_offset.low_reg);
    LoadBaseDispWide(cu, rl_object.low_reg, 0, rl_result.low_reg, rl_result.high_reg, INVALID_SREG);
    StoreValueWide(cu, rl_dest, rl_result);
  } else {
    LoadBaseIndexed(cu, rl_object.low_reg, rl_offset.low_reg, rl_result.low_reg, 0, kWord);
    StoreValue(cu, rl_dest, rl_result);
  }
  return true;
}

bool Codegen::GenInlinedUnsafePut(CompilationUnit* cu, CallInfo* info, bool is_long,
                                  bool is_object, bool is_volatile, bool is_ordered) {
  if (cu->instruction_set == kMips) {
    // TODO - add Mips implementation
    return false;
  }
  // Unused - RegLocation rl_src_unsafe = info->args[0];
  RegLocation rl_src_obj = info->args[1];  // Object
  RegLocation rl_src_offset = info->args[2];  // long low
  rl_src_offset.wide = 0;  // ignore high half in info->args[3]
  RegLocation rl_src_value = info->args[4];  // value to store
  if (is_volatile || is_ordered) {
    GenMemBarrier(cu, kStoreStore);
  }
  RegLocation rl_object = LoadValue(cu, rl_src_obj, kCoreReg);
  RegLocation rl_offset = LoadValue(cu, rl_src_offset, kCoreReg);
  RegLocation rl_value = LoadValue(cu, rl_src_value, kCoreReg);
  if (is_long) {
    OpRegReg(cu, kOpAdd, rl_object.low_reg, rl_offset.low_reg);
    StoreBaseDispWide(cu, rl_object.low_reg, 0, rl_value.low_reg, rl_value.high_reg);
  } else {
    StoreBaseIndexed(cu, rl_object.low_reg, rl_offset.low_reg, rl_value.low_reg, 0, kWord);
  }
  if (is_volatile) {
    GenMemBarrier(cu, kStoreLoad);
  }
  if (is_object) {
    MarkGCCard(cu, rl_value.low_reg, rl_object.low_reg);
  }
  return true;
}

bool Codegen::GenIntrinsic(CompilationUnit* cu, CallInfo* info)
{
  if (info->opt_flags & MIR_INLINED) {
    return false;
  }
  /*
   * TODO: move these to a target-specific structured constant array
   * and use a generic match function.  The list of intrinsics may be
   * slightly different depending on target.
   * TODO: Fold this into a matching function that runs during
   * basic block building.  This should be part of the action for
   * small method inlining and recognition of the special object init
   * method.  By doing this during basic block construction, we can also
   * take advantage of/generate new useful dataflow info.
   */
  std::string tgt_method(PrettyMethod(info->index, *cu->dex_file));
  if (tgt_method.find(" java.lang") != std::string::npos) {
    if (tgt_method == "long java.lang.Double.doubleToRawLongBits(double)") {
      return GenInlinedDoubleCvt(cu, info);
    }
    if (tgt_method == "double java.lang.Double.longBitsToDouble(long)") {
      return GenInlinedDoubleCvt(cu, info);
    }
    if (tgt_method == "int java.lang.Float.float_to_raw_int_bits(float)") {
      return GenInlinedFloatCvt(cu, info);
    }
    if (tgt_method == "float java.lang.Float.intBitsToFloat(int)") {
      return GenInlinedFloatCvt(cu, info);
    }
    if (tgt_method == "int java.lang.Math.abs(int)" ||
        tgt_method == "int java.lang.StrictMath.abs(int)") {
      return GenInlinedAbsInt(cu, info);
    }
    if (tgt_method == "long java.lang.Math.abs(long)" ||
        tgt_method == "long java.lang.StrictMath.abs(long)") {
      return GenInlinedAbsLong(cu, info);
    }
    if (tgt_method == "int java.lang.Math.max(int, int)" ||
        tgt_method == "int java.lang.StrictMath.max(int, int)") {
      return GenInlinedMinMaxInt(cu, info, false /* is_min */);
    }
    if (tgt_method == "int java.lang.Math.min(int, int)" ||
        tgt_method == "int java.lang.StrictMath.min(int, int)") {
      return GenInlinedMinMaxInt(cu, info, true /* is_min */);
    }
    if (tgt_method == "double java.lang.Math.sqrt(double)" ||
        tgt_method == "double java.lang.StrictMath.sqrt(double)") {
      return GenInlinedSqrt(cu, info);
    }
    if (tgt_method == "char java.lang.String.charAt(int)") {
      return GenInlinedCharAt(cu, info);
    }
    if (tgt_method == "int java.lang.String.compareTo(java.lang.String)") {
      return GenInlinedStringCompareTo(cu, info);
    }
    if (tgt_method == "boolean java.lang.String.is_empty()") {
      return GenInlinedStringIsEmptyOrLength(cu, info, true /* is_empty */);
    }
    if (tgt_method == "int java.lang.String.index_of(int, int)") {
      return GenInlinedIndexOf(cu, info, false /* base 0 */);
    }
    if (tgt_method == "int java.lang.String.index_of(int)") {
      return GenInlinedIndexOf(cu, info, true /* base 0 */);
    }
    if (tgt_method == "int java.lang.String.length()") {
      return GenInlinedStringIsEmptyOrLength(cu, info, false /* is_empty */);
    }
    if (tgt_method == "java.lang.Thread java.lang.Thread.currentThread()") {
      return GenInlinedCurrentThread(cu, info);
    }
  } else if (tgt_method.find(" sun.misc.Unsafe") != std::string::npos) {
    if (tgt_method == "boolean sun.misc.Unsafe.compareAndSwapInt(java.lang.Object, long, int, int)") {
      return GenInlinedCas32(cu, info, false);
    }
    if (tgt_method == "boolean sun.misc.Unsafe.compareAndSwapObject(java.lang.Object, long, java.lang.Object, java.lang.Object)") {
      return GenInlinedCas32(cu, info, true);
    }
    if (tgt_method == "int sun.misc.Unsafe.getInt(java.lang.Object, long)") {
      return GenInlinedUnsafeGet(cu, info, false /* is_long */, false /* is_volatile */);
    }
    if (tgt_method == "int sun.misc.Unsafe.getIntVolatile(java.lang.Object, long)") {
      return GenInlinedUnsafeGet(cu, info, false /* is_long */, true /* is_volatile */);
    }
    if (tgt_method == "void sun.misc.Unsafe.putInt(java.lang.Object, long, int)") {
      return GenInlinedUnsafePut(cu, info, false /* is_long */, false /* is_object */,
                                 false /* is_volatile */, false /* is_ordered */);
    }
    if (tgt_method == "void sun.misc.Unsafe.putIntVolatile(java.lang.Object, long, int)") {
      return GenInlinedUnsafePut(cu, info, false /* is_long */, false /* is_object */,
                                 true /* is_volatile */, false /* is_ordered */);
    }
    if (tgt_method == "void sun.misc.Unsafe.putOrderedInt(java.lang.Object, long, int)") {
      return GenInlinedUnsafePut(cu, info, false /* is_long */, false /* is_object */,
                                 false /* is_volatile */, true /* is_ordered */);
    }
    if (tgt_method == "long sun.misc.Unsafe.getLong(java.lang.Object, long)") {
      return GenInlinedUnsafeGet(cu, info, true /* is_long */, false /* is_volatile */);
    }
    if (tgt_method == "long sun.misc.Unsafe.getLongVolatile(java.lang.Object, long)") {
      return GenInlinedUnsafeGet(cu, info, true /* is_long */, true /* is_volatile */);
    }
    if (tgt_method == "void sun.misc.Unsafe.putLong(java.lang.Object, long, long)") {
      return GenInlinedUnsafePut(cu, info, true /* is_long */, false /* is_object */,
                                 false /* is_volatile */, false /* is_ordered */);
    }
    if (tgt_method == "void sun.misc.Unsafe.putLongVolatile(java.lang.Object, long, long)") {
      return GenInlinedUnsafePut(cu, info, true /* is_long */, false /* is_object */,
                                 true /* is_volatile */, false /* is_ordered */);
    }
    if (tgt_method == "void sun.misc.Unsafe.putOrderedLong(java.lang.Object, long, long)") {
      return GenInlinedUnsafePut(cu, info, true /* is_long */, false /* is_object */,
                                 false /* is_volatile */, true /* is_ordered */);
    }
    if (tgt_method == "java.lang.Object sun.misc.Unsafe.getObject(java.lang.Object, long)") {
      return GenInlinedUnsafeGet(cu, info, false /* is_long */, false /* is_volatile */);
    }
    if (tgt_method == "java.lang.Object sun.misc.Unsafe.getObjectVolatile(java.lang.Object, long)") {
      return GenInlinedUnsafeGet(cu, info, false /* is_long */, true /* is_volatile */);
    }
    if (tgt_method == "void sun.misc.Unsafe.putObject(java.lang.Object, long, java.lang.Object)") {
      return GenInlinedUnsafePut(cu, info, false /* is_long */, true /* is_object */,
                                 false /* is_volatile */, false /* is_ordered */);
    }
    if (tgt_method == "void sun.misc.Unsafe.putObjectVolatile(java.lang.Object, long, java.lang.Object)") {
      return GenInlinedUnsafePut(cu, info, false /* is_long */, true /* is_object */,
                                 true /* is_volatile */, false /* is_ordered */);
    }
    if (tgt_method == "void sun.misc.Unsafe.putOrderedObject(java.lang.Object, long, java.lang.Object)") {
      return GenInlinedUnsafePut(cu, info, false /* is_long */, true /* is_object */,
                                 false /* is_volatile */, true /* is_ordered */);
    }
  }
  return false;
}

void Codegen::GenInvoke(CompilationUnit* cu, CallInfo* info)
{
  if (GenIntrinsic(cu, info)) {
    return;
  }
  InvokeType original_type = info->type;  // avoiding mutation by ComputeInvokeInfo
  int call_state = 0;
  LIR* null_ck;
  LIR** p_null_ck = NULL;
  NextCallInsn next_call_insn;
  FlushAllRegs(cu);  /* Everything to home location */
  // Explicit register usage
  LockCallTemps(cu);

  DexCompilationUnit m_unit(cu);

  uint32_t dex_method_idx = info->index;
  int vtable_idx;
  uintptr_t direct_code;
  uintptr_t direct_method;
  bool skip_this;
  bool fast_path =
    cu->compiler_driver->ComputeInvokeInfo(dex_method_idx, &m_unit, info->type,
                                           vtable_idx, direct_code,
                                           direct_method)
    && !SLOW_INVOKE_PATH;
  if (info->type == kInterface) {
    if (fast_path) {
      p_null_ck = &null_ck;
    }
    next_call_insn = fast_path ? NextInterfaceCallInsn
                            : NextInterfaceCallInsnWithAccessCheck;
    skip_this = false;
  } else if (info->type == kDirect) {
    if (fast_path) {
      p_null_ck = &null_ck;
    }
    next_call_insn = fast_path ? NextSDCallInsn : NextDirectCallInsnSP;
    skip_this = false;
  } else if (info->type == kStatic) {
    next_call_insn = fast_path ? NextSDCallInsn : NextStaticCallInsnSP;
    skip_this = false;
  } else if (info->type == kSuper) {
    DCHECK(!fast_path);  // Fast path is a direct call.
    next_call_insn = NextSuperCallInsnSP;
    skip_this = false;
  } else {
    DCHECK_EQ(info->type, kVirtual);
    next_call_insn = fast_path ? NextVCallInsn : NextVCallInsnSP;
    skip_this = fast_path;
  }
  if (!info->is_range) {
    call_state = GenDalvikArgsNoRange(cu, info, call_state, p_null_ck,
                                     next_call_insn, dex_method_idx,
                                     vtable_idx, direct_code, direct_method,
                                     original_type, skip_this);
  } else {
    call_state = GenDalvikArgsRange(cu, info, call_state, p_null_ck,
                                   next_call_insn, dex_method_idx, vtable_idx,
                                   direct_code, direct_method, original_type,
                                   skip_this);
  }
  // Finish up any of the call sequence not interleaved in arg loading
  while (call_state >= 0) {
    call_state = next_call_insn(cu, info, call_state, dex_method_idx,
                             vtable_idx, direct_code, direct_method,
                             original_type);
  }
  if (cu->enable_debug & (1 << kDebugDisplayMissingTargets)) {
    GenShowTarget(cu);
  }
  LIR* call_inst;
  if (cu->instruction_set != kX86) {
    call_inst = OpReg(cu, kOpBlx, TargetReg(kInvokeTgt));
  } else {
    if (fast_path && info->type != kInterface) {
      call_inst = OpMem(cu, kOpBlx, TargetReg(kArg0),
                        mirror::AbstractMethod::GetCodeOffset().Int32Value());
    } else {
      int trampoline = 0;
      switch (info->type) {
      case kInterface:
        trampoline = fast_path ? ENTRYPOINT_OFFSET(pInvokeInterfaceTrampoline)
            : ENTRYPOINT_OFFSET(pInvokeInterfaceTrampolineWithAccessCheck);
        break;
      case kDirect:
        trampoline = ENTRYPOINT_OFFSET(pInvokeDirectTrampolineWithAccessCheck);
        break;
      case kStatic:
        trampoline = ENTRYPOINT_OFFSET(pInvokeStaticTrampolineWithAccessCheck);
        break;
      case kSuper:
        trampoline = ENTRYPOINT_OFFSET(pInvokeSuperTrampolineWithAccessCheck);
        break;
      case kVirtual:
        trampoline = ENTRYPOINT_OFFSET(pInvokeVirtualTrampolineWithAccessCheck);
        break;
      default:
        LOG(FATAL) << "Unexpected invoke type";
      }
      call_inst = OpThreadMem(cu, kOpBlx, trampoline);
    }
  }
  MarkSafepointPC(cu, call_inst);

  ClobberCalleeSave(cu);
  if (info->result.location != kLocInvalid) {
    // We have a following MOVE_RESULT - do it now.
    if (info->result.wide) {
      RegLocation ret_loc = GetReturnWide(cu, info->result.fp);
      StoreValueWide(cu, info->result, ret_loc);
    } else {
      RegLocation ret_loc = GetReturn(cu, info->result.fp);
      StoreValue(cu, info->result, ret_loc);
    }
  }
}

/*
 * Build an array of location records for the incoming arguments.
 * Note: one location record per word of arguments, with dummy
 * high-word loc for wide arguments.  Also pull up any following
 * MOVE_RESULT and incorporate it into the invoke.
 */
CallInfo* Codegen::NewMemCallInfo(CompilationUnit* cu, BasicBlock* bb, MIR* mir, InvokeType type,
                                  bool is_range)
{
  CallInfo* info = static_cast<CallInfo*>(NewMem(cu, sizeof(CallInfo), true, kAllocMisc));
  MIR* move_result_mir = FindMoveResult(cu, bb, mir);
  if (move_result_mir == NULL) {
    info->result.location = kLocInvalid;
  } else {
    info->result = GetRawDest(cu, move_result_mir);
    move_result_mir->meta.original_opcode = move_result_mir->dalvikInsn.opcode;
    move_result_mir->dalvikInsn.opcode = static_cast<Instruction::Code>(kMirOpNop);
  }
  info->num_arg_words = mir->ssa_rep->num_uses;
  info->args = (info->num_arg_words == 0) ? NULL : static_cast<RegLocation*>
      (NewMem(cu, sizeof(RegLocation) * info->num_arg_words, false, kAllocMisc));
  for (int i = 0; i < info->num_arg_words; i++) {
    info->args[i] = GetRawSrc(cu, mir, i);
  }
  info->opt_flags = mir->optimization_flags;
  info->type = type;
  info->is_range = is_range;
  info->index = mir->dalvikInsn.vB;
  info->offset = mir->offset;
  return info;
}

}  // namespace art
