/*
 * 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"
#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),
        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),
                       Array::DataOffset(sizeof(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), 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), Object::ClassOffset().Int32Value(),
                       cg->TargetReg(kInvokeTgt));
      break;
    case 2: // Get this->klass_->vtable [usr kInvokeTgt, set kInvokeTgt]
      cg->LoadWordDisp(cu, cg->TargetReg(kInvokeTgt), 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) +
                       Array::DataOffset(sizeof(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), 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_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),
                       AbstractMethod::DexCacheResolvedMethodsOffset().Int32Value(),
                       cg->TargetReg(kArg0));
      break;
    case 2:  // Grab target method* [set/use kArg0]
      cg->LoadWordDisp(cu, cg->TargetReg(kArg0),
                       Array::DataOffset(sizeof(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 = String::ValueOffset().Int32Value();
  // Location of count
  int count_offset = String::CountOffset().Int32Value();
  // Starting offset within data array
  int offset_offset = String::OffsetOffset().Int32Value();
  // Start of char data with array_
  int data_offset = 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, 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::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("boolean sun.misc.Unsafe.compareAndSwap") != 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);
    }
  }
  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);

  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);

  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->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),
                       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
