/*
 * 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 register alloction support and is intended to be
 * included by:
 *
 *        Codegen-$(TARGET_ARCH_VARIANT).c
 *
 */

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

#define SREG(c, s) ((c)->regLocation[(s)].sRegLow)
/*
 * Get the "real" sreg number associated with an sReg slot.  In general,
 * sReg values passed through codegen are the SSA names created by
 * dataflow analysis and refer to slot numbers in the cUnit->regLocation
 * array.  However, renaming is accomplished by simply replacing RegLocation
 * entries in the cUnit->reglocation[] array.  Therefore, when location
 * records for operands are first created, we need to ask the locRecord
 * identified by the dataflow pass what it's new name is.
 */

/*
 * Free all allocated temps in the temp pools.  Note that this does
 * not affect the "liveness" of a temp register, which will stay
 * live until it is either explicitly killed or reallocated.
 */
extern void oatResetRegPool(CompilationUnit* cUnit)
{
    int i;
    for (i=0; i < cUnit->regPool->numCoreRegs; i++) {
        if (cUnit->regPool->coreRegs[i].isTemp)
            cUnit->regPool->coreRegs[i].inUse = false;
    }
    for (i=0; i < cUnit->regPool->numFPRegs; i++) {
        if (cUnit->regPool->FPRegs[i].isTemp)
            cUnit->regPool->FPRegs[i].inUse = false;
    }
}

 /* Set up temp & preserved register pools specialized by target */
extern void oatInitPool(RegisterInfo* regs, int* regNums, int num)
{
    int i;
    for (i=0; i < num; i++) {
        regs[i].reg = regNums[i];
        regs[i].inUse = false;
        regs[i].isTemp = false;
        regs[i].pair = false;
        regs[i].live = false;
        regs[i].dirty = false;
        regs[i].sReg = INVALID_SREG;
    }
}

static void dumpRegPool(RegisterInfo* p, int numRegs)
{
    int i;
    LOG(INFO) << "================================================";
    for (i=0; i < numRegs; i++ ){
        char buf[100];
        snprintf(buf, 100,
            "R[%d]: T:%d, U:%d, P:%d, p:%d, LV:%d, D:%d, SR:%d, ST:%x, EN:%x",
            p[i].reg, p[i].isTemp, p[i].inUse, p[i].pair, p[i].partner,
            p[i].live, p[i].dirty, p[i].sReg,(int)p[i].defStart,
            (int)p[i].defEnd);
    LOG(INFO) << buf;
    }
    LOG(INFO) << "================================================";
}

/* Get info for a reg. */
static RegisterInfo* getRegInfo(CompilationUnit* cUnit, int reg)
{
    int numRegs = cUnit->regPool->numCoreRegs;
    RegisterInfo* p = cUnit->regPool->coreRegs;
    int i;
    for (i=0; i< numRegs; i++) {
        if (p[i].reg == reg) {
            return &p[i];
        }
    }
    p = cUnit->regPool->FPRegs;
    numRegs = cUnit->regPool->numFPRegs;
    for (i=0; i< numRegs; i++) {
        if (p[i].reg == reg) {
            return &p[i];
        }
    }
    LOG(FATAL) << "Tried to get info on a non-existant reg :r" << reg;
    return NULL; // Quiet gcc
}

void oatFlushRegWide(CompilationUnit* cUnit, int reg1, int reg2)
{
    RegisterInfo* info1 = getRegInfo(cUnit, reg1);
    RegisterInfo* info2 = getRegInfo(cUnit, reg2);
    assert(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 (oatS2VReg(cUnit, info2->sReg) <
            oatS2VReg(cUnit, info1->sReg))
            info1 = info2;
        int vReg = oatS2VReg(cUnit, info1->sReg);
        oatFlushRegWideImpl(cUnit, rSP,
                                    oatVRegOffset(cUnit, vReg),
                                    info1->reg, info1->partner);
    }
}

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

/* return true if found reg to clobber */
static bool clobberRegBody(CompilationUnit* cUnit, RegisterInfo* p,
                           int numRegs, int reg)
{
    int i;
    for (i=0; i< numRegs; i++) {
        if (p[i].reg == reg) {
            if (p[i].isTemp) {
                if (p[i].isTemp && p[i].live && p[i].dirty) {
                    if (p[i].pair) {
                        oatFlushRegWide(cUnit, p[i].reg, p[i].partner);
                    } else {
                        oatFlushReg(cUnit, p[i].reg);
                    }
                }
                p[i].live = false;
                p[i].sReg = INVALID_SREG;
            }
            p[i].defStart = NULL;
            p[i].defEnd = NULL;
            if (p[i].pair) {
                p[i].pair = false;
                /* partners should be in same pool */
                clobberRegBody(cUnit, p, numRegs, p[i].partner);
            }
            return true;
        }
    }
    return false;
}

