/*
 * 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, 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, RegLocation* argLocs,
                      RegLocation rlMethod)
{
  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, kThrowStackOverflow);
    opRegCopy(cUnit, rSP, rLR);     // Establish stack
  } else {
    opRegImm(cUnit, kOpSub, rSP, cUnit->frameSize - (spillCount * 4));
  }

  flushIns(cUnit, argLocs, rlMethod);

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