/*
 * 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 Mips-specific register allocation support.
 */

#include "../../CompilerUtility.h"
#include "../../CompilerIR.h"
#include "../..//Dataflow.h"
#include "MipsLIR.h"
#include "Codegen.h"
#include "../Ralloc.h"

namespace art {

/*
 * TUNING: is leaf?  Can't just use "hasInvoke" to determine as some
 * instructions might call out to C/assembly helper functions.  Until
 * machinery is in place, always spill lr.
 */

void oatAdjustSpillMask(CompilationUnit* cUnit)
{
  cUnit->coreSpillMask |= (1 << r_RA);
  cUnit->numCoreSpills++;
}

/*
 * Mark a callee-save fp register as promoted.  Note that
 * vpush/vpop uses contiguous register lists so we must
 * include any holes in the mask.  Associate holes with
 * Dalvik register INVALID_VREG (0xFFFFU).
 */
void oatMarkPreservedSingle(CompilationUnit* cUnit, int sReg, int reg)
{
  LOG(FATAL) << "No support yet for promoted FP regs";
}

void oatFlushRegWide(CompilationUnit* cUnit, int reg1, int reg2)
{
  RegisterInfo* info1 = oatGetRegInfo(cUnit, reg1);
  RegisterInfo* info2 = oatGetRegInfo(cUnit, reg2);
  DCHECK(info1 && info2 && info1->pair && info2->pair &&
         (info1->partner == info2->reg) &&
         (info2->partner == info1->reg));
  if ((info1->live && info1->dirty) || (info2->live && info2->dirty)) {
    if (!(info1->isTemp && info2->isTemp)) {
      /* Should not happen.  If it does, there's a problem in evalLoc */
      LOG(FATAL) << "Long half-temp, half-promoted";
    }

    info1->dirty = false;
    info2->dirty = false;
    if (SRegToVReg(cUnit, info2->sReg) < SRegToVReg(cUnit, info1->sReg))
      info1 = info2;
    int vReg = SRegToVReg(cUnit, info1->sReg);
    oatFlushRegWideImpl(cUnit, rSP, oatVRegOffset(cUnit, vReg), info1->reg,
                        info1->partner);
  }
}

void oatFlushReg(CompilationUnit* cUnit, int reg)
{
  RegisterInfo* info = oatGetRegInfo(cUnit, reg);
  if (info->live && info->dirty) {
    info->dirty = false;
    int vReg = SRegToVReg(cUnit, info->sReg);
    oatFlushRegImpl(cUnit, rSP, oatVRegOffset(cUnit, vReg), reg, kWord);
  }
}

/* Give access to the target-dependent FP register encoding to common code */
bool oatIsFpReg(int reg) {
  return FPREG(reg);
}

uint32_t oatFpRegMask() {
  return FP_REG_MASK;
}

/* Clobber all regs that might be used by an external C call */
extern void oatClobberCalleeSave(CompilationUnit *cUnit)
{
  oatClobber(cUnit, r_ZERO);
  oatClobber(cUnit, r_AT);
  oatClobber(cUnit, r_V0);
  oatClobber(cUnit, r_V1);
  oatClobber(cUnit, r_A0);
  oatClobber(cUnit, r_A1);
  oatClobber(cUnit, r_A2);
  oatClobber(cUnit, r_A3);
  oatClobber(cUnit, r_T0);
  oatClobber(cUnit, r_T1);
  oatClobber(cUnit, r_T2);
  oatClobber(cUnit, r_T3);
  oatClobber(cUnit, r_T4);
  oatClobber(cUnit, r_T5);
  oatClobber(cUnit, r_T6);
  oatClobber(cUnit, r_T7);
  oatClobber(cUnit, r_T8);
  oatClobber(cUnit, r_T9);
  oatClobber(cUnit, r_K0);
  oatClobber(cUnit, r_K1);
  oatClobber(cUnit, r_GP);
  oatClobber(cUnit, r_FP);
  oatClobber(cUnit, r_RA);
  oatClobber(cUnit, r_F0);
  oatClobber(cUnit, r_F1);
  oatClobber(cUnit, r_F2);
  oatClobber(cUnit, r_F3);
  oatClobber(cUnit, r_F4);
  oatClobber(cUnit, r_F5);
  oatClobber(cUnit, r_F6);
  oatClobber(cUnit, r_F7);
  oatClobber(cUnit, r_F8);
  oatClobber(cUnit, r_F9);
  oatClobber(cUnit, r_F10);
  oatClobber(cUnit, r_F11);
  oatClobber(cUnit, r_F12);
  oatClobber(cUnit, r_F13);
  oatClobber(cUnit, r_F14);
  oatClobber(cUnit, r_F15);
}

extern RegLocation oatGetReturnWideAlt(CompilationUnit* cUnit)
{
  RegLocation res = LOC_C_RETURN_WIDE_ALT;
  oatClobber(cUnit, res.lowReg);
  oatClobber(cUnit, res.highReg);
  oatMarkInUse(cUnit, res.lowReg);
  oatMarkInUse(cUnit, res.highReg);
  oatMarkPair(cUnit, res.lowReg, res.highReg);
  return res;
}

extern RegLocation oatGetReturnAlt(CompilationUnit* cUnit)
{
  RegLocation res = LOC_C_RETURN_ALT;
  oatClobber(cUnit, res.lowReg);
  oatMarkInUse(cUnit, res.lowReg);
  return res;
}

extern RegisterInfo* oatGetRegInfo(CompilationUnit* cUnit, int reg)
{
  return FPREG(reg) ? &cUnit->regPool->FPRegs[reg & FP_REG_MASK]
            : &cUnit->regPool->coreRegs[reg];
}

/* To be used when explicitly managing register use */
extern void oatLockCallTemps(CompilationUnit* cUnit)
{
  oatLockTemp(cUnit, rARG0);
  oatLockTemp(cUnit, rARG1);
  oatLockTemp(cUnit, rARG2);
  oatLockTemp(cUnit, rARG3);
}

/* To be used when explicitly managing register use */
extern void oatFreeCallTemps(CompilationUnit* cUnit)
{
  oatFreeTemp(cUnit, rARG0);
  oatFreeTemp(cUnit, rARG1);
  oatFreeTemp(cUnit, rARG2);
  oatFreeTemp(cUnit, rARG3);
}

/* Convert an instruction to a NOP */
void oatNopLIR( LIR* lir)
{
  ((LIR*)lir)->flags.isNop = true;
}

}  // namespace art