/* Mark a temp register as dead.  Does not affect allocation state. */
void oatClobber(CompilationUnit* cUnit, int reg)
{
    if (!clobberRegBody(cUnit, cUnit->regPool->coreRegs,
                        cUnit->regPool->numCoreRegs, reg)) {
        clobberRegBody(cUnit, cUnit->regPool->FPRegs,
                       cUnit->regPool->numFPRegs, reg);
    }
}

static void clobberSRegBody(RegisterInfo* p, int numRegs, int sReg)
{
    int i;
    for (i=0; i< numRegs; i++) {
        if (p[i].sReg == sReg) {
            if (p[i].isTemp) {
                p[i].live = false;
            }
            p[i].defStart = NULL;
            p[i].defEnd = NULL;
        }
    }
}

/* Clobber any temp associated with an sReg.  Could be in either class */
extern void oatClobberSReg(CompilationUnit* cUnit, int sReg)
{
    clobberSRegBody(cUnit->regPool->coreRegs, cUnit->regPool->numCoreRegs,
                    sReg);
    clobberSRegBody(cUnit->regPool->FPRegs, cUnit->regPool->numFPRegs,
                    sReg);
}

/* Reserve a callee-save register.  Return -1 if none available */
extern int oatAllocPreservedCoreReg(CompilationUnit* cUnit, int sReg)
{
    int res = -1;
    RegisterInfo* coreRegs = cUnit->regPool->coreRegs;
    for (int i = 0; i < cUnit->regPool->numCoreRegs; i++) {
        if (!coreRegs[i].isTemp && !coreRegs[i].inUse) {
            res = coreRegs[i].reg;
            coreRegs[i].inUse = true;
            cUnit->coreSpillMask |= (1 << res);
            cUnit->numSpills++;
            cUnit->regLocation[sReg].location = kLocPhysReg;
            cUnit->regLocation[sReg].lowReg = res;
            cUnit->regLocation[sReg].home = true;
            break;
        }
    }
    return res;
}

/*
 * Reserve a callee-save fp single register.  Try to fullfill request for
 * even/odd  allocation, but go ahead and allocate anything if not
 * available.  If nothing's available, return -1.
 */
static int allocPreservedSingle(CompilationUnit* cUnit, int sReg, bool even)
{
    int res = -1;
    RegisterInfo* FPRegs = cUnit->regPool->FPRegs;
    for (int i = 0; i < cUnit->regPool->numFPRegs; i++) {
        if (!FPRegs[i].isTemp && !FPRegs[i].inUse &&
            ((FPRegs[i].reg & 0x1) == 0) == even) {
            res = FPRegs[i].reg;
            FPRegs[i].inUse = true;
            cUnit->fpSpillMask |= (1 << (res & FP_REG_MASK));
            cUnit->numSpills++;
            cUnit->numFPSpills++;
            cUnit->regLocation[sReg].fpLocation = kLocPhysReg;
            cUnit->regLocation[sReg].fpLowReg = res;
            cUnit->regLocation[sReg].home = true;
            break;
        }
    }
    return res;
}

/*
 * Somewhat messy code here.  We want to allocate a pair of contiguous
 * physical single-precision floating point registers starting with
 * an even numbered reg.  It is possible that the paired sReg (sReg+1)
 * has already been allocated - try to fit if possible.  Fail to
 * allocate if we can't meet the requirements for the pair of
 * sReg<=sX[even] & (sReg+1)<= sX+1.
 */
