/*
 * 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.
 */

/* This file contains codegen for the Mips ISA */

#include "oat/runtime/oat_support_entrypoints.h"
#include "mips_lir.h"
#include "codegen_mips.h"
#include "../codegen_util.h"
#include "../ralloc_util.h"

namespace art {

void MipsCodegen::GenSpecialCase(CompilationUnit* cu, BasicBlock* bb, MIR* mir,
                                 SpecialCaseHandler special_case)
{
    // TODO
}

/*
 * The lack of pc-relative loads on Mips presents somewhat of a challenge
 * for our PIC switch table strategy.  To materialize the current location
 * we'll do a dummy JAL and reference our tables using r_RA as the
 * base register.  Note that r_RA will be used both as the base to
 * locate the switch table data and as the reference base for the switch
 * target offsets stored in the table.  We'll use a special pseudo-instruction
 * to represent the jal and trigger the construction of the
 * switch table offsets (which will happen after final assembly and all
 * labels are fixed).
 *
 * The test loop will look something like:
 *
 *   ori   rEnd, r_ZERO, #table_size  ; size in bytes
 *   jal   BaseLabel         ; stores "return address" (BaseLabel) in r_RA
 *   nop                     ; opportunistically fill
 * BaseLabel:
 *   addiu rBase, r_RA, <table> - <BaseLabel>  ; table relative to BaseLabel
     addu  rEnd, rEnd, rBase                   ; end of table
 *   lw    r_val, [rSP, v_reg_off]                ; Test Value
 * loop:
 *   beq   rBase, rEnd, done
 *   lw    r_key, 0(rBase)
 *   addu  rBase, 8
 *   bne   r_val, r_key, loop
 *   lw    r_disp, -4(rBase)
 *   addu  r_RA, r_disp
 *   jr    r_RA
 * done:
 *
 */
void MipsCodegen::GenSparseSwitch(CompilationUnit* cu, uint32_t table_offset, RegLocation rl_src)
{
  const uint16_t* table = cu->insns + cu->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 = cu->current_dalvik_offset;
  int elements = table[1];
  tab_rec->targets =
      static_cast<LIR**>(NewMem(cu, elements * sizeof(LIR*), true, kAllocLIR));
  InsertGrowableList(cu, &cu->switch_tables, reinterpret_cast<uintptr_t>(tab_rec));

  // The table is composed of 8-byte key/disp pairs
  int byte_size = elements * 8;

  int size_hi = byte_size >> 16;
  int size_lo = byte_size & 0xffff;

  int rEnd = AllocTemp(cu);
  if (size_hi) {
    NewLIR2(cu, kMipsLui, rEnd, size_hi);
  }
  // Must prevent code motion for the curr pc pair
  GenBarrier(cu);  // Scheduling barrier
  NewLIR0(cu, kMipsCurrPC);  // Really a jal to .+8
  // Now, fill the branch delay slot
  if (size_hi) {
    NewLIR3(cu, kMipsOri, rEnd, rEnd, size_lo);
  } else {
    NewLIR3(cu, kMipsOri, rEnd, r_ZERO, size_lo);
  }
  GenBarrier(cu);  // Scheduling barrier

  // Construct BaseLabel and set up table base register
  LIR* base_label = NewLIR0(cu, kPseudoTargetLabel);
  // Remember base label so offsets can be computed later
  tab_rec->anchor = base_label;
  int rBase = AllocTemp(cu);
  NewLIR4(cu, kMipsDelta, rBase, 0, reinterpret_cast<uintptr_t>(base_label),
          reinterpret_cast<uintptr_t>(tab_rec));
  OpRegRegReg(cu, kOpAdd, rEnd, rEnd, rBase);

  // Grab switch test value
  rl_src = LoadValue(cu, rl_src, kCoreReg);

  // Test loop
  int r_key = AllocTemp(cu);
  LIR* loop_label = NewLIR0(cu, kPseudoTargetLabel);
  LIR* exit_branch = OpCmpBranch(cu , kCondEq, rBase, rEnd, NULL);
  LoadWordDisp(cu, rBase, 0, r_key);
  OpRegImm(cu, kOpAdd, rBase, 8);
  OpCmpBranch(cu, kCondNe, rl_src.low_reg, r_key, loop_label);
  int r_disp = AllocTemp(cu);
  LoadWordDisp(cu, rBase, -4, r_disp);
  OpRegRegReg(cu, kOpAdd, r_RA, r_RA, r_disp);
  OpReg(cu, kOpBx, r_RA);

  // Loop exit
  LIR* exit_label = NewLIR0(cu, kPseudoTargetLabel);
  exit_branch->target = exit_label;
}

/*
 * Code pattern will look something like:
 *
 *   lw    r_val
 *   jal   BaseLabel         ; stores "return address" (BaseLabel) in r_RA
 *   nop                     ; opportunistically fill
 *   [subiu r_val, bias]      ; Remove bias if low_val != 0
 *   bound check -> done
 *   lw    r_disp, [r_RA, r_val]
 *   addu  r_RA, r_disp
 *   jr    r_RA
 * done:
 */
void MipsCodegen::GenPackedSwitch(CompilationUnit* cu, uint32_t table_offset, RegLocation rl_src)
{
  const uint16_t* table = cu->insns + cu->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 = cu->current_dalvik_offset;
  int size = table[1];
  tab_rec->targets = static_cast<LIR**>(NewMem(cu, size * sizeof(LIR*), true, kAllocLIR));
  InsertGrowableList(cu, &cu->switch_tables, reinterpret_cast<uintptr_t>(tab_rec));

  // Get the switch value
  rl_src = LoadValue(cu, rl_src, kCoreReg);

  // Prepare the bias.  If too big, handle 1st stage here
  int low_key = s4FromSwitchData(&table[2]);
  bool large_bias = false;
  int r_key;
  if (low_key == 0) {
    r_key = rl_src.low_reg;
  } else if ((low_key & 0xffff) != low_key) {
    r_key = AllocTemp(cu);
    LoadConstant(cu, r_key, low_key);
    large_bias = true;
  } else {
    r_key = AllocTemp(cu);
  }

  // Must prevent code motion for the curr pc pair
  GenBarrier(cu);
  NewLIR0(cu, kMipsCurrPC);  // Really a jal to .+8
  // Now, fill the branch delay slot with bias strip
  if (low_key == 0) {
    NewLIR0(cu, kMipsNop);
  } else {
    if (large_bias) {
      OpRegRegReg(cu, kOpSub, r_key, rl_src.low_reg, r_key);
    } else {
      OpRegRegImm(cu, kOpSub, r_key, rl_src.low_reg, low_key);
    }
  }
  GenBarrier(cu);  // Scheduling barrier

  // Construct BaseLabel and set up table base register
  LIR* base_label = NewLIR0(cu, kPseudoTargetLabel);
  // Remember base label so offsets can be computed later
  tab_rec->anchor = base_label;

  // Bounds check - if < 0 or >= size continue following switch
  LIR* branch_over = OpCmpImmBranch(cu, kCondHi, r_key, size-1, NULL);

  // Materialize the table base pointer
  int rBase = AllocTemp(cu);
  NewLIR4(cu, kMipsDelta, rBase, 0, reinterpret_cast<uintptr_t>(base_label),
          reinterpret_cast<uintptr_t>(tab_rec));

  // Load the displacement from the switch table
  int r_disp = AllocTemp(cu);
  LoadBaseIndexed(cu, rBase, r_key, r_disp, 2, kWord);

  // Add to r_AP and go
  OpRegRegReg(cu, kOpAdd, r_RA, r_RA, r_disp);
  OpReg(cu, kOpBx, r_RA);

  /* branch_over target here */
  LIR* target = NewLIR0(cu, 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 MipsCodegen::GenFillArrayData(CompilationUnit* cu, uint32_t table_offset, RegLocation rl_src)
{
  const uint16_t* table = cu->insns + cu->current_dalvik_offset + table_offset;
  // Add the table to the list - we'll process it later
  FillArrayData *tab_rec =
      reinterpret_cast<FillArrayData*>(NewMem(cu, sizeof(FillArrayData), true, kAllocData));
  tab_rec->table = table;
  tab_rec->vaddr = cu->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, &cu->fill_array_data, reinterpret_cast<uintptr_t>(tab_rec));

  // Making a call - use explicit registers
  FlushAllRegs(cu);   /* Everything to home location */
  LockCallTemps(cu);
  LoadValueDirectFixed(cu, rl_src, rMIPS_ARG0);

  // Must prevent code motion for the curr pc pair
  GenBarrier(cu);
  NewLIR0(cu, kMipsCurrPC);  // Really a jal to .+8
  // Now, fill the branch delay slot with the helper load
  int r_tgt = LoadHelper(cu, ENTRYPOINT_OFFSET(pHandleFillArrayDataFromCode));
  GenBarrier(cu);  // Scheduling barrier

  // Construct BaseLabel and set up table base register
  LIR* base_label = NewLIR0(cu, kPseudoTargetLabel);

  // Materialize a pointer to the fill data image
  NewLIR4(cu, kMipsDelta, rMIPS_ARG1, 0, reinterpret_cast<uintptr_t>(base_label),
          reinterpret_cast<uintptr_t>(tab_rec));

  // And go...
  ClobberCalleeSave(cu);
  LIR* call_inst = OpReg(cu, kOpBlx, r_tgt); // ( array*, fill_data* )
  MarkSafepointPC(cu, call_inst);
}

/*
 * TODO: implement fast path to short-circuit thin-lock case
 */
void MipsCodegen::GenMonitorEnter(CompilationUnit* cu, int opt_flags, RegLocation rl_src)
{
  FlushAllRegs(cu);
  LoadValueDirectFixed(cu, rl_src, rMIPS_ARG0);  // Get obj
  LockCallTemps(cu);  // Prepare for explicit register usage
  GenNullCheck(cu, rl_src.s_reg_low, rMIPS_ARG0, opt_flags);
  // Go expensive route - artLockObjectFromCode(self, obj);
  int r_tgt = LoadHelper(cu, ENTRYPOINT_OFFSET(pLockObjectFromCode));
  ClobberCalleeSave(cu);
  LIR* call_inst = OpReg(cu, kOpBlx, r_tgt);
  MarkSafepointPC(cu, call_inst);
}

/*
 * TODO: implement fast path to short-circuit thin-lock case
 */
void MipsCodegen::GenMonitorExit(CompilationUnit* cu, int opt_flags, RegLocation rl_src)
{
  FlushAllRegs(cu);
  LoadValueDirectFixed(cu, rl_src, rMIPS_ARG0);  // Get obj
  LockCallTemps(cu);  // Prepare for explicit register usage
  GenNullCheck(cu, rl_src.s_reg_low, rMIPS_ARG0, opt_flags);
  // Go expensive route - UnlockObjectFromCode(obj);
  int r_tgt = LoadHelper(cu, ENTRYPOINT_OFFSET(pUnlockObjectFromCode));
  ClobberCalleeSave(cu);
  LIR* call_inst = OpReg(cu, kOpBlx, r_tgt);
  MarkSafepointPC(cu, call_inst);
}

/*
 * Mark garbage collection card. Skip if the value we're storing is null.
 */
void MipsCodegen::MarkGCCard(CompilationUnit* cu, int val_reg, int tgt_addr_reg)
{
  int reg_card_base = AllocTemp(cu);
  int reg_card_no = AllocTemp(cu);
  LIR* branch_over = OpCmpImmBranch(cu, kCondEq, val_reg, 0, NULL);
  LoadWordDisp(cu, rMIPS_SELF, Thread::CardTableOffset().Int32Value(), reg_card_base);
  OpRegRegImm(cu, kOpLsr, reg_card_no, tgt_addr_reg, CardTable::kCardShift);
  StoreBaseIndexed(cu, reg_card_base, reg_card_no, reg_card_base, 0,
                   kUnsignedByte);
  LIR* target = NewLIR0(cu, kPseudoTargetLabel);
  branch_over->target = target;
  FreeTemp(cu, reg_card_base);
  FreeTemp(cu, reg_card_no);
}
void MipsCodegen::GenEntrySequence(CompilationUnit* cu, RegLocation* ArgLocs, RegLocation rl_method)
{
  int spill_count = cu->num_core_spills + cu->num_fp_spills;
  /*
   * On entry, rMIPS_ARG0, rMIPS_ARG1, rMIPS_ARG2 & rMIPS_ARG3 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(cu, rMIPS_ARG0);
  LockTemp(cu, rMIPS_ARG1);
  LockTemp(cu, rMIPS_ARG2);
  LockTemp(cu, rMIPS_ARG3);

  /*
   * We can safely skip the stack overflow check if we're
   * a leaf *and* our frame size < fudge factor.
   */
  bool skip_overflow_check = ((cu->attrs & METHOD_IS_LEAF) &&
      (static_cast<size_t>(cu->frame_size) < Thread::kStackOverflowReservedBytes));
  NewLIR0(cu, kPseudoMethodEntry);
  int check_reg = AllocTemp(cu);
  int new_sp = AllocTemp(cu);
  if (!skip_overflow_check) {
    /* Load stack limit */
    LoadWordDisp(cu, rMIPS_SELF, Thread::StackEndOffset().Int32Value(), check_reg);
  }
  /* Spill core callee saves */
  SpillCoreRegs(cu);
  /* NOTE: promotion of FP regs currently unsupported, thus no FP spill */
  DCHECK_EQ(cu->num_fp_spills, 0);
  if (!skip_overflow_check) {
    OpRegRegImm(cu, kOpSub, new_sp, rMIPS_SP, cu->frame_size - (spill_count * 4));
    GenRegRegCheck(cu, kCondCc, new_sp, check_reg, kThrowStackOverflow);
    OpRegCopy(cu, rMIPS_SP, new_sp);     // Establish stack
  } else {
    OpRegImm(cu, kOpSub, rMIPS_SP, cu->frame_size - (spill_count * 4));
  }

  FlushIns(cu, ArgLocs, rl_method);

  FreeTemp(cu, rMIPS_ARG0);
  FreeTemp(cu, rMIPS_ARG1);
  FreeTemp(cu, rMIPS_ARG2);
  FreeTemp(cu, rMIPS_ARG3);
}

void MipsCodegen::GenExitSequence(CompilationUnit* cu)
{
  /*
   * In the exit path, rMIPS_RET0/rMIPS_RET1 are live - make sure they aren't
   * allocated by the register utilities as temps.
   */
  LockTemp(cu, rMIPS_RET0);
  LockTemp(cu, rMIPS_RET1);

  NewLIR0(cu, kPseudoMethodExit);
  UnSpillCoreRegs(cu);
  OpReg(cu, kOpBx, r_RA);
}

}  // namespace art
