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

namespace art {

/*
 * This file contains target-independent codegen and support, and is
 * included by:
 *
 *        $(TARGET_ARCH)/Codegen-$(TARGET_ARCH_VARIANT).c
 *
 * which combines this common code with specific support found in the
 * applicable directories below this one.
 *
 */

/*
 * Load an immediate value into a fixed or temp register.  Target
 * register is clobbered, and marked inUse.
 */
LIR* loadConstant(CompilationUnit* cUnit, int rDest, int value)
{
    if (oatIsTemp(cUnit, rDest)) {
        oatClobber(cUnit, rDest);
        oatMarkInUse(cUnit, rDest);
    }
    return loadConstantNoClobber(cUnit, rDest, value);
}

/* Load a word at base + displacement.  Displacement must be word multiple */
LIR* loadWordDisp(CompilationUnit* cUnit, int rBase, int displacement,
                  int rDest)
{
    return loadBaseDisp(cUnit, NULL, rBase, displacement, rDest, kWord,
                        INVALID_SREG);
}

LIR* storeWordDisp(CompilationUnit* cUnit, int rBase, int displacement,
                   int rSrc)
{
    return storeBaseDisp(cUnit, rBase, displacement, rSrc, kWord);
}

/*
 * Load a Dalvik register into a physical register.  Take care when
 * using this routine, as it doesn't perform any bookkeeping regarding
 * register liveness.  That is the responsibility of the caller.
 */
void loadValueDirect(CompilationUnit* cUnit, RegLocation rlSrc, int rDest)
{
    rlSrc = oatUpdateLoc(cUnit, rlSrc);
    if (rlSrc.location == kLocPhysReg) {
        opRegCopy(cUnit, rDest, rlSrc.lowReg);
    } else {
        DCHECK((rlSrc.location == kLocDalvikFrame) ||
               (rlSrc.location == kLocCompilerTemp));
        loadWordDisp(cUnit, rSP, oatSRegOffset(cUnit, rlSrc.sRegLow), rDest);
    }
}

/*
 * Similar to loadValueDirect, but clobbers and allocates the target
 * register.  Should be used when loading to a fixed register (for example,
 * loading arguments to an out of line call.
 */
void loadValueDirectFixed(CompilationUnit* cUnit, RegLocation rlSrc, int rDest)
{
    oatClobber(cUnit, rDest);
    oatMarkInUse(cUnit, rDest);
    loadValueDirect(cUnit, rlSrc, rDest);
}

/*
 * Load a Dalvik register pair into a physical register[s].  Take care when
 * using this routine, as it doesn't perform any bookkeeping regarding
 * register liveness.  That is the responsibility of the caller.
 */
void loadValueDirectWide(CompilationUnit* cUnit, RegLocation rlSrc, int regLo,
                         int regHi)
{
    rlSrc = oatUpdateLocWide(cUnit, rlSrc);
    if (rlSrc.location == kLocPhysReg) {
        opRegCopyWide(cUnit, regLo, regHi, rlSrc.lowReg, rlSrc.highReg);
    } else {
        DCHECK((rlSrc.location == kLocDalvikFrame) ||
               (rlSrc.location == kLocCompilerTemp));
        loadBaseDispWide(cUnit, NULL, rSP,
                         oatSRegOffset(cUnit, rlSrc.sRegLow),
                         regLo, regHi, INVALID_SREG);
    }
}

/*
 * Similar to loadValueDirect, but clobbers and allocates the target
 * registers.  Should be used when loading to a fixed registers (for example,
 * loading arguments to an out of line call.
 */
void loadValueDirectWideFixed(CompilationUnit* cUnit, RegLocation rlSrc,
                              int regLo, int regHi)
{
    oatClobber(cUnit, regLo);
    oatClobber(cUnit, regHi);
    oatMarkInUse(cUnit, regLo);
    oatMarkInUse(cUnit, regHi);
    loadValueDirectWide(cUnit, rlSrc, regLo, regHi);
}

RegLocation loadValue(CompilationUnit* cUnit, RegLocation rlSrc,
                      RegisterClass opKind)
{
    rlSrc = oatEvalLoc(cUnit, rlSrc, opKind, false);
    if (rlSrc.location != kLocPhysReg) {
        DCHECK((rlSrc.location == kLocDalvikFrame) ||
               (rlSrc.location == kLocCompilerTemp));
        loadValueDirect(cUnit, rlSrc, rlSrc.lowReg);
        rlSrc.location = kLocPhysReg;
        oatMarkLive(cUnit, rlSrc.lowReg, rlSrc.sRegLow);
    }
    return rlSrc;
}

void storeValue(CompilationUnit* cUnit, RegLocation rlDest, RegLocation rlSrc)
{
#ifndef NDEBUG
    /*
     * Sanity checking - should never try to store to the same
     * ssa name during the compilation of a single instruction
     * without an intervening oatClobberSReg().
     */
    DCHECK((cUnit->liveSReg == INVALID_SREG) ||
           (rlDest.sRegLow != cUnit->liveSReg));
    cUnit->liveSReg = rlDest.sRegLow;
#endif
    LIR* defStart;
    LIR* defEnd;
    DCHECK(!rlDest.wide);
    DCHECK(!rlSrc.wide);
    rlSrc = oatUpdateLoc(cUnit, rlSrc);
    rlDest = oatUpdateLoc(cUnit, rlDest);
    if (rlSrc.location == kLocPhysReg) {
        if (oatIsLive(cUnit, rlSrc.lowReg) ||
            oatIsPromoted(cUnit, rlSrc.lowReg) ||
            (rlDest.location == kLocPhysReg)) {
            // Src is live/promoted or Dest has assigned reg.
            rlDest = oatEvalLoc(cUnit, rlDest, kAnyReg, false);
            opRegCopy(cUnit, rlDest.lowReg, rlSrc.lowReg);
        } else {
            // Just re-assign the registers.  Dest gets Src's regs
            rlDest.lowReg = rlSrc.lowReg;
            oatClobber(cUnit, rlSrc.lowReg);
        }
    } else {
        // Load Src either into promoted Dest or temps allocated for Dest
        rlDest = oatEvalLoc(cUnit, rlDest, kAnyReg, false);
        loadValueDirect(cUnit, rlSrc, rlDest.lowReg);
    }

    // Dest is now live and dirty (until/if we flush it to home location)
    oatMarkLive(cUnit, rlDest.lowReg, rlDest.sRegLow);
    oatMarkDirty(cUnit, rlDest);


    oatResetDefLoc(cUnit, rlDest);
    if (oatIsDirty(cUnit, rlDest.lowReg) &&
        oatLiveOut(cUnit, rlDest.sRegLow)) {
        defStart = (LIR* )cUnit->lastLIRInsn;
        storeBaseDisp(cUnit, rSP, oatSRegOffset(cUnit, rlDest.sRegLow),
                      rlDest.lowReg, kWord);
        oatMarkClean(cUnit, rlDest);
        defEnd = (LIR* )cUnit->lastLIRInsn;
        oatMarkDef(cUnit, rlDest, defStart, defEnd);
    }
}

RegLocation loadValueWide(CompilationUnit* cUnit, RegLocation rlSrc,
                          RegisterClass opKind)
{
    DCHECK(rlSrc.wide);
    rlSrc = oatEvalLoc(cUnit, rlSrc, opKind, false);
    if (rlSrc.location != kLocPhysReg) {
        DCHECK((rlSrc.location == kLocDalvikFrame) ||
               (rlSrc.location == kLocCompilerTemp));
        loadValueDirectWide(cUnit, rlSrc, rlSrc.lowReg, rlSrc.highReg);
        rlSrc.location = kLocPhysReg;
        oatMarkLive(cUnit, rlSrc.lowReg, rlSrc.sRegLow);
        oatMarkLive(cUnit, rlSrc.highReg,
                            oatSRegHi(rlSrc.sRegLow));
    }
    return rlSrc;
}

void storeValueWide(CompilationUnit* cUnit, RegLocation rlDest,
                    RegLocation rlSrc)
{
#ifndef NDEBUG
    /*
     * Sanity checking - should never try to store to the same
     * ssa name during the compilation of a single instruction
     * without an intervening oatClobberSReg().
     */
    DCHECK((cUnit->liveSReg == INVALID_SREG) ||
           (rlDest.sRegLow != cUnit->liveSReg));
    cUnit->liveSReg = rlDest.sRegLow;
#endif
    LIR* defStart;
    LIR* defEnd;
    DCHECK_EQ(FPREG(rlSrc.lowReg), FPREG(rlSrc.highReg));
    DCHECK(rlDest.wide);
    DCHECK(rlSrc.wide);
    if (rlSrc.location == kLocPhysReg) {
        if (oatIsLive(cUnit, rlSrc.lowReg) ||
            oatIsLive(cUnit, rlSrc.highReg) ||
            oatIsPromoted(cUnit, rlSrc.lowReg) ||
            oatIsPromoted(cUnit, rlSrc.highReg) ||
            (rlDest.location == kLocPhysReg)) {
            // Src is live or promoted or Dest has assigned reg.
            rlDest = oatEvalLoc(cUnit, rlDest, kAnyReg, false);
            opRegCopyWide(cUnit, rlDest.lowReg, rlDest.highReg,
                           rlSrc.lowReg, rlSrc.highReg);
        } else {
            // Just re-assign the registers.  Dest gets Src's regs
            rlDest.lowReg = rlSrc.lowReg;
            rlDest.highReg = rlSrc.highReg;
            oatClobber(cUnit, rlSrc.lowReg);
            oatClobber(cUnit, rlSrc.highReg);
        }
    } else {
        // Load Src either into promoted Dest or temps allocated for Dest
        rlDest = oatEvalLoc(cUnit, rlDest, kAnyReg, false);
        loadValueDirectWide(cUnit, rlSrc, rlDest.lowReg,
                            rlDest.highReg);
    }

    // Dest is now live and dirty (until/if we flush it to home location)
    oatMarkLive(cUnit, rlDest.lowReg, rlDest.sRegLow);
    oatMarkLive(cUnit, rlDest.highReg,
                        oatSRegHi(rlDest.sRegLow));
    oatMarkDirty(cUnit, rlDest);
    oatMarkPair(cUnit, rlDest.lowReg, rlDest.highReg);


    oatResetDefLocWide(cUnit, rlDest);
    if ((oatIsDirty(cUnit, rlDest.lowReg) ||
        oatIsDirty(cUnit, rlDest.highReg)) &&
        (oatLiveOut(cUnit, rlDest.sRegLow) ||
        oatLiveOut(cUnit, oatSRegHi(rlDest.sRegLow)))) {
        defStart = (LIR*)cUnit->lastLIRInsn;
        DCHECK_EQ((SRegToVReg(cUnit, rlDest.sRegLow)+1),
                   SRegToVReg(cUnit, oatSRegHi(rlDest.sRegLow)));
        storeBaseDispWide(cUnit, rSP, oatSRegOffset(cUnit, rlDest.sRegLow),
                          rlDest.lowReg, rlDest.highReg);
        oatMarkClean(cUnit, rlDest);
        defEnd = (LIR*)cUnit->lastLIRInsn;
        oatMarkDefWide(cUnit, rlDest, defStart, defEnd);
    }
}

/*
 * Mark garbage collection card. Skip if the value we're storing is null.
 */
void markGCCard(CompilationUnit* cUnit, int valReg, int tgtAddrReg)
{
    int regCardBase = oatAllocTemp(cUnit);
    int regCardNo = oatAllocTemp(cUnit);
    LIR* branchOver = opCmpImmBranch(cUnit, kCondEq, valReg, 0, NULL);
#if !defined(TARGET_X86)
    loadWordDisp(cUnit, rSELF, Thread::CardTableOffset().Int32Value(),
                 regCardBase);
#else
    newLIR2(cUnit, kX86Mov32RT, regCardBase,
            Thread::CardTableOffset().Int32Value());
#endif
    opRegRegImm(cUnit, kOpLsr, regCardNo, tgtAddrReg, GC_CARD_SHIFT);
    storeBaseIndexed(cUnit, regCardBase, regCardNo, regCardBase, 0,
                     kUnsignedByte);
    LIR* target = newLIR0(cUnit, kPseudoTargetLabel);
    branchOver->target = (LIR*)target;
    oatFreeTemp(cUnit, regCardBase);
    oatFreeTemp(cUnit, regCardNo);
}

/* Utilities to load the current Method* */
void loadCurrMethodDirect(CompilationUnit *cUnit, int rTgt)
{
    loadValueDirectFixed(cUnit, cUnit->regLocation[cUnit->methodSReg], rTgt);
}

RegLocation loadCurrMethod(CompilationUnit *cUnit)
{
    return loadValue(cUnit, cUnit->regLocation[cUnit->methodSReg], kCoreReg);
}

bool methodStarInReg(CompilationUnit* cUnit)
{
     return (cUnit->regLocation[cUnit->methodSReg].location == kLocPhysReg);
}


}  // namespace art