static int allocPreservedDouble(CompilationUnit* cUnit, int sReg)
{
    int res = -1; // Assume failure
    if (cUnit->regLocation[sReg+1].fpLocation == kLocPhysReg) {
        // Upper reg is already allocated.  Can we fit?
        int highReg = cUnit->regLocation[sReg+1].fpLowReg;
        if ((highReg & 1) == 0) {
            // High reg is even - fail.
            return res;
        }
        // Is the low reg of the pair free?
        RegisterInfo* p = getRegInfo(cUnit, highReg-1);
        if (p->inUse || p->isTemp) {
            // Already allocated or not preserved - fail.
            return res;
        }
        // OK - good to go.
        res = p->reg;
        p->inUse = true;
        assert((res & 1) == 0);
        cUnit->fpSpillMask |= (1 << (res & FP_REG_MASK));
        cUnit->numSpills++;
        cUnit->numFPSpills ++;
    } else {
        RegisterInfo* FPRegs = cUnit->regPool->FPRegs;
        for (int i = 0; i < cUnit->regPool->numFPRegs; i++) {
            if (!FPRegs[i].isTemp && !FPRegs[i].inUse &&
                ((FPRegs[i].reg & 0x1) == 0x0) &&
                !FPRegs[i+1].isTemp && !FPRegs[i+1].inUse &&
                ((FPRegs[i+1].reg & 0x1) == 0x1) &&
                (FPRegs[i].reg + 1) == FPRegs[i+1].reg) {
                res = FPRegs[i].reg;
                FPRegs[i].inUse = true;
                cUnit->fpSpillMask |= (1 << (res & FP_REG_MASK));
                FPRegs[i+1].inUse = true;
                cUnit->fpSpillMask |= (1 << ((res+1) & FP_REG_MASK));
                cUnit->numSpills += 2;
                cUnit->numFPSpills += 2;
                break;
            }
        }
    }
    if (res != -1) {
        cUnit->regLocation[sReg].fpLocation = kLocPhysReg;
        cUnit->regLocation[sReg].fpLowReg = res;
        cUnit->regLocation[sReg].home = true;
        cUnit->regLocation[sReg+1].fpLocation = kLocPhysReg;
        cUnit->regLocation[sReg+1].fpLowReg = res + 1;
        cUnit->regLocation[sReg+1].home = true;
    }
    return res;
}


/*
 * Reserve a callee-save fp register.   If this register can be used
 * as the first of a double, attempt to allocate an even pair of fp
 * single regs (but if can't still attempt to allocate a single, preferring
 * first to allocate an odd register.
 */
extern int oatAllocPreservedFPReg(CompilationUnit* cUnit, int sReg,
                                  bool doubleStart)
{
    int res = -1;
    if (doubleStart) {
        res = allocPreservedDouble(cUnit, sReg);
    } else {
    }
    if (res == -1) {
        res = allocPreservedSingle(cUnit, sReg, false /* try odd # */);
    }
    if (res == -1)
        res = allocPreservedSingle(cUnit, sReg, true /* try even # */);
    return res;
}

static int allocTempBody(CompilationUnit* cUnit, RegisterInfo* p, int numRegs,
                         int* nextTemp, bool required)
{
    int i;
    int next = *nextTemp;
    for (i=0; i< numRegs; i++) {
        if (next >= numRegs)
            next = 0;
        if (p[next].isTemp && !p[next].inUse && !p[next].live) {
            oatClobber(cUnit, p[next].reg);
            p[next].inUse = true;
            p[next].pair = false;
            *nextTemp = next + 1;
            return p[next].reg;
        }
        next++;
    }
    next = *nextTemp;
    for (i=0; i< numRegs; i++) {
        if (next >= numRegs)
            next = 0;
        if (p[next].isTemp && !p[next].inUse) {
            oatClobber(cUnit, p[next].reg);
            p[next].inUse = true;
            p[next].pair = false;
            *nextTemp = next + 1;
            return p[next].reg;
        }
        next++;
    }
    if (required) {
        dumpRegPool(cUnit->regPool->coreRegs,
                    cUnit->regPool->numCoreRegs);
        LOG(FATAL) << "No free temp registers";
    }
    return -1;  // No register available
}

