/*
 * Copyright (C) 2011 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.
 */

/* This file contains codegen for the Thumb2 ISA. */

#include "arm_lir.h"
#include "codegen_arm.h"
#include "oat/runtime/oat_support_entrypoints.h"

namespace art {


/* Return the position of an ssa name within the argument list */
int ArmMir2Lir::InPosition(int s_reg)
{
  int v_reg = mir_graph_->SRegToVReg(s_reg);
  return v_reg - cu_->num_regs;
}

/*
 * Describe an argument.  If it's already in an arg register, just leave it
 * there.  NOTE: all live arg registers must be locked prior to this call
 * to avoid having them allocated as a temp by downstream utilities.
 */
RegLocation ArmMir2Lir::ArgLoc(RegLocation loc)
{
  int arg_num = InPosition(loc.s_reg_low);
  if (loc.wide) {
    if (arg_num == 2) {
      // Bad case - half in register, half in frame.  Just punt
      loc.location = kLocInvalid;
    } else if (arg_num < 2) {
      loc.low_reg = rARM_ARG1 + arg_num;
      loc.high_reg = loc.low_reg + 1;
      loc.location = kLocPhysReg;
    } else {
      loc.location = kLocDalvikFrame;
    }
  } else {
    if (arg_num < 3) {
      loc.low_reg = rARM_ARG1 + arg_num;
      loc.location = kLocPhysReg;
    } else {
      loc.location = kLocDalvikFrame;
    }
  }
  return loc;
}

/*
 * Load an argument.  If already in a register, just return.  If in
 * the frame, we can't use the normal LoadValue() because it assumed
 * a proper frame - and we're frameless.
 */
RegLocation ArmMir2Lir::LoadArg(RegLocation loc)
{
  if (loc.location == kLocDalvikFrame) {
    int start = (InPosition(loc.s_reg_low) + 1) * sizeof(uint32_t);
    loc.low_reg = AllocTemp();
    LoadWordDisp(rARM_SP, start, loc.low_reg);
    if (loc.wide) {
      loc.high_reg = AllocTemp();
      LoadWordDisp(rARM_SP, start + sizeof(uint32_t), loc.high_reg);
    }
    loc.location = kLocPhysReg;
  }
  return loc;
}

/* Lock any referenced arguments that arrive in registers */
void ArmMir2Lir::LockLiveArgs(MIR* mir)
{
  int first_in = cu_->num_regs;
  const int num_arg_regs = 3;  // TODO: generalize & move to RegUtil.cc
  for (int i = 0; i < mir->ssa_rep->num_uses; i++) {
    int v_reg = mir_graph_->SRegToVReg(mir->ssa_rep->uses[i]);
    int InPosition = v_reg - first_in;
    if (InPosition < num_arg_regs) {
      LockTemp(rARM_ARG1 + InPosition);
    }
  }
}

/* Find the next MIR, which may be in a following basic block */
// TODO: should this be a utility in mir_graph?
MIR* ArmMir2Lir::GetNextMir(BasicBlock** p_bb, MIR* mir)
{
  BasicBlock* bb = *p_bb;
  MIR* orig_mir = mir;
  while (bb != NULL) {
    if (mir != NULL) {
      mir = mir->next;
    }
    if (mir != NULL) {
      return mir;
    } else {
      bb = bb->fall_through;
      *p_bb = bb;
      if (bb) {
         mir = bb->first_mir_insn;
         if (mir != NULL) {
           return mir;
         }
      }
    }
  }
  return orig_mir;
}

/* Used for the "verbose" listing */
//TODO:  move to common code
void ArmMir2Lir::GenPrintLabel(MIR* mir)
{
  /* Mark the beginning of a Dalvik instruction for line tracking */
  char* inst_str = cu_->verbose ?
     mir_graph_->GetDalvikDisassembly(mir) : NULL;
  MarkBoundary(mir->offset, inst_str);
}

MIR* ArmMir2Lir::SpecialIGet(BasicBlock** bb, MIR* mir,
                             OpSize size, bool long_or_double, bool is_object)
{
  int field_offset;
  bool is_volatile;
  uint32_t field_idx = mir->dalvikInsn.vC;
  bool fast_path = FastInstance(field_idx, field_offset, is_volatile, false);
  if (!fast_path || !(mir->optimization_flags & MIR_IGNORE_NULL_CHECK)) {
    return NULL;
  }
  RegLocation rl_obj = mir_graph_->GetSrc(mir, 0);
  LockLiveArgs(mir);
  rl_obj = ArmMir2Lir::ArgLoc(rl_obj);
  RegLocation rl_dest;
  if (long_or_double) {
    rl_dest = GetReturnWide(false);
  } else {
    rl_dest = GetReturn(false);
  }
  // Point of no return - no aborts after this
  ArmMir2Lir::GenPrintLabel(mir);
  rl_obj = LoadArg(rl_obj);
  GenIGet(field_idx, mir->optimization_flags, size, rl_dest, rl_obj, long_or_double, is_object);
  return GetNextMir(bb, mir);
}

MIR* ArmMir2Lir::SpecialIPut(BasicBlock** bb, MIR* mir,
                             OpSize size, bool long_or_double, bool is_object)
{
  int field_offset;
  bool is_volatile;
  uint32_t field_idx = mir->dalvikInsn.vC;
  bool fast_path = FastInstance(field_idx, field_offset, is_volatile, false);
  if (!fast_path || !(mir->optimization_flags & MIR_IGNORE_NULL_CHECK)) {
    return NULL;
  }
  RegLocation rl_src;
  RegLocation rl_obj;
  LockLiveArgs(mir);
  if (long_or_double) {
    rl_src = mir_graph_->GetSrcWide(mir, 0);
    rl_obj = mir_graph_->GetSrc(mir, 2);
  } else {
    rl_src = mir_graph_->GetSrc(mir, 0);
    rl_obj = mir_graph_->GetSrc(mir, 1);
  }
  rl_src = ArmMir2Lir::ArgLoc(rl_src);
  rl_obj = ArmMir2Lir::ArgLoc(rl_obj);
  // Reject if source is split across registers & frame
  if (rl_obj.location == kLocInvalid) {
    ResetRegPool();
    return NULL;
  }
  // Point of no return - no aborts after this
  ArmMir2Lir::GenPrintLabel(mir);
  rl_obj = LoadArg(rl_obj);
  rl_src = LoadArg(rl_src);
  GenIPut(field_idx, mir->optimization_flags, size, rl_src, rl_obj, long_or_double, is_object);
  return GetNextMir(bb, mir);
}

MIR* ArmMir2Lir::SpecialIdentity(MIR* mir)
{
  RegLocation rl_src;
  RegLocation rl_dest;
  bool wide = (mir->ssa_rep->num_uses == 2);
  if (wide) {
    rl_src = mir_graph_->GetSrcWide(mir, 0);
    rl_dest = GetReturnWide(false);
  } else {
    rl_src = mir_graph_->GetSrc(mir, 0);
    rl_dest = GetReturn(false);
  }
  LockLiveArgs(mir);
  rl_src = ArmMir2Lir::ArgLoc(rl_src);
  if (rl_src.location == kLocInvalid) {
    ResetRegPool();
    return NULL;
  }
  // Point of no return - no aborts after this
  ArmMir2Lir::GenPrintLabel(mir);
  rl_src = LoadArg(rl_src);
  if (wide) {
    StoreValueWide(rl_dest, rl_src);
  } else {
    StoreValue(rl_dest, rl_src);
  }
  return mir;
}

/*
 * Special-case code genration for simple non-throwing leaf methods.
 */
void ArmMir2Lir::GenSpecialCase(BasicBlock* bb, MIR* mir,
                                SpecialCaseHandler special_case)
{
   current_dalvik_offset_ = mir->offset;
   MIR* next_mir = NULL;
   switch (special_case) {
     case kNullMethod:
       DCHECK(mir->dalvikInsn.opcode == Instruction::RETURN_VOID);
       next_mir = mir;
       break;
     case kConstFunction:
       ArmMir2Lir::GenPrintLabel(mir);
       LoadConstant(rARM_RET0, mir->dalvikInsn.vB);
       next_mir = GetNextMir(&bb, mir);
       break;
     case kIGet:
       next_mir = SpecialIGet(&bb, mir, kWord, false, false);
       break;
     case kIGetBoolean:
     case kIGetByte:
       next_mir = SpecialIGet(&bb, mir, kUnsignedByte, false, false);
       break;
     case kIGetObject:
       next_mir = SpecialIGet(&bb, mir, kWord, false, true);
       break;
     case kIGetChar:
       next_mir = SpecialIGet(&bb, mir, kUnsignedHalf, false, false);
       break;
     case kIGetShort:
       next_mir = SpecialIGet(&bb, mir, kSignedHalf, false, false);
       break;
     case kIGetWide:
       next_mir = SpecialIGet(&bb, mir, kLong, true, false);
       break;
     case kIPut:
       next_mir = SpecialIPut(&bb, mir, kWord, false, false);
       break;
     case kIPutBoolean:
     case kIPutByte:
       next_mir = SpecialIPut(&bb, mir, kUnsignedByte, false, false);
       break;
     case kIPutObject:
       next_mir = SpecialIPut(&bb, mir, kWord, false, true);
       break;
     case kIPutChar:
       next_mir = SpecialIPut(&bb, mir, kUnsignedHalf, false, false);
       break;
     case kIPutShort:
       next_mir = SpecialIPut(&bb, mir, kSignedHalf, false, false);
       break;
     case kIPutWide:
       next_mir = SpecialIPut(&bb, mir, kLong, true, false);
       break;
     case kIdentity:
       next_mir = SpecialIdentity(mir);
       break;
     default:
       return;
   }
   if (next_mir != NULL) {
    current_dalvik_offset_ = next_mir->offset;
    if (special_case != kIdentity) {
      ArmMir2Lir::GenPrintLabel(next_mir);
    }
    NewLIR1(kThumbBx, rARM_LR);
    core_spill_mask_ = 0;
    num_core_spills_ = 0;
    fp_spill_mask_ = 0;
    num_fp_spills_ = 0;
    frame_size_ = 0;
    core_vmap_table_.clear();
    fp_vmap_table_.clear();
  }
}

/*
 * The sparse table in the literal pool is an array of <key,displacement>
 * pairs.  For each set, we'll load them as a pair using ldmia.
 * This means that the register number of the temp we use for the key
 * must be lower than the reg for the displacement.
 *
 * The test loop will look something like:
 *
 *   adr   rBase, <table>
 *   ldr   r_val, [rARM_SP, v_reg_off]
 *   mov   r_idx, #table_size
 * lp:
 *   ldmia rBase!, {r_key, r_disp}
 *   sub   r_idx, #1
 *   cmp   r_val, r_key
 *   ifeq
 *   add   rARM_PC, r_disp   ; This is the branch from which we compute displacement
 *   cbnz  r_idx, lp
 */
void ArmMir2Lir::GenSparseSwitch(MIR* mir, uint32_t table_offset,
                                 RegLocation rl_src)
{
  const uint16_t* table = cu_->insns + current_dalvik_offset_ + table_offset;
  if (cu_->verbose) {
    DumpSparseSwitchTable(table);
  }
  // Add the table to the list - we'll process it later
  SwitchTable *tab_rec =
      static_cast<SwitchTable*>(NewMem(cu_, sizeof(SwitchTable), true, kAllocData));
  tab_rec->table = table;
  tab_rec->vaddr = current_dalvik_offset_;
  int size = table[1];
  tab_rec->targets = static_cast<LIR**>(NewMem(cu_, size * sizeof(LIR*), true, kAllocLIR));
  InsertGrowableList(cu_, &switch_tables_, reinterpret_cast<uintptr_t>(tab_rec));

  // Get the switch value
  rl_src = LoadValue(rl_src, kCoreReg);
  int rBase = AllocTemp();
  /* Allocate key and disp temps */
  int r_key = AllocTemp();
  int r_disp = AllocTemp();
  // Make sure r_key's register number is less than r_disp's number for ldmia
  if (r_key > r_disp) {
    int tmp = r_disp;
    r_disp = r_key;
    r_key = tmp;
  }
  // Materialize a pointer to the switch table
  NewLIR3(kThumb2Adr, rBase, 0, reinterpret_cast<uintptr_t>(tab_rec));
  // Set up r_idx
  int r_idx = AllocTemp();
  LoadConstant(r_idx, size);
  // Establish loop branch target
  LIR* target = NewLIR0(kPseudoTargetLabel);
  // Load next key/disp
  NewLIR2(kThumb2LdmiaWB, rBase, (1 << r_key) | (1 << r_disp));
  OpRegReg(kOpCmp, r_key, rl_src.low_reg);
  // Go if match. NOTE: No instruction set switch here - must stay Thumb2
  OpIT(kCondEq, "");
  LIR* switch_branch = NewLIR1(kThumb2AddPCR, r_disp);
  tab_rec->anchor = switch_branch;
  // Needs to use setflags encoding here
  NewLIR3(kThumb2SubsRRI12, r_idx, r_idx, 1);
  OpCondBranch(kCondNe, target);
}


void ArmMir2Lir::GenPackedSwitch(MIR* mir, uint32_t table_offset,
                                 RegLocation rl_src)
{
  const uint16_t* table = cu_->insns + current_dalvik_offset_ + table_offset;
  if (cu_->verbose) {
    DumpPackedSwitchTable(table);
  }
  // Add the table to the list - we'll process it later
  SwitchTable *tab_rec =
      static_cast<SwitchTable*>(NewMem(cu_, sizeof(SwitchTable), true, kAllocData));
  tab_rec->table = table;
  tab_rec->vaddr = current_dalvik_offset_;
  int size = table[1];
  tab_rec->targets = static_cast<LIR**>(NewMem(cu_, size * sizeof(LIR*), true, kAllocLIR));
  InsertGrowableList(cu_, &switch_tables_, reinterpret_cast<uintptr_t>(tab_rec));

  // Get the switch value
  rl_src = LoadValue(rl_src, kCoreReg);
  int table_base = AllocTemp();
  // Materialize a pointer to the switch table
  NewLIR3(kThumb2Adr, table_base, 0, reinterpret_cast<uintptr_t>(tab_rec));
  int low_key = s4FromSwitchData(&table[2]);
  int keyReg;
  // Remove the bias, if necessary
  if (low_key == 0) {
    keyReg = rl_src.low_reg;
  } else {
    keyReg = AllocTemp();
    OpRegRegImm(kOpSub, keyReg, rl_src.low_reg, low_key);
  }
  // Bounds check - if < 0 or >= size continue following switch
  OpRegImm(kOpCmp, keyReg, size-1);
  LIR* branch_over = OpCondBranch(kCondHi, NULL);

  // Load the displacement from the switch table
  int disp_reg = AllocTemp();
  LoadBaseIndexed(table_base, keyReg, disp_reg, 2, kWord);

  // ..and go! NOTE: No instruction set switch here - must stay Thumb2
  LIR* switch_branch = NewLIR1(kThumb2AddPCR, disp_reg);
  tab_rec->anchor = switch_branch;

  /* branch_over target here */
  LIR* target = NewLIR0(kPseudoTargetLabel);
  branch_over->target = target;
}

/*
 * Array data table format:
 *  ushort ident = 0x0300   magic value
 *  ushort width            width of each element in the table
 *  uint   size             number of elements in the table
 *  ubyte  data[size*width] table of data values (may contain a single-byte
 *                          padding at the end)
 *
 * Total size is 4+(width * size + 1)/2 16-bit code units.
 */
void ArmMir2Lir::GenFillArrayData(uint32_t table_offset, RegLocation rl_src)
{
  const uint16_t* table = cu_->insns + current_dalvik_offset_ + table_offset;
  // Add the table to the list - we'll process it later
  FillArrayData *tab_rec =
      static_cast<FillArrayData*>(NewMem(cu_, sizeof(FillArrayData), true, kAllocData));
  tab_rec->table = table;
  tab_rec->vaddr = current_dalvik_offset_;
  uint16_t width = tab_rec->table[1];
  uint32_t size = tab_rec->table[2] | ((static_cast<uint32_t>(tab_rec->table[3])) << 16);
  tab_rec->size = (size * width) + 8;

  InsertGrowableList(cu_, &fill_array_data_, reinterpret_cast<uintptr_t>(tab_rec));

  // Making a call - use explicit registers
  FlushAllRegs();   /* Everything to home location */
  LoadValueDirectFixed(rl_src, r0);
  LoadWordDisp(rARM_SELF, ENTRYPOINT_OFFSET(pHandleFillArrayDataFromCode),
               rARM_LR);
  // Materialize a pointer to the fill data image
  NewLIR3(kThumb2Adr, r1, 0, reinterpret_cast<uintptr_t>(tab_rec));
  ClobberCalleeSave();
  LIR* call_inst = OpReg(kOpBlx, rARM_LR);
  MarkSafepointPC(call_inst);
}

/*
 * Handle simple case (thin lock) inline.  If it's complicated, bail
 * out to the heavyweight lock/unlock routines.  We'll use dedicated
 * registers here in order to be in the right position in case we
 * to bail to oat[Lock/Unlock]Object(self, object)
 *
 * r0 -> self pointer [arg0 for oat[Lock/Unlock]Object
 * r1 -> object [arg1 for oat[Lock/Unlock]Object
 * r2 -> intial contents of object->lock, later result of strex
 * r3 -> self->thread_id
 * r12 -> allow to be used by utilities as general temp
 *
 * The result of the strex is 0 if we acquire the lock.
 *
 * See comments in monitor.cc for the layout of the lock word.
 * Of particular interest to this code is the test for the
 * simple case - which we handle inline.  For monitor enter, the
 * simple case is thin lock, held by no-one.  For monitor exit,
 * the simple case is thin lock, held by the unlocking thread with
 * a recurse count of 0.
 *
 * A minor complication is that there is a field in the lock word
 * unrelated to locking: the hash state.  This field must be ignored, but
 * preserved.
 *
 */
void ArmMir2Lir::GenMonitorEnter(int opt_flags, RegLocation rl_src)
{
  FlushAllRegs();
  DCHECK_EQ(LW_SHAPE_THIN, 0);
  LoadValueDirectFixed(rl_src, r0);  // Get obj
  LockCallTemps();  // Prepare for explicit register usage
  GenNullCheck(rl_src.s_reg_low, r0, opt_flags);
  LoadWordDisp(rARM_SELF, Thread::ThinLockIdOffset().Int32Value(), r2);
  NewLIR3(kThumb2Ldrex, r1, r0,
          mirror::Object::MonitorOffset().Int32Value() >> 2); // Get object->lock
  // Align owner
  OpRegImm(kOpLsl, r2, LW_LOCK_OWNER_SHIFT);
  // Is lock unheld on lock or held by us (==thread_id) on unlock?
  NewLIR4(kThumb2Bfi, r2, r1, 0, LW_LOCK_OWNER_SHIFT - 1);
  NewLIR3(kThumb2Bfc, r1, LW_HASH_STATE_SHIFT, LW_LOCK_OWNER_SHIFT - 1);
  OpRegImm(kOpCmp, r1, 0);
  OpIT(kCondEq, "");
  NewLIR4(kThumb2Strex, r1, r2, r0,
          mirror::Object::MonitorOffset().Int32Value() >> 2);
  OpRegImm(kOpCmp, r1, 0);
  OpIT(kCondNe, "T");
  // Go expensive route - artLockObjectFromCode(self, obj);
  LoadWordDisp(rARM_SELF, ENTRYPOINT_OFFSET(pLockObjectFromCode), rARM_LR);
  ClobberCalleeSave();
  LIR* call_inst = OpReg(kOpBlx, rARM_LR);
  MarkSafepointPC(call_inst);
  GenMemBarrier(kLoadLoad);
}

/*
 * For monitor unlock, we don't have to use ldrex/strex.  Once
 * we've determined that the lock is thin and that we own it with
 * a zero recursion count, it's safe to punch it back to the
 * initial, unlock thin state with a store word.
 */
void ArmMir2Lir::GenMonitorExit(int opt_flags, RegLocation rl_src)
{
  DCHECK_EQ(LW_SHAPE_THIN, 0);
  FlushAllRegs();
  LoadValueDirectFixed(rl_src, r0);  // Get obj
  LockCallTemps();  // Prepare for explicit register usage
  GenNullCheck(rl_src.s_reg_low, r0, opt_flags);
  LoadWordDisp(r0, mirror::Object::MonitorOffset().Int32Value(), r1); // Get lock
  LoadWordDisp(rARM_SELF, Thread::ThinLockIdOffset().Int32Value(), r2);
  // Is lock unheld on lock or held by us (==thread_id) on unlock?
  OpRegRegImm(kOpAnd, r3, r1,
              (LW_HASH_STATE_MASK << LW_HASH_STATE_SHIFT));
  // Align owner
  OpRegImm(kOpLsl, r2, LW_LOCK_OWNER_SHIFT);
  NewLIR3(kThumb2Bfc, r1, LW_HASH_STATE_SHIFT, LW_LOCK_OWNER_SHIFT - 1);
  OpRegReg(kOpSub, r1, r2);
  OpIT(kCondEq, "EE");
  StoreWordDisp(r0, mirror::Object::MonitorOffset().Int32Value(), r3);
  // Go expensive route - UnlockObjectFromCode(obj);
  LoadWordDisp(rARM_SELF, ENTRYPOINT_OFFSET(pUnlockObjectFromCode), rARM_LR);
  ClobberCalleeSave();
  LIR* call_inst = OpReg(kOpBlx, rARM_LR);
  MarkSafepointPC(call_inst);
  GenMemBarrier(kStoreLoad);
}

void ArmMir2Lir::GenMoveException(RegLocation rl_dest)
{
  int ex_offset = Thread::ExceptionOffset().Int32Value();
  RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
  int reset_reg = AllocTemp();
  LoadWordDisp(rARM_SELF, ex_offset, rl_result.low_reg);
  LoadConstant(reset_reg, 0);
  StoreWordDisp(rARM_SELF, ex_offset, reset_reg);
  FreeTemp(reset_reg);
  StoreValue(rl_dest, rl_result);
}

/*
 * Mark garbage collection card. Skip if the value we're storing is null.
 */
void ArmMir2Lir::MarkGCCard(int val_reg, int tgt_addr_reg)
{
  int reg_card_base = AllocTemp();
  int reg_card_no = AllocTemp();
  LIR* branch_over = OpCmpImmBranch(kCondEq, val_reg, 0, NULL);
  LoadWordDisp(rARM_SELF, Thread::CardTableOffset().Int32Value(), reg_card_base);
  OpRegRegImm(kOpLsr, reg_card_no, tgt_addr_reg, CardTable::kCardShift);
  StoreBaseIndexed(reg_card_base, reg_card_no, reg_card_base, 0,
                   kUnsignedByte);
  LIR* target = NewLIR0(kPseudoTargetLabel);
  branch_over->target = target;
  FreeTemp(reg_card_base);
  FreeTemp(reg_card_no);
}

void ArmMir2Lir::GenEntrySequence(RegLocation* ArgLocs, RegLocation rl_method)
{
  int spill_count = num_core_spills_ + num_fp_spills_;
  /*
   * On entry, r0, r1, r2 & r3 are live.  Let the register allocation
   * mechanism know so it doesn't try to use any of them when
   * expanding the frame or flushing.  This leaves the utility
   * code with a single temp: r12.  This should be enough.
   */
  LockTemp(r0);
  LockTemp(r1);
  LockTemp(r2);
  LockTemp(r3);

  /*
   * We can safely skip the stack overflow check if we're
   * a leaf *and* our frame size < fudge factor.
   */
  bool skip_overflow_check = (mir_graph_->MethodIsLeaf() &&
                            (static_cast<size_t>(frame_size_) <
                            Thread::kStackOverflowReservedBytes));
  NewLIR0(kPseudoMethodEntry);
  if (!skip_overflow_check) {
    /* Load stack limit */
    LoadWordDisp(rARM_SELF, Thread::StackEndOffset().Int32Value(), r12);
  }
  /* Spill core callee saves */
  NewLIR1(kThumb2Push, core_spill_mask_);
  /* Need to spill any FP regs? */
  if (num_fp_spills_) {
    /*
     * NOTE: fp spills are a little different from core spills in that
     * they are pushed as a contiguous block.  When promoting from
     * the fp set, we must allocate all singles from s16..highest-promoted
     */
    NewLIR1(kThumb2VPushCS, num_fp_spills_);
  }
  if (!skip_overflow_check) {
    OpRegRegImm(kOpSub, rARM_LR, rARM_SP, frame_size_ - (spill_count * 4));
    GenRegRegCheck(kCondCc, rARM_LR, r12, kThrowStackOverflow);
    OpRegCopy(rARM_SP, rARM_LR);     // Establish stack
  } else {
    OpRegImm(kOpSub, rARM_SP, frame_size_ - (spill_count * 4));
  }

  FlushIns(ArgLocs, rl_method);

  FreeTemp(r0);
  FreeTemp(r1);
  FreeTemp(r2);
  FreeTemp(r3);
}

void ArmMir2Lir::GenExitSequence()
{
  int spill_count = num_core_spills_ + num_fp_spills_;
  /*
   * In the exit path, r0/r1 are live - make sure they aren't
   * allocated by the register utilities as temps.
   */
  LockTemp(r0);
  LockTemp(r1);

  NewLIR0(kPseudoMethodExit);
  OpRegImm(kOpAdd, rARM_SP, frame_size_ - (spill_count * 4));
  /* Need to restore any FP callee saves? */
  if (num_fp_spills_) {
    NewLIR1(kThumb2VPopCS, num_fp_spills_);
  }
  if (core_spill_mask_ & (1 << rARM_LR)) {
    /* Unspill rARM_LR to rARM_PC */
    core_spill_mask_ &= ~(1 << rARM_LR);
    core_spill_mask_ |= (1 << rARM_PC);
  }
  NewLIR1(kThumb2Pop, core_spill_mask_);
  if (!(core_spill_mask_ & (1 << rARM_PC))) {
    /* We didn't pop to rARM_PC, so must do a bv rARM_LR */
    NewLIR1(kThumbBx, rARM_LR);
  }
}

}  // namespace art
