/*
 * 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 arm-specific codegen factory support.
 * It is included by
 *
 *        Codegen-$(TARGET_ARCH_VARIANT).c
 *
 */

#include "oat/runtime/oat_support_entrypoints.h"

namespace art {

void genDebuggerUpdate(CompilationUnit* cUnit, int32_t offset);

bool genNegLong(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
                RegLocation rlSrc)
{
  rlSrc = loadValueWide(cUnit, rlSrc, kCoreReg);
  RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
  int zReg = oatAllocTemp(cUnit);
  loadConstantNoClobber(cUnit, zReg, 0);
  // Check for destructive overlap
  if (rlResult.lowReg == rlSrc.highReg) {
    int tReg = oatAllocTemp(cUnit);
    opRegRegReg(cUnit, kOpSub, rlResult.lowReg, zReg, rlSrc.lowReg);
    opRegRegReg(cUnit, kOpSbc, rlResult.highReg, zReg, tReg);
    oatFreeTemp(cUnit, tReg);
  } else {
    opRegRegReg(cUnit, kOpSub, rlResult.lowReg, zReg, rlSrc.lowReg);
    opRegRegReg(cUnit, kOpSbc, rlResult.highReg, zReg, rlSrc.highReg);
  }
  oatFreeTemp(cUnit, zReg);
  storeValueWide(cUnit, rlDest, rlResult);
  return false;
}

int loadHelper(CompilationUnit* cUnit, int offset)
{
  loadWordDisp(cUnit, rSELF, offset, rLR);
  return rLR;
}

void genEntrySequence(CompilationUnit* cUnit, BasicBlock* bb)
{
  int spillCount = cUnit->numCoreSpills + cUnit->numFPSpills;
  /*
   * 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.
   */
  oatLockTemp(cUnit, r0);
  oatLockTemp(cUnit, r1);
  oatLockTemp(cUnit, r2);
  oatLockTemp(cUnit, r3);

  /*
   * We can safely skip the stack overflow check if we're
   * a leaf *and* our frame size < fudge factor.
   */
  bool skipOverflowCheck = ((cUnit->attrs & METHOD_IS_LEAF) &&
                            ((size_t)cUnit->frameSize <
                            Thread::kStackOverflowReservedBytes));
  newLIR0(cUnit, kPseudoMethodEntry);
  if (!skipOverflowCheck) {
    /* Load stack limit */
    loadWordDisp(cUnit, rSELF, Thread::StackEndOffset().Int32Value(), r12);
  }
  /* Spill core callee saves */
  newLIR1(cUnit, kThumb2Push, cUnit->coreSpillMask);
  /* Need to spill any FP regs? */
  if (cUnit->numFPSpills) {
    /*
     * 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(cUnit, kThumb2VPushCS, cUnit->numFPSpills);
  }
  if (!skipOverflowCheck) {
    opRegRegImm(cUnit, kOpSub, rLR, rSP, cUnit->frameSize - (spillCount * 4));
    genRegRegCheck(cUnit, kCondCc, rLR, r12, NULL, kThrowStackOverflow);
    opRegCopy(cUnit, rSP, rLR);     // Establish stack
  } else {
    opRegImm(cUnit, kOpSub, rSP, cUnit->frameSize - (spillCount * 4));
  }

  flushIns(cUnit);

  if (cUnit->genDebugger) {
    // Refresh update debugger callout
    loadWordDisp(cUnit, rSELF,
                 ENTRYPOINT_OFFSET(pUpdateDebuggerFromCode), rSUSPEND);
    genDebuggerUpdate(cUnit, DEBUGGER_METHOD_ENTRY);
  }

  oatFreeTemp(cUnit, r0);
  oatFreeTemp(cUnit, r1);
  oatFreeTemp(cUnit, r2);
  oatFreeTemp(cUnit, r3);
}

void genExitSequence(CompilationUnit* cUnit, BasicBlock* bb)
{
  int spillCount = cUnit->numCoreSpills + cUnit->numFPSpills;
  /*
   * In the exit path, r0/r1 are live - make sure they aren't
   * allocated by the register utilities as temps.
   */
  oatLockTemp(cUnit, r0);
  oatLockTemp(cUnit, r1);

  newLIR0(cUnit, kPseudoMethodExit);
  /* If we're compiling for the debugger, generate an update callout */
  if (cUnit->genDebugger) {
    genDebuggerUpdate(cUnit, DEBUGGER_METHOD_EXIT);
  }
  opRegImm(cUnit, kOpAdd, rSP, cUnit->frameSize - (spillCount * 4));
  /* Need to restore any FP callee saves? */
  if (cUnit->numFPSpills) {
    newLIR1(cUnit, kThumb2VPopCS, cUnit->numFPSpills);
  }
  if (cUnit->coreSpillMask & (1 << rLR)) {
    /* Unspill rLR to rPC */
    cUnit->coreSpillMask &= ~(1 << rLR);
    cUnit->coreSpillMask |= (1 << rPC);
  }
  newLIR1(cUnit, kThumb2Pop, cUnit->coreSpillMask);
  if (!(cUnit->coreSpillMask & (1 << rPC))) {
    /* We didn't pop to rPC, so must do a bv rLR */
    newLIR1(cUnit, kThumbBx, rLR);
  }
}

/*
 * Nop any unconditional branches that go to the next instruction.
 * Note: new redundant branches may be inserted later, and we'll
 * use a check in final instruction assembly to nop those out.
 */
void removeRedundantBranches(CompilationUnit* cUnit)
{
  LIR* thisLIR;

  for (thisLIR = (LIR*) cUnit->firstLIRInsn;
     thisLIR != (LIR*) cUnit->lastLIRInsn;
     thisLIR = NEXT_LIR(thisLIR)) {

    /* Branch to the next instruction */
    if ((thisLIR->opcode == kThumbBUncond) ||
      (thisLIR->opcode == kThumb2BUncond)) {
      LIR* nextLIR = thisLIR;

      while (true) {
        nextLIR = NEXT_LIR(nextLIR);

        /*
         * Is the branch target the next instruction?
         */
        if (nextLIR == (LIR*) thisLIR->target) {
          thisLIR->flags.isNop = true;
          break;
        }

        /*
         * Found real useful stuff between the branch and the target.
         * Need to explicitly check the lastLIRInsn here because it
         * might be the last real instruction.
         */
        if (!isPseudoOpcode(nextLIR->opcode) ||
          (nextLIR = (LIR*) cUnit->lastLIRInsn))
          break;
      }
    }
  }
}


/* Common initialization routine for an architecture family */
bool oatArchInit()
{
  int i;

  for (i = 0; i < kArmLast; i++) {
    if (EncodingMap[i].opcode != i) {
      LOG(FATAL) << "Encoding order for " << EncodingMap[i].name
                 << " is wrong: expecting " << i << ", seeing "
                 << (int)EncodingMap[i].opcode;
    }
  }

  return oatArchVariantInit();
}
}  // namespace art