//REDO: too many assumptions.
extern int oatAllocTempDouble(CompilationUnit* cUnit)
{
    RegisterInfo* p = cUnit->regPool->FPRegs;
    int numRegs = cUnit->regPool->numFPRegs;
    int next = cUnit->regPool->nextFPReg;
    int i;

    for (i=0; i < numRegs; i+=2) {
        /* Cleanup - not all targets need aligned regs */
        if (next & 1)
            next++;
        if (next >= numRegs)
            next = 0;
        if ((p[next].isTemp && !p[next].inUse && !p[next].live) &&
            (p[next+1].isTemp && !p[next+1].inUse && !p[next+1].live)) {
            oatClobber(cUnit, p[next].reg);
            oatClobber(cUnit, p[next+1].reg);
            p[next].inUse = true;
            p[next+1].inUse = true;
            assert((p[next].reg+1) == p[next+1].reg);
            assert((p[next].reg & 0x1) == 0);
            cUnit->regPool->nextFPReg += 2;
            return p[next].reg;
        }
        next += 2;
    }
    next = cUnit->regPool->nextFPReg;
    for (i=0; i < numRegs; i+=2) {
        if (next >= numRegs)
            next = 0;
        if (p[next].isTemp && !p[next].inUse && p[next+1].isTemp &&
            !p[next+1].inUse) {
            oatClobber(cUnit, p[next].reg);
            oatClobber(cUnit, p[next+1].reg);
            p[next].inUse = true;
            p[next+1].inUse = true;
            assert((p[next].reg+1) == p[next+1].reg);
            assert((p[next].reg & 0x1) == 0);
            cUnit->regPool->nextFPReg += 2;
            return p[next].reg;
        }
        next += 2;
    }
    LOG(FATAL) << "No free temp registers";
    return -1;
}

/* Return a temp if one is available, -1 otherwise */
extern int oatAllocFreeTemp(CompilationUnit* cUnit)
{
    return allocTempBody(cUnit, cUnit->regPool->coreRegs,
                         cUnit->regPool->numCoreRegs,
                         &cUnit->regPool->nextCoreReg, true);
}

extern int oatAllocTemp(CompilationUnit* cUnit)
{
    return allocTempBody(cUnit, cUnit->regPool->coreRegs,
                         cUnit->regPool->numCoreRegs,
                         &cUnit->regPool->nextCoreReg, true);
}

extern int oatAllocTempFloat(CompilationUnit* cUnit)
{
    return allocTempBody(cUnit, cUnit->regPool->FPRegs,
                         cUnit->regPool->numFPRegs,
                         &cUnit->regPool->nextFPReg, true);
}

static RegisterInfo* allocLiveBody(RegisterInfo* p, int numRegs, int sReg)
{
    int i;
    if (sReg == -1)
        return NULL;
    for (i=0; i < numRegs; i++) {
        if (p[i].live && (p[i].sReg == sReg)) {
            if (p[i].isTemp)
                p[i].inUse = true;
            return &p[i];
        }
    }
    return NULL;
}

static RegisterInfo* allocLive(CompilationUnit* cUnit, int sReg,
                               int regClass)
{
    RegisterInfo* res = NULL;
    switch(regClass) {
        case kAnyReg:
            res = allocLiveBody(cUnit->regPool->FPRegs,
                                cUnit->regPool->numFPRegs, sReg);
            if (res)
                break;
            /* Intentional fallthrough */
        case kCoreReg:
            res = allocLiveBody(cUnit->regPool->coreRegs,
                                cUnit->regPool->numCoreRegs, sReg);
            break;
        case kFPReg:
            res = allocLiveBody(cUnit->regPool->FPRegs,
                                cUnit->regPool->numFPRegs, sReg);
            break;
        default:
            LOG(FATAL) << "Invalid register type";
    }
    return res;
}

extern void oatFreeTemp(CompilationUnit* cUnit, int reg)
{
    RegisterInfo* p = cUnit->regPool->coreRegs;
    int numRegs = cUnit->regPool->numCoreRegs;
    int i;
    for (i=0; i< numRegs; i++) {
        if (p[i].reg == reg) {
            if (p[i].isTemp) {
                p[i].inUse = false;
            }
            p[i].pair = false;
            return;
        }
    }
    p = cUnit->regPool->FPRegs;
    numRegs = cUnit->regPool->numFPRegs;
    for (i=0; i< numRegs; i++) {
        if (p[i].reg == reg) {
            if (p[i].isTemp) {
                p[i].inUse = false;
            }
            p[i].pair = false;
            return;
        }
    }
    LOG(FATAL) << "Tried to free a non-existant temp: r" << reg;
}

extern RegisterInfo* oatIsLive(CompilationUnit* cUnit, int reg)
{
    RegisterInfo* p = cUnit->regPool->coreRegs;
    int numRegs = cUnit->regPool->numCoreRegs;
    int i;
    for (i=0; i< numRegs; i++) {
        if (p[i].reg == reg) {
            return p[i].live ? &p[i] : NULL;
        }
    }
    p = cUnit->regPool->FPRegs;
    numRegs = cUnit->regPool->numFPRegs;
    for (i=0; i< numRegs; i++) {
        if (p[i].reg == reg) {
            return p[i].live ? &p[i] : NULL;
        }
    }
    return NULL;
}

extern RegisterInfo* oatIsTemp(CompilationUnit* cUnit, int reg)
{
    RegisterInfo* p = getRegInfo(cUnit, reg);
    return (p->isTemp) ? p : NULL;
}

extern bool oatIsDirty(CompilationUnit* cUnit, int reg)
{
    RegisterInfo* p = getRegInfo(cUnit, reg);
    return p->dirty;
}

/*
 * Similar to oatAllocTemp(), but forces the allocation of a specific
 * register.  No check is made to see if the register was previously
 * allocated.  Use with caution.
 */
extern void oatLockTemp(CompilationUnit* cUnit, int reg)
{
    RegisterInfo* p = cUnit->regPool->coreRegs;
    int numRegs = cUnit->regPool->numCoreRegs;
    int i;
    for (i=0; i< numRegs; i++) {
        if (p[i].reg == reg) {
            assert(p[i].isTemp);
            p[i].inUse = true;
            p[i].live = false;
            return;
        }
    }
    p = cUnit->regPool->FPRegs;
    numRegs = cUnit->regPool->numFPRegs;
    for (i=0; i< numRegs; i++) {
        if (p[i].reg == reg) {
            assert(p[i].isTemp);
            p[i].inUse = true;
            p[i].live = false;
            return;
        }
    }
    LOG(FATAL) << "Tried to lock a non-existant temp: r" << reg;
}

extern void oatResetDef(CompilationUnit* cUnit, int reg)
{
    RegisterInfo* p = getRegInfo(cUnit, reg);
    p->defStart = NULL;
    p->defEnd = NULL;
}

static void nullifyRange(CompilationUnit* cUnit, LIR *start, LIR *finish,
                         int sReg1, int sReg2)
{
    if (start && finish) {
        LIR *p;
        assert(sReg1 == sReg2);
        for (p = start; ;p = p->next) {
            ((ArmLIR *)p)->flags.isNop = true;
            if (p == finish)
                break;
        }
    }
}

/*
 * Mark the beginning and end LIR of a def sequence.  Note that
 * on entry start points to the LIR prior to the beginning of the
 * sequence.
 */
extern void oatMarkDef(CompilationUnit* cUnit, RegLocation rl,
                    LIR *start, LIR *finish)
{
    assert(!rl.wide);
    assert(start && start->next);
    assert(finish);
    RegisterInfo* p = getRegInfo(cUnit, rl.lowReg);
    p->defStart = start->next;
    p->defEnd = finish;
}

/*
 * Mark the beginning and end LIR of a def sequence.  Note that
 * on entry start points to the LIR prior to the beginning of the
 * sequence.
 */
extern void oatMarkDefWide(CompilationUnit* cUnit, RegLocation rl,
                        LIR *start, LIR *finish)
{
    assert(rl.wide);
    assert(start && start->next);
    assert(finish);
    RegisterInfo* p = getRegInfo(cUnit, rl.lowReg);
    oatResetDef(cUnit, rl.highReg);  // Only track low of pair
    p->defStart = start->next;
    p->defEnd = finish;
}

extern RegLocation oatWideToNarrow(CompilationUnit* cUnit,
                                           RegLocation rl)
{
    assert(rl.wide);
    if (rl.location == kLocPhysReg) {
        RegisterInfo* infoLo = getRegInfo(cUnit, rl.lowReg);
        RegisterInfo* infoHi = getRegInfo(cUnit, rl.highReg);
        if (infoLo->isTemp) {
            infoLo->pair = false;
            infoLo->defStart = NULL;
            infoLo->defEnd = NULL;
        }
        if (infoHi->isTemp) {
            infoHi->pair = false;
            infoHi->defStart = NULL;
            infoHi->defEnd = NULL;
        }
    }
    rl.wide = false;
    return rl;
}

extern void oatResetDefLoc(CompilationUnit* cUnit, RegLocation rl)
{
    assert(!rl.wide);
    if (!(cUnit->disableOpt & (1 << kSuppressLoads))) {
        RegisterInfo* p = getRegInfo(cUnit, rl.lowReg);
        assert(!p->pair);
        nullifyRange(cUnit, p->defStart, p->defEnd,
                     p->sReg, rl.sRegLow);
    }
    oatResetDef(cUnit, rl.lowReg);
}

extern void oatResetDefLocWide(CompilationUnit* cUnit, RegLocation rl)
{
    assert(rl.wide);
    if (!(cUnit->disableOpt & (1 << kSuppressLoads))) {
        RegisterInfo* p = getRegInfo(cUnit, rl.lowReg);
        assert(p->pair);
        nullifyRange(cUnit, p->defStart, p->defEnd,
                     p->sReg, rl.sRegLow);
    }
    oatResetDef(cUnit, rl.lowReg);
    oatResetDef(cUnit, rl.highReg);
}

extern void oatResetDefTracking(CompilationUnit* cUnit)
{
    int i;
    for (i=0; i< cUnit->regPool->numCoreRegs; i++) {
        oatResetDef(cUnit, cUnit->regPool->coreRegs[i].reg);
    }
    for (i=0; i< cUnit->regPool->numFPRegs; i++) {
        oatResetDef(cUnit, cUnit->regPool->FPRegs[i].reg);
    }
}

extern void oatClobberAllRegs(CompilationUnit* cUnit)
{
    int i;
    for (i=0; i< cUnit->regPool->numCoreRegs; i++) {
        oatClobber(cUnit, cUnit->regPool->coreRegs[i].reg);
    }
    for (i=0; i< cUnit->regPool->numFPRegs; i++) {
        oatClobber(cUnit, cUnit->regPool->FPRegs[i].reg);
    }
}

/* To be used when explicitly managing register use */
extern void oatLockCallTemps(CompilationUnit* cUnit)
{
    //TODO: Arm specific - move to target dependent code
    oatLockTemp(cUnit, r0);
    oatLockTemp(cUnit, r1);
    oatLockTemp(cUnit, r2);
    oatLockTemp(cUnit, r3);
}

/* To be used when explicitly managing register use */
extern void oatFreeCallTemps(CompilationUnit* cUnit)
{
    //TODO: Arm specific - move to target dependent code
    oatFreeTemp(cUnit, r0);
    oatFreeTemp(cUnit, r1);
    oatFreeTemp(cUnit, r2);
    oatFreeTemp(cUnit, r3);
}

// Make sure nothing is live and dirty
static void flushAllRegsBody(CompilationUnit* cUnit, RegisterInfo* info,
                             int numRegs)
{
    int i;
    for (i=0; i < numRegs; i++) {
        if (info[i].live && info[i].dirty) {
            if (info[i].pair) {
                oatFlushRegWide(cUnit, info[i].reg, info[i].partner);
            } else {
                oatFlushReg(cUnit, info[i].reg);
            }
        }
    }
}

extern void oatFlushAllRegs(CompilationUnit* cUnit)
{
    flushAllRegsBody(cUnit, cUnit->regPool->coreRegs,
                     cUnit->regPool->numCoreRegs);
    flushAllRegsBody(cUnit, cUnit->regPool->FPRegs,
                     cUnit->regPool->numFPRegs);
    oatClobberAllRegs(cUnit);
}


//TUNING: rewrite all of this reg stuff.  Probably use an attribute table
static bool regClassMatches(int regClass, int reg)
{
    if (regClass == kAnyReg) {
        return true;
    } else if (regClass == kCoreReg) {
        return !FPREG(reg);
    } else {
        return FPREG(reg);
    }
}

extern void oatMarkLive(CompilationUnit* cUnit, int reg, int sReg)
{
    RegisterInfo* info = getRegInfo(cUnit, reg);
    if ((info->reg == reg) && (info->sReg == sReg) && info->live) {
        return;  /* already live */
    } else if (sReg != INVALID_SREG) {
        oatClobberSReg(cUnit, sReg);
        if (info->isTemp) {
            info->live = true;
        }
    } else {
        /* Can't be live if no associated sReg */
        assert(info->isTemp);
        info->live = false;
    }
    info->sReg = sReg;
}

extern void oatMarkTemp(CompilationUnit* cUnit, int reg)
{
    RegisterInfo* info = getRegInfo(cUnit, reg);
    info->isTemp = true;
}

extern void oatUnmarkTemp(CompilationUnit* cUnit, int reg)
{
    RegisterInfo* info = getRegInfo(cUnit, reg);
    info->isTemp = false;
}

extern void oatMarkPair(CompilationUnit* cUnit, int lowReg, int highReg)
{
    RegisterInfo* infoLo = getRegInfo(cUnit, lowReg);
    RegisterInfo* infoHi = getRegInfo(cUnit, highReg);
    infoLo->pair = infoHi->pair = true;
    infoLo->partner = highReg;
    infoHi->partner = lowReg;
}

extern void oatMarkClean(CompilationUnit* cUnit, RegLocation loc)
{
    RegisterInfo* info = getRegInfo(cUnit, loc.lowReg);
    info->dirty = false;
    if (loc.wide) {
        info = getRegInfo(cUnit, loc.highReg);
        info->dirty = false;
    }
}

extern void oatMarkDirty(CompilationUnit* cUnit, RegLocation loc)
{
    if (loc.home) {
        // If already home, can't be dirty
        return;
    }
    RegisterInfo* info = getRegInfo(cUnit, loc.lowReg);
    info->dirty = true;
    if (loc.wide) {
        info = getRegInfo(cUnit, loc.highReg);
        info->dirty = true;
    }
}

extern void oatMarkInUse(CompilationUnit* cUnit, int reg)
{
      RegisterInfo* info = getRegInfo(cUnit, reg);
      info->inUse = true;
}

static void copyRegInfo(CompilationUnit* cUnit, int newReg, int oldReg)
{
    RegisterInfo* newInfo = getRegInfo(cUnit, newReg);
    RegisterInfo* oldInfo = getRegInfo(cUnit, oldReg);
    // Target temp status must not change
    bool isTemp = newInfo->isTemp;
    *newInfo = *oldInfo;
    // Restore target's temp status
    newInfo->isTemp = isTemp;
    newInfo->reg = newReg;
}

/*
 * Return an updated location record with current in-register status.
 * If the value lives in live temps, reflect that fact.  No code
 * is generated.  The the live value is part of an older pair,
 * clobber both low and high.
 * TUNING: clobbering both is a bit heavy-handed, but the alternative
 * is a bit complex when dealing with FP regs.  Examine code to see
 * if it's worthwhile trying to be more clever here.
 */

extern RegLocation oatUpdateLoc(CompilationUnit* cUnit, RegLocation loc)
{
    assert(!loc.wide);
    if (loc.location == kLocDalvikFrame) {
        RegisterInfo* infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
        if (infoLo) {
            if (infoLo->pair) {
                oatClobber(cUnit, infoLo->reg);
                oatClobber(cUnit, infoLo->partner);
            } else {
                loc.lowReg = infoLo->reg;
                loc.location = kLocPhysReg;
            }
        }
    }

    return loc;
}

/* see comments for updateLoc */
extern RegLocation oatUpdateLocWide(CompilationUnit* cUnit,
                                    RegLocation loc)
{
    assert(loc.wide);
    if (loc.location == kLocDalvikFrame) {
        // Are the dalvik regs already live in physical registers?
        RegisterInfo* infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
        RegisterInfo* infoHi = allocLive(cUnit,
              oatSRegHi(loc.sRegLow), kAnyReg);
        bool match = true;
        match = match && (infoLo != NULL);
        match = match && (infoHi != NULL);
        // Are they both core or both FP?
        match = match && (FPREG(infoLo->reg) == FPREG(infoHi->reg));
        // If a pair of floating point singles, are they properly aligned?
        if (match && FPREG(infoLo->reg)) {
            match &= ((infoLo->reg & 0x1) == 0);
            match &= ((infoHi->reg - infoLo->reg) == 1);
        }
        // If previously used as a pair, it is the same pair?
        if (match && (infoLo->pair || infoHi->pair)) {
            match = (infoLo->pair == infoHi->pair);
            match &= ((infoLo->reg == infoHi->partner) &&
                      (infoHi->reg == infoLo->partner));
        }
        if (match) {
            // Can reuse - update the register usage info
            loc.lowReg = infoLo->reg;
            loc.highReg = infoHi->reg;
            loc.location = kLocPhysReg;
            oatMarkPair(cUnit, loc.lowReg, loc.highReg);
            assert(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
            return loc;
        }
        // Can't easily reuse - clobber any overlaps
        if (infoLo) {
            oatClobber(cUnit, infoLo->reg);
            if (infoLo->pair)
                oatClobber(cUnit, infoLo->partner);
        }
        if (infoHi) {
            oatClobber(cUnit, infoHi->reg);
            if (infoHi->pair)
                oatClobber(cUnit, infoHi->partner);
        }
    }
    return loc;
}

static RegLocation evalLocWide(CompilationUnit* cUnit, RegLocation loc,
                               int regClass, bool update)
{
    assert(loc.wide);
    int newRegs;
    int lowReg;
    int highReg;

    loc = oatUpdateLocWide(cUnit, loc);

    /* If already in registers, we can assume proper form.  Right reg class? */
    if (loc.location == kLocPhysReg) {
        assert(FPREG(loc.lowReg) == FPREG(loc.highReg));
        assert(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
        if (!regClassMatches(regClass, loc.lowReg)) {
            /* Wrong register class.  Reallocate and copy */
            newRegs = oatAllocTypedTempPair(cUnit, loc.fp, regClass);
            lowReg = newRegs & 0xff;
            highReg = (newRegs >> 8) & 0xff;
            oatRegCopyWide(cUnit, lowReg, highReg, loc.lowReg,
                                   loc.highReg);
            copyRegInfo(cUnit, lowReg, loc.lowReg);
            copyRegInfo(cUnit, highReg, loc.highReg);
            oatClobber(cUnit, loc.lowReg);
            oatClobber(cUnit, loc.highReg);
            loc.lowReg = lowReg;
            loc.highReg = highReg;
            oatMarkPair(cUnit, loc.lowReg, loc.highReg);
            assert(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
        }
        return loc;
    }

    assert(loc.sRegLow != INVALID_SREG);
    assert(oatSRegHi(loc.sRegLow) != INVALID_SREG);

    newRegs = oatAllocTypedTempPair(cUnit, loc.fp, regClass);
    loc.lowReg = newRegs & 0xff;
    loc.highReg = (newRegs >> 8) & 0xff;

    oatMarkPair(cUnit, loc.lowReg, loc.highReg);
    if (update) {
        loc.location = kLocPhysReg;
        oatMarkLive(cUnit, loc.lowReg, loc.sRegLow);
        oatMarkLive(cUnit, loc.highReg, oatSRegHi(loc.sRegLow));
    }
    assert(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
    return loc;
}

extern RegLocation oatEvalLoc(CompilationUnit* cUnit, RegLocation loc,
                              int regClass, bool update)
{
    int newReg;

    if (loc.wide)
        return evalLocWide(cUnit, loc, regClass, update);

    loc = oatUpdateLoc(cUnit, loc);

    if (loc.location == kLocPhysReg) {
        if (!regClassMatches(regClass, loc.lowReg)) {
            /* Wrong register class.  Realloc, copy and transfer ownership */
            newReg = oatAllocTypedTemp(cUnit, loc.fp, regClass);
            oatRegCopy(cUnit, newReg, loc.lowReg);
            copyRegInfo(cUnit, newReg, loc.lowReg);
            oatClobber(cUnit, loc.lowReg);
            loc.lowReg = newReg;
        }
        return loc;
    }

    assert(loc.sRegLow != INVALID_SREG);

    newReg = oatAllocTypedTemp(cUnit, loc.fp, regClass);
    loc.lowReg = newReg;

    if (update) {
        loc.location = kLocPhysReg;
        oatMarkLive(cUnit, loc.lowReg, loc.sRegLow);
    }
    return loc;
}

extern RegLocation oatGetDest(CompilationUnit* cUnit, MIR* mir, int num)
{
    RegLocation res = cUnit->regLocation[mir->ssaRep->defs[num]];
    assert(!res.wide);
    return res;
}
extern RegLocation oatGetSrc(CompilationUnit* cUnit, MIR* mir, int num)
{
    RegLocation res = cUnit->regLocation[mir->ssaRep->uses[num]];
    assert(!res.wide);
    return res;
}
extern RegLocation oatGetRawSrc(CompilationUnit* cUnit, MIR* mir, int num)
{
    RegLocation res = cUnit->regLocation[mir->ssaRep->uses[num]];
    return res;
}
extern RegLocation oatGetDestWide(CompilationUnit* cUnit, MIR* mir,
                                  int low, int high)
{
    RegLocation res = cUnit->regLocation[mir->ssaRep->defs[low]];
    assert(res.wide);
    return res;
}

extern RegLocation oatGetSrcWide(CompilationUnit* cUnit, MIR* mir,
                                 int low, int high)
{
    RegLocation res = cUnit->regLocation[mir->ssaRep->uses[low]];
    assert(res.wide);
    return res;
}
