Home | History | Annotate | Download | only in mips
      1 /*
      2  * Copyright (C) 2009 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 /*
     18  * This file contains register alloction support and is intended to be
     19  * included by:
     20  *
     21  *        Codegen-$(TARGET_ARCH_VARIANT).c
     22  *
     23  */
     24 
     25 #include "compiler/CompilerUtility.h"
     26 #include "compiler/CompilerIR.h"
     27 #include "compiler/Dataflow.h"
     28 #include "MipsLIR.h"
     29 #include "Codegen.h"
     30 #include "Ralloc.h"
     31 
     32 #define SREG(c, s) ((c)->regLocation[(s)].sRegLow)
     33 /*
     34  * Get the "real" sreg number associated with an sReg slot.  In general,
     35  * sReg values passed through codegen are the SSA names created by
     36  * dataflow analysis and refer to slot numbers in the cUnit->regLocation
     37  * array.  However, renaming is accomplished by simply replacing RegLocation
     38  * entries in the cUnit->reglocation[] array.  Therefore, when location
     39  * records for operands are first created, we need to ask the locRecord
     40  * identified by the dataflow pass what it's new name is.
     41  */
     42 
     43 /*
     44  * Free all allocated temps in the temp pools.  Note that this does
     45  * not affect the "liveness" of a temp register, which will stay
     46  * live until it is either explicitly killed or reallocated.
     47  */
     48 extern void dvmCompilerResetRegPool(CompilationUnit *cUnit)
     49 {
     50     int i;
     51     for (i=0; i < cUnit->regPool->numCoreTemps; i++) {
     52         cUnit->regPool->coreTemps[i].inUse = false;
     53     }
     54     for (i=0; i < cUnit->regPool->numFPTemps; i++) {
     55         cUnit->regPool->FPTemps[i].inUse = false;
     56     }
     57 }
     58 
     59  /* Set up temp & preserved register pools specialized by target */
     60 extern void dvmCompilerInitPool(RegisterInfo *regs, int *regNums, int num)
     61 {
     62     int i;
     63     for (i=0; i < num; i++) {
     64         regs[i].reg = regNums[i];
     65         regs[i].inUse = false;
     66         regs[i].pair = false;
     67         regs[i].live = false;
     68         regs[i].dirty = false;
     69         regs[i].sReg = INVALID_SREG;
     70     }
     71 }
     72 
     73 static void dumpRegPool(RegisterInfo *p, int numRegs)
     74 {
     75     int i;
     76     ALOGE("================================================");
     77     for (i=0; i < numRegs; i++ ){
     78         ALOGE("R[%d]: U:%d, P:%d, part:%d, LV:%d, D:%d, SR:%d, ST:%x, EN:%x",
     79            p[i].reg, p[i].inUse, p[i].pair, p[i].partner, p[i].live,
     80            p[i].dirty, p[i].sReg,(int)p[i].defStart, (int)p[i].defEnd);
     81     }
     82     ALOGE("================================================");
     83 }
     84 
     85 static RegisterInfo *getRegInfo(CompilationUnit *cUnit, int reg)
     86 {
     87     int numTemps = cUnit->regPool->numCoreTemps;
     88     RegisterInfo *p = cUnit->regPool->coreTemps;
     89     int i;
     90     for (i=0; i< numTemps; i++) {
     91         if (p[i].reg == reg) {
     92             return &p[i];
     93         }
     94     }
     95     p = cUnit->regPool->FPTemps;
     96     numTemps = cUnit->regPool->numFPTemps;
     97     for (i=0; i< numTemps; i++) {
     98         if (p[i].reg == reg) {
     99             return &p[i];
    100         }
    101     }
    102     ALOGE("Tried to get info on a non-existant temp: r%d",reg);
    103     dvmCompilerAbort(cUnit);
    104     return NULL;
    105 }
    106 
    107 static void flushRegWide(CompilationUnit *cUnit, int reg1, int reg2)
    108 {
    109     RegisterInfo *info1 = getRegInfo(cUnit, reg1);
    110     RegisterInfo *info2 = getRegInfo(cUnit, reg2);
    111     assert(info1 && info2 && info1->pair && info2->pair &&
    112            (info1->partner == info2->reg) &&
    113            (info2->partner == info1->reg));
    114     if ((info1->live && info1->dirty) || (info2->live && info2->dirty)) {
    115         info1->dirty = false;
    116         info2->dirty = false;
    117         if (dvmCompilerS2VReg(cUnit, info2->sReg) <
    118             dvmCompilerS2VReg(cUnit, info1->sReg))
    119             info1 = info2;
    120         dvmCompilerFlushRegWideImpl(cUnit, rFP,
    121                                     dvmCompilerS2VReg(cUnit, info1->sReg) << 2,
    122                                     info1->reg, info1->partner);
    123     }
    124 }
    125 
    126 static void flushReg(CompilationUnit *cUnit, int reg)
    127 {
    128     RegisterInfo *info = getRegInfo(cUnit, reg);
    129     if (info->live && info->dirty) {
    130         info->dirty = false;
    131         dvmCompilerFlushRegImpl(cUnit, rFP,
    132                                 dvmCompilerS2VReg(cUnit, info->sReg) << 2,
    133                                 reg, kWord);
    134     }
    135 }
    136 
    137 /* return true if found reg to clobber */
    138 static bool clobberRegBody(CompilationUnit *cUnit, RegisterInfo *p,
    139                            int numTemps, int reg)
    140 {
    141     int i;
    142     for (i=0; i< numTemps; i++) {
    143         if (p[i].reg == reg) {
    144             if (p[i].live && p[i].dirty) {
    145                 if (p[i].pair) {
    146                     flushRegWide(cUnit, p[i].reg, p[i].partner);
    147                 } else {
    148                     flushReg(cUnit, p[i].reg);
    149                 }
    150             }
    151             p[i].live = false;
    152             p[i].sReg = INVALID_SREG;
    153             p[i].defStart = NULL;
    154             p[i].defEnd = NULL;
    155             if (p[i].pair) {
    156                 p[i].pair = false;
    157                 /* partners should be in same pool */
    158                 clobberRegBody(cUnit, p, numTemps, p[i].partner);
    159             }
    160             return true;
    161         }
    162     }
    163     return false;
    164 }
    165 
    166 /* Mark a temp register as dead.  Does not affect allocation state. */
    167 void dvmCompilerClobber(CompilationUnit *cUnit, int reg)
    168 {
    169     if (!clobberRegBody(cUnit, cUnit->regPool->coreTemps,
    170                         cUnit->regPool->numCoreTemps, reg)) {
    171         clobberRegBody(cUnit, cUnit->regPool->FPTemps,
    172                        cUnit->regPool->numFPTemps, reg);
    173     }
    174 }
    175 
    176 static void clobberSRegBody(RegisterInfo *p, int numTemps, int sReg)
    177 {
    178     int i;
    179     for (i=0; i< numTemps; i++) {
    180         if (p[i].sReg == sReg) {
    181             p[i].live = false;
    182             p[i].defStart = NULL;
    183             p[i].defEnd = NULL;
    184         }
    185     }
    186 }
    187 
    188 /* Clobber any temp associated with an sReg.  Could be in either class */
    189 extern void dvmCompilerClobberSReg(CompilationUnit *cUnit, int sReg)
    190 {
    191     clobberSRegBody(cUnit->regPool->coreTemps, cUnit->regPool->numCoreTemps,
    192                     sReg);
    193     clobberSRegBody(cUnit->regPool->FPTemps, cUnit->regPool->numFPTemps,
    194                     sReg);
    195 }
    196 
    197 static int allocTempBody(CompilationUnit *cUnit, RegisterInfo *p, int numTemps,
    198                          int *nextTemp, bool required)
    199 {
    200     int i;
    201     int next = *nextTemp;
    202     for (i=0; i< numTemps; i++) {
    203         if (next >= numTemps)
    204             next = 0;
    205         if (!p[next].inUse && !p[next].live) {
    206             dvmCompilerClobber(cUnit, p[next].reg);
    207             p[next].inUse = true;
    208             p[next].pair = false;
    209             *nextTemp = next + 1;
    210             return p[next].reg;
    211         }
    212         next++;
    213     }
    214     next = *nextTemp;
    215     for (i=0; i< numTemps; i++) {
    216         if (next >= numTemps)
    217             next = 0;
    218         if (!p[next].inUse) {
    219             dvmCompilerClobber(cUnit, p[next].reg);
    220             p[next].inUse = true;
    221             p[next].pair = false;
    222             *nextTemp = next + 1;
    223             return p[next].reg;
    224         }
    225         next++;
    226     }
    227     if (required) {
    228         ALOGE("No free temp registers");
    229         dvmCompilerAbort(cUnit);
    230     }
    231     return -1;  // No register available
    232 }
    233 
    234 //REDO: too many assumptions.
    235 extern int dvmCompilerAllocTempDouble(CompilationUnit *cUnit)
    236 {
    237     RegisterInfo *p = cUnit->regPool->FPTemps;
    238     int numTemps = cUnit->regPool->numFPTemps;
    239     /* Cleanup - not all targets need aligned regs */
    240     int start = cUnit->regPool->nextFPTemp + (cUnit->regPool->nextFPTemp & 1);
    241     int next = start;
    242     int i;
    243 
    244     for (i=0; i < numTemps; i+=2) {
    245         if (next >= numTemps)
    246             next = 0;
    247         if ((!p[next].inUse && !p[next].live) &&
    248             (!p[next+1].inUse && !p[next+1].live)) {
    249             dvmCompilerClobber(cUnit, p[next].reg);
    250             dvmCompilerClobber(cUnit, p[next+1].reg);
    251             p[next].inUse = true;
    252             p[next+1].inUse = true;
    253             assert((p[next].reg+1) == p[next+1].reg);
    254             assert((p[next].reg & 0x1) == 0);
    255             cUnit->regPool->nextFPTemp += 2;
    256             return p[next].reg;
    257         }
    258         next += 2;
    259     }
    260     next = start;
    261     for (i=0; i < numTemps; i+=2) {
    262         if (next >= numTemps)
    263             next = 0;
    264         if (!p[next].inUse && !p[next+1].inUse) {
    265             dvmCompilerClobber(cUnit, p[next].reg);
    266             dvmCompilerClobber(cUnit, p[next+1].reg);
    267             p[next].inUse = true;
    268             p[next+1].inUse = true;
    269             assert((p[next].reg+1) == p[next+1].reg);
    270             assert((p[next].reg & 0x1) == 0);
    271             cUnit->regPool->nextFPTemp += 2;
    272             return p[next].reg;
    273         }
    274         next += 2;
    275     }
    276     ALOGE("No free temp registers");
    277     dvmCompilerAbort(cUnit);
    278     return -1;
    279 }
    280 
    281 /* Return a temp if one is available, -1 otherwise */
    282 extern int dvmCompilerAllocFreeTemp(CompilationUnit *cUnit)
    283 {
    284     return allocTempBody(cUnit, cUnit->regPool->coreTemps,
    285                          cUnit->regPool->numCoreTemps,
    286                          &cUnit->regPool->nextCoreTemp, true);
    287 }
    288 
    289 extern int dvmCompilerAllocTemp(CompilationUnit *cUnit)
    290 {
    291     return allocTempBody(cUnit, cUnit->regPool->coreTemps,
    292                          cUnit->regPool->numCoreTemps,
    293                          &cUnit->regPool->nextCoreTemp, true);
    294 }
    295 
    296 extern int dvmCompilerAllocTempFloat(CompilationUnit *cUnit)
    297 {
    298     return allocTempBody(cUnit, cUnit->regPool->FPTemps,
    299                          cUnit->regPool->numFPTemps,
    300                          &cUnit->regPool->nextFPTemp, true);
    301 }
    302 
    303 static RegisterInfo *allocLiveBody(RegisterInfo *p, int numTemps, int sReg)
    304 {
    305     int i;
    306     if (sReg == -1)
    307         return NULL;
    308     for (i=0; i < numTemps; i++) {
    309         if (p[i].live && (p[i].sReg == sReg)) {
    310             p[i].inUse = true;
    311             return &p[i];
    312         }
    313     }
    314     return NULL;
    315 }
    316 
    317 static RegisterInfo *allocLive(CompilationUnit *cUnit, int sReg,
    318                                int regClass)
    319 {
    320     RegisterInfo *res = NULL;
    321     switch(regClass) {
    322         case kAnyReg:
    323             res = allocLiveBody(cUnit->regPool->FPTemps,
    324                                 cUnit->regPool->numFPTemps, sReg);
    325             if (res)
    326                 break;
    327             /* Intentional fallthrough */
    328         case kCoreReg:
    329             res = allocLiveBody(cUnit->regPool->coreTemps,
    330                                 cUnit->regPool->numCoreTemps, sReg);
    331             break;
    332         case kFPReg:
    333             res = allocLiveBody(cUnit->regPool->FPTemps,
    334                                 cUnit->regPool->numFPTemps, sReg);
    335             break;
    336         default:
    337             ALOGE("Invalid register type");
    338             dvmCompilerAbort(cUnit);
    339     }
    340     return res;
    341 }
    342 
    343 extern void dvmCompilerFreeTemp(CompilationUnit *cUnit, int reg)
    344 {
    345     RegisterInfo *p = cUnit->regPool->coreTemps;
    346     int numTemps = cUnit->regPool->numCoreTemps;
    347     int i;
    348     for (i=0; i< numTemps; i++) {
    349         if (p[i].reg == reg) {
    350             p[i].inUse = false;
    351             p[i].pair = false;
    352             return;
    353         }
    354     }
    355     p = cUnit->regPool->FPTemps;
    356     numTemps = cUnit->regPool->numFPTemps;
    357     for (i=0; i< numTemps; i++) {
    358         if (p[i].reg == reg) {
    359             p[i].inUse = false;
    360             p[i].pair = false;
    361             return;
    362         }
    363     }
    364     ALOGE("Tried to free a non-existant temp: r%d",reg);
    365     dvmCompilerAbort(cUnit);
    366 }
    367 
    368 /*
    369  * FIXME - this needs to also check the preserved pool once we start
    370  * start using preserved registers.
    371  */
    372 extern RegisterInfo *dvmCompilerIsLive(CompilationUnit *cUnit, int reg)
    373 {
    374     RegisterInfo *p = cUnit->regPool->coreTemps;
    375     int numTemps = cUnit->regPool->numCoreTemps;
    376     int i;
    377     for (i=0; i< numTemps; i++) {
    378         if (p[i].reg == reg) {
    379             return p[i].live ? &p[i] : NULL;
    380         }
    381     }
    382     p = cUnit->regPool->FPTemps;
    383     numTemps = cUnit->regPool->numFPTemps;
    384     for (i=0; i< numTemps; i++) {
    385         if (p[i].reg == reg) {
    386             return p[i].live ? &p[i] : NULL;
    387         }
    388     }
    389     return NULL;
    390 }
    391 
    392 extern RegisterInfo *dvmCompilerIsTemp(CompilationUnit *cUnit, int reg)
    393 {
    394     RegisterInfo *p = cUnit->regPool->coreTemps;
    395     int numTemps = cUnit->regPool->numCoreTemps;
    396     int i;
    397     for (i=0; i< numTemps; i++) {
    398         if (p[i].reg == reg) {
    399             return &p[i];
    400         }
    401     }
    402     p = cUnit->regPool->FPTemps;
    403     numTemps = cUnit->regPool->numFPTemps;
    404     for (i=0; i< numTemps; i++) {
    405         if (p[i].reg == reg) {
    406             return &p[i];
    407         }
    408     }
    409     return NULL;
    410 }
    411 
    412 /*
    413  * Similar to dvmCompilerAllocTemp(), but forces the allocation of a specific
    414  * register.  No check is made to see if the register was previously
    415  * allocated.  Use with caution.
    416  */
    417 extern void dvmCompilerLockTemp(CompilationUnit *cUnit, int reg)
    418 {
    419     RegisterInfo *p = cUnit->regPool->coreTemps;
    420     int numTemps = cUnit->regPool->numCoreTemps;
    421     int i;
    422     for (i=0; i< numTemps; i++) {
    423         if (p[i].reg == reg) {
    424             p[i].inUse = true;
    425             p[i].live = false;
    426             return;
    427         }
    428     }
    429     p = cUnit->regPool->FPTemps;
    430     numTemps = cUnit->regPool->numFPTemps;
    431     for (i=0; i< numTemps; i++) {
    432         if (p[i].reg == reg) {
    433             p[i].inUse = true;
    434             p[i].live = false;
    435             return;
    436         }
    437     }
    438     ALOGE("Tried to lock a non-existant temp: r%d",reg);
    439     dvmCompilerAbort(cUnit);
    440 }
    441 
    442 /* Clobber all regs that might be used by an external C call */
    443 extern void dvmCompilerClobberCallRegs(CompilationUnit *cUnit)
    444 {
    445     dvmCompilerClobber(cUnit, r_ZERO);
    446     dvmCompilerClobber(cUnit, r_AT);
    447     dvmCompilerClobber(cUnit, r_V0);
    448     dvmCompilerClobber(cUnit, r_V1);
    449     dvmCompilerClobber(cUnit, r_A0);
    450     dvmCompilerClobber(cUnit, r_A1);
    451     dvmCompilerClobber(cUnit, r_A2);
    452     dvmCompilerClobber(cUnit, r_A3);
    453     dvmCompilerClobber(cUnit, r_T0);
    454     dvmCompilerClobber(cUnit, r_T1);
    455     dvmCompilerClobber(cUnit, r_T2);
    456     dvmCompilerClobber(cUnit, r_T3);
    457     dvmCompilerClobber(cUnit, r_T4);
    458     dvmCompilerClobber(cUnit, r_T5);
    459     dvmCompilerClobber(cUnit, r_T6);
    460     dvmCompilerClobber(cUnit, r_T7);
    461     dvmCompilerClobber(cUnit, r_T8);
    462     dvmCompilerClobber(cUnit, r_T9);
    463     dvmCompilerClobber(cUnit, r_K0);
    464     dvmCompilerClobber(cUnit, r_K1);
    465     dvmCompilerClobber(cUnit, r_GP);
    466     dvmCompilerClobber(cUnit, r_FP);
    467     dvmCompilerClobber(cUnit, r_RA);
    468     dvmCompilerClobber(cUnit, r_HI);
    469     dvmCompilerClobber(cUnit, r_LO);
    470     dvmCompilerClobber(cUnit, r_F0);
    471     dvmCompilerClobber(cUnit, r_F1);
    472     dvmCompilerClobber(cUnit, r_F2);
    473     dvmCompilerClobber(cUnit, r_F3);
    474     dvmCompilerClobber(cUnit, r_F4);
    475     dvmCompilerClobber(cUnit, r_F5);
    476     dvmCompilerClobber(cUnit, r_F6);
    477     dvmCompilerClobber(cUnit, r_F7);
    478     dvmCompilerClobber(cUnit, r_F8);
    479     dvmCompilerClobber(cUnit, r_F9);
    480     dvmCompilerClobber(cUnit, r_F10);
    481     dvmCompilerClobber(cUnit, r_F11);
    482     dvmCompilerClobber(cUnit, r_F12);
    483     dvmCompilerClobber(cUnit, r_F13);
    484     dvmCompilerClobber(cUnit, r_F14);
    485     dvmCompilerClobber(cUnit, r_F15);
    486 }
    487 
    488 /* Clobber all of the temps that might be used by a handler. */
    489 extern void dvmCompilerClobberHandlerRegs(CompilationUnit *cUnit)
    490 {
    491     //TUNING: reduce the set of regs used by handlers.  Only a few need lots.
    492     dvmCompilerClobberCallRegs(cUnit);
    493     dvmCompilerClobber(cUnit, r_S0);
    494     dvmCompilerClobber(cUnit, r_S1);
    495     dvmCompilerClobber(cUnit, r_S2);
    496     dvmCompilerClobber(cUnit, r_S3);
    497     dvmCompilerClobber(cUnit, r_S4);
    498     dvmCompilerClobber(cUnit, r_S5);
    499     dvmCompilerClobber(cUnit, r_S6);
    500     dvmCompilerClobber(cUnit, r_S7);
    501 }
    502 
    503 extern void dvmCompilerResetDef(CompilationUnit *cUnit, int reg)
    504 {
    505     RegisterInfo *p = getRegInfo(cUnit, reg);
    506     p->defStart = NULL;
    507     p->defEnd = NULL;
    508 }
    509 
    510 static void nullifyRange(CompilationUnit *cUnit, LIR *start, LIR *finish,
    511                          int sReg1, int sReg2)
    512 {
    513     if (start && finish) {
    514         LIR *p;
    515         assert(sReg1 == sReg2);
    516         for (p = start; ;p = p->next) {
    517             ((MipsLIR *)p)->flags.isNop = true;
    518             if (p == finish)
    519                 break;
    520         }
    521     }
    522 }
    523 
    524 /*
    525  * Mark the beginning and end LIR of a def sequence.  Note that
    526  * on entry start points to the LIR prior to the beginning of the
    527  * sequence.
    528  */
    529 extern void dvmCompilerMarkDef(CompilationUnit *cUnit, RegLocation rl,
    530                     LIR *start, LIR *finish)
    531 {
    532     assert(!rl.wide);
    533     assert(start && start->next);
    534     assert(finish);
    535     RegisterInfo *p = getRegInfo(cUnit, rl.lowReg);
    536     p->defStart = start->next;
    537     p->defEnd = finish;
    538 }
    539 
    540 /*
    541  * Mark the beginning and end LIR of a def sequence.  Note that
    542  * on entry start points to the LIR prior to the beginning of the
    543  * sequence.
    544  */
    545 extern void dvmCompilerMarkDefWide(CompilationUnit *cUnit, RegLocation rl,
    546                         LIR *start, LIR *finish)
    547 {
    548     assert(rl.wide);
    549     assert(start && start->next);
    550     assert(finish);
    551     RegisterInfo *p = getRegInfo(cUnit, rl.lowReg);
    552     dvmCompilerResetDef(cUnit, rl.highReg);  // Only track low of pair
    553     p->defStart = start->next;
    554     p->defEnd = finish;
    555 }
    556 
    557 extern RegLocation dvmCompilerWideToNarrow(CompilationUnit *cUnit,
    558                                            RegLocation rl)
    559 {
    560     assert(rl.wide);
    561     if (rl.location == kLocPhysReg) {
    562         RegisterInfo *infoLo = getRegInfo(cUnit, rl.lowReg);
    563         RegisterInfo *infoHi = getRegInfo(cUnit, rl.highReg);
    564         if (!infoLo->pair) {
    565             dumpRegPool(cUnit->regPool->coreTemps,
    566                         cUnit->regPool->numCoreTemps);
    567             assert(infoLo->pair);
    568         }
    569         if (!infoHi->pair) {
    570             dumpRegPool(cUnit->regPool->coreTemps,
    571                         cUnit->regPool->numCoreTemps);
    572             assert(infoHi->pair);
    573         }
    574         assert(infoLo->pair);
    575         assert(infoHi->pair);
    576         assert(infoLo->partner == infoHi->reg);
    577         assert(infoHi->partner == infoLo->reg);
    578         infoLo->pair = false;
    579         infoHi->pair = false;
    580         infoLo->defStart = NULL;
    581         infoLo->defEnd = NULL;
    582         infoHi->defStart = NULL;
    583         infoHi->defEnd = NULL;
    584     }
    585 #ifndef HAVE_LITTLE_ENDIAN
    586     else if (rl.location == kLocDalvikFrame) {
    587         rl.sRegLow = dvmCompilerSRegHi(rl.sRegLow);
    588     }
    589 #endif
    590 
    591     rl.wide = false;
    592     return rl;
    593 }
    594 
    595 extern void dvmCompilerResetDefLoc(CompilationUnit *cUnit, RegLocation rl)
    596 {
    597     assert(!rl.wide);
    598     if (!(gDvmJit.disableOpt & (1 << kSuppressLoads))) {
    599         RegisterInfo *p = getRegInfo(cUnit, rl.lowReg);
    600         assert(!p->pair);
    601         nullifyRange(cUnit, p->defStart, p->defEnd,
    602                      p->sReg, rl.sRegLow);
    603     }
    604     dvmCompilerResetDef(cUnit, rl.lowReg);
    605 }
    606 
    607 extern void dvmCompilerResetDefLocWide(CompilationUnit *cUnit, RegLocation rl)
    608 {
    609     assert(rl.wide);
    610     if (!(gDvmJit.disableOpt & (1 << kSuppressLoads))) {
    611         RegisterInfo *p = getRegInfo(cUnit, rl.lowReg);
    612         assert(p->pair);
    613         nullifyRange(cUnit, p->defStart, p->defEnd,
    614                      p->sReg, rl.sRegLow);
    615     }
    616     dvmCompilerResetDef(cUnit, rl.lowReg);
    617     dvmCompilerResetDef(cUnit, rl.highReg);
    618 }
    619 
    620 extern void dvmCompilerResetDefTracking(CompilationUnit *cUnit)
    621 {
    622     int i;
    623     for (i=0; i< cUnit->regPool->numCoreTemps; i++) {
    624         dvmCompilerResetDef(cUnit, cUnit->regPool->coreTemps[i].reg);
    625     }
    626     for (i=0; i< cUnit->regPool->numFPTemps; i++) {
    627         dvmCompilerResetDef(cUnit, cUnit->regPool->FPTemps[i].reg);
    628     }
    629 }
    630 
    631 extern void dvmCompilerClobberAllRegs(CompilationUnit *cUnit)
    632 {
    633     int i;
    634     for (i=0; i< cUnit->regPool->numCoreTemps; i++) {
    635         dvmCompilerClobber(cUnit, cUnit->regPool->coreTemps[i].reg);
    636     }
    637     for (i=0; i< cUnit->regPool->numFPTemps; i++) {
    638         dvmCompilerClobber(cUnit, cUnit->regPool->FPTemps[i].reg);
    639     }
    640 }
    641 
    642 /* To be used when explicitly managing register use */
    643 extern void dvmCompilerLockAllTemps(CompilationUnit *cUnit)
    644 {
    645     int i;
    646     for (i=0; i< cUnit->regPool->numCoreTemps; i++) {
    647         dvmCompilerLockTemp(cUnit, cUnit->regPool->coreTemps[i].reg);
    648     }
    649 }
    650 
    651 // Make sure nothing is live and dirty
    652 static void flushAllRegsBody(CompilationUnit *cUnit, RegisterInfo *info,
    653                              int numRegs)
    654 {
    655     int i;
    656     for (i=0; i < numRegs; i++) {
    657         if (info[i].live && info[i].dirty) {
    658             if (info[i].pair) {
    659                 flushRegWide(cUnit, info[i].reg, info[i].partner);
    660             } else {
    661                 flushReg(cUnit, info[i].reg);
    662             }
    663         }
    664     }
    665 }
    666 
    667 extern void dvmCompilerFlushAllRegs(CompilationUnit *cUnit)
    668 {
    669     flushAllRegsBody(cUnit, cUnit->regPool->coreTemps,
    670                      cUnit->regPool->numCoreTemps);
    671     flushAllRegsBody(cUnit, cUnit->regPool->FPTemps,
    672                      cUnit->regPool->numFPTemps);
    673     dvmCompilerClobberAllRegs(cUnit);
    674 }
    675 
    676 
    677 //TUNING: rewrite all of this reg stuff.  Probably use an attribute table
    678 static bool regClassMatches(int regClass, int reg)
    679 {
    680     if (regClass == kAnyReg) {
    681         return true;
    682     } else if (regClass == kCoreReg) {
    683         return !FPREG(reg);
    684     } else {
    685         return FPREG(reg);
    686     }
    687 }
    688 
    689 extern void dvmCompilerMarkLive(CompilationUnit *cUnit, int reg, int sReg)
    690 {
    691     RegisterInfo *info = getRegInfo(cUnit, reg);
    692     if ((info->reg == reg) && (info->sReg == sReg) && info->live) {
    693         return;  /* already live */
    694     } else if (sReg != INVALID_SREG) {
    695         dvmCompilerClobberSReg(cUnit, sReg);
    696         info->live = true;
    697     } else {
    698         /* Can't be live if no associated sReg */
    699         info->live = false;
    700     }
    701     info->sReg = sReg;
    702 }
    703 
    704 extern void dvmCompilerMarkPair(CompilationUnit *cUnit, int lowReg, int highReg)
    705 {
    706     RegisterInfo *infoLo = getRegInfo(cUnit, lowReg);
    707     RegisterInfo *infoHi = getRegInfo(cUnit, highReg);
    708     infoLo->pair = infoHi->pair = true;
    709     infoLo->partner = highReg;
    710     infoHi->partner = lowReg;
    711 }
    712 
    713 extern void dvmCompilerMarkClean(CompilationUnit *cUnit, int reg)
    714 {
    715     RegisterInfo *info = getRegInfo(cUnit, reg);
    716     info->dirty = false;
    717 }
    718 
    719 extern void dvmCompilerMarkDirty(CompilationUnit *cUnit, int reg)
    720 {
    721     RegisterInfo *info = getRegInfo(cUnit, reg);
    722     info->dirty = true;
    723 }
    724 
    725 extern void dvmCompilerMarkInUse(CompilationUnit *cUnit, int reg)
    726 {
    727       RegisterInfo *info = getRegInfo(cUnit, reg);
    728           info->inUse = true;
    729 }
    730 
    731 void copyRegInfo(CompilationUnit *cUnit, int newReg, int oldReg)
    732 {
    733     RegisterInfo *newInfo = getRegInfo(cUnit, newReg);
    734     RegisterInfo *oldInfo = getRegInfo(cUnit, oldReg);
    735     *newInfo = *oldInfo;
    736     newInfo->reg = newReg;
    737 }
    738 
    739 /*
    740  * Return an updated location record with current in-register status.
    741  * If the value lives in live temps, reflect that fact.  No code
    742  * is generated.  The the live value is part of an older pair,
    743  * clobber both low and high.
    744  * TUNING: clobbering both is a bit heavy-handed, but the alternative
    745  * is a bit complex when dealing with FP regs.  Examine code to see
    746  * if it's worthwhile trying to be more clever here.
    747  */
    748 extern RegLocation dvmCompilerUpdateLoc(CompilationUnit *cUnit, RegLocation loc)
    749 {
    750     assert(!loc.wide);
    751     if (loc.location == kLocDalvikFrame) {
    752         RegisterInfo *infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
    753         if (infoLo) {
    754             if (infoLo->pair) {
    755                 dvmCompilerClobber(cUnit, infoLo->reg);
    756                 dvmCompilerClobber(cUnit, infoLo->partner);
    757             } else {
    758                 loc.lowReg = infoLo->reg;
    759                 loc.location = kLocPhysReg;
    760             }
    761         }
    762     }
    763 
    764     return loc;
    765 }
    766 
    767 /* see comments for updateLoc */
    768 extern RegLocation dvmCompilerUpdateLocWide(CompilationUnit *cUnit,
    769                                             RegLocation loc)
    770 {
    771     assert(loc.wide);
    772     if (loc.location == kLocDalvikFrame) {
    773         // Are the dalvik regs already live in physical registers?
    774         RegisterInfo *infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
    775         RegisterInfo *infoHi = allocLive(cUnit,
    776               dvmCompilerSRegHi(loc.sRegLow), kAnyReg);
    777         bool match = true;
    778         match = match && (infoLo != NULL);
    779         match = match && (infoHi != NULL);
    780         // Are they both core or both FP?
    781         match = match && (FPREG(infoLo->reg) == FPREG(infoHi->reg));
    782         // If a pair of floating point singles, are they properly aligned?
    783         if (match && FPREG(infoLo->reg)) {
    784             match &= ((infoLo->reg & 0x1) == 0);
    785             match &= ((infoHi->reg - infoLo->reg) == 1);
    786         }
    787         // If previously used as a pair, it is the same pair?
    788         if (match && (infoLo->pair || infoHi->pair)) {
    789             match = (infoLo->pair == infoHi->pair);
    790             match &= ((infoLo->reg == infoHi->partner) &&
    791                       (infoHi->reg == infoLo->partner));
    792         }
    793         if (match) {
    794             // Can reuse - update the register usage info
    795             loc.lowReg = infoLo->reg;
    796             loc.highReg = infoHi->reg;
    797             loc.location = kLocPhysReg;
    798             dvmCompilerMarkPair(cUnit, loc.lowReg, loc.highReg);
    799             assert(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
    800             return loc;
    801         }
    802         // Can't easily reuse - clobber any overlaps
    803         if (infoLo) {
    804             dvmCompilerClobber(cUnit, infoLo->reg);
    805             if (infoLo->pair)
    806                 dvmCompilerClobber(cUnit, infoLo->partner);
    807         }
    808         if (infoHi) {
    809             dvmCompilerClobber(cUnit, infoHi->reg);
    810             if (infoHi->pair)
    811                 dvmCompilerClobber(cUnit, infoHi->partner);
    812         }
    813     }
    814 
    815     return loc;
    816 }
    817 
    818 static RegLocation evalLocWide(CompilationUnit *cUnit, RegLocation loc,
    819                                int regClass, bool update)
    820 {
    821     assert(loc.wide);
    822     int newRegs;
    823     int lowReg;
    824     int highReg;
    825 
    826     loc = dvmCompilerUpdateLocWide(cUnit, loc);
    827 
    828     /* If already in registers, we can assume proper form.  Right reg class? */
    829     if (loc.location == kLocPhysReg) {
    830         assert(FPREG(loc.lowReg) == FPREG(loc.highReg));
    831         assert(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
    832         if (!regClassMatches(regClass, loc.lowReg)) {
    833             /* Wrong register class.  Reallocate and copy */
    834             newRegs = dvmCompilerAllocTypedTempPair(cUnit, loc.fp, regClass);
    835             lowReg = newRegs & 0xff;
    836             highReg = (newRegs >> 8) & 0xff;
    837             dvmCompilerRegCopyWide(cUnit, lowReg, highReg, loc.lowReg,
    838                                    loc.highReg);
    839             copyRegInfo(cUnit, lowReg, loc.lowReg);
    840             copyRegInfo(cUnit, highReg, loc.highReg);
    841             dvmCompilerClobber(cUnit, loc.lowReg);
    842             dvmCompilerClobber(cUnit, loc.highReg);
    843             loc.lowReg = lowReg;
    844             loc.highReg = highReg;
    845             dvmCompilerMarkPair(cUnit, loc.lowReg, loc.highReg);
    846             assert(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
    847         }
    848         return loc;
    849     }
    850 
    851     assert((loc.location != kLocRetval) || (loc.sRegLow == INVALID_SREG));
    852     assert((loc.location != kLocRetval) ||
    853            (dvmCompilerSRegHi(loc.sRegLow) == INVALID_SREG));
    854 
    855     newRegs = dvmCompilerAllocTypedTempPair(cUnit, loc.fp, regClass);
    856     loc.lowReg = newRegs & 0xff;
    857     loc.highReg = (newRegs >> 8) & 0xff;
    858 
    859     dvmCompilerMarkPair(cUnit, loc.lowReg, loc.highReg);
    860     if (update) {
    861         loc.location = kLocPhysReg;
    862         dvmCompilerMarkLive(cUnit, loc.lowReg, loc.sRegLow);
    863         dvmCompilerMarkLive(cUnit, loc.highReg, dvmCompilerSRegHi(loc.sRegLow));
    864     }
    865     assert(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
    866     return loc;
    867 }
    868 
    869 extern RegLocation dvmCompilerEvalLoc(CompilationUnit *cUnit, RegLocation loc,
    870                                       int regClass, bool update)
    871 {
    872     int newReg;
    873     if (loc.wide)
    874         return evalLocWide(cUnit, loc, regClass, update);
    875     loc = dvmCompilerUpdateLoc(cUnit, loc);
    876 
    877     if (loc.location == kLocPhysReg) {
    878         if (!regClassMatches(regClass, loc.lowReg)) {
    879             /* Wrong register class.  Realloc, copy and transfer ownership */
    880             newReg = dvmCompilerAllocTypedTemp(cUnit, loc.fp, regClass);
    881             dvmCompilerRegCopy(cUnit, newReg, loc.lowReg);
    882             copyRegInfo(cUnit, newReg, loc.lowReg);
    883             dvmCompilerClobber(cUnit, loc.lowReg);
    884             loc.lowReg = newReg;
    885         }
    886         return loc;
    887     }
    888 
    889     assert((loc.location != kLocRetval) || (loc.sRegLow == INVALID_SREG));
    890 
    891     newReg = dvmCompilerAllocTypedTemp(cUnit, loc.fp, regClass);
    892     loc.lowReg = newReg;
    893 
    894     if (update) {
    895         loc.location = kLocPhysReg;
    896         dvmCompilerMarkLive(cUnit, loc.lowReg, loc.sRegLow);
    897     }
    898     return loc;
    899 }
    900 
    901 static inline int getDestSSAName(MIR *mir, int num)
    902 {
    903     assert(mir->ssaRep->numDefs > num);
    904     return mir->ssaRep->defs[num];
    905 }
    906 
    907 // Get the LocRecord associated with an SSA name use.
    908 extern RegLocation dvmCompilerGetSrc(CompilationUnit *cUnit, MIR *mir, int num)
    909 {
    910     RegLocation loc = cUnit->regLocation[
    911          SREG(cUnit, dvmCompilerSSASrc(mir, num))];
    912     loc.fp = cUnit->regLocation[dvmCompilerSSASrc(mir, num)].fp;
    913     loc.wide = false;
    914     return loc;
    915 }
    916 
    917 // Get the LocRecord associated with an SSA name def.
    918 extern RegLocation dvmCompilerGetDest(CompilationUnit *cUnit, MIR *mir,
    919                                       int num)
    920 {
    921     RegLocation loc = cUnit->regLocation[SREG(cUnit, getDestSSAName(mir, num))];
    922     loc.fp = cUnit->regLocation[getDestSSAName(mir, num)].fp;
    923     loc.wide = false;
    924     return loc;
    925 }
    926 
    927 static RegLocation getLocWide(CompilationUnit *cUnit, MIR *mir,
    928                               int low, int high, bool isSrc)
    929 {
    930     RegLocation lowLoc;
    931     RegLocation highLoc;
    932     /* Copy loc record for low word and patch in data from high word */
    933     if (isSrc) {
    934         lowLoc = dvmCompilerGetSrc(cUnit, mir, low);
    935         highLoc = dvmCompilerGetSrc(cUnit, mir, high);
    936     } else {
    937         lowLoc = dvmCompilerGetDest(cUnit, mir, low);
    938         highLoc = dvmCompilerGetDest(cUnit, mir, high);
    939     }
    940     /* Avoid this case by either promoting both or neither. */
    941     assert(lowLoc.location == highLoc.location);
    942     if (lowLoc.location == kLocPhysReg) {
    943         /* This case shouldn't happen if we've named correctly */
    944         assert(lowLoc.fp == highLoc.fp);
    945     }
    946     lowLoc.wide = true;
    947     lowLoc.highReg = highLoc.lowReg;
    948     return lowLoc;
    949 }
    950 
    951 extern RegLocation dvmCompilerGetDestWide(CompilationUnit *cUnit, MIR *mir,
    952                                           int low, int high)
    953 {
    954     return getLocWide(cUnit, mir, low, high, false);
    955 }
    956 
    957 extern RegLocation dvmCompilerGetSrcWide(CompilationUnit *cUnit, MIR *mir,
    958                                          int low, int high)
    959 {
    960     return getLocWide(cUnit, mir, low, high, true);
    961 }
    962 
    963 extern RegLocation dvmCompilerGetReturnWide(CompilationUnit *cUnit)
    964 {
    965     RegLocation res = LOC_C_RETURN_WIDE;
    966     dvmCompilerClobber(cUnit, r_V0);
    967     dvmCompilerClobber(cUnit, r_V1);
    968     dvmCompilerMarkInUse(cUnit, r_V0);
    969     dvmCompilerMarkInUse(cUnit, r_V1);
    970     dvmCompilerMarkPair(cUnit, res.lowReg, res.highReg);
    971     return res;
    972 }
    973 
    974 extern RegLocation dvmCompilerGetReturn(CompilationUnit *cUnit)
    975 {
    976     RegLocation res = LOC_C_RETURN;
    977     dvmCompilerClobber(cUnit, r_V0);
    978     dvmCompilerMarkInUse(cUnit, r_V0);
    979     return res;
    980 }
    981 
    982 extern RegLocation dvmCompilerGetReturnWideAlt(CompilationUnit *cUnit)
    983 {
    984     RegLocation res = LOC_C_RETURN_WIDE_ALT;
    985     dvmCompilerClobber(cUnit, r_F0);
    986     dvmCompilerClobber(cUnit, r_F1);
    987     dvmCompilerMarkInUse(cUnit, r_F0);
    988     dvmCompilerMarkInUse(cUnit, r_F1);
    989     dvmCompilerMarkPair(cUnit, res.lowReg, res.highReg);
    990     return res;
    991 }
    992 
    993 extern RegLocation dvmCompilerGetReturnAlt(CompilationUnit *cUnit)
    994 {
    995     RegLocation res = LOC_C_RETURN_ALT;
    996     dvmCompilerClobber(cUnit, r_F0);
    997     dvmCompilerMarkInUse(cUnit, r_F0);
    998     return res;
    999 }
   1000 
   1001 /* Kill the corresponding bit in the null-checked register list */
   1002 extern void dvmCompilerKillNullCheckedLoc(CompilationUnit *cUnit,
   1003                                           RegLocation loc)
   1004 {
   1005     if (loc.location != kLocRetval) {
   1006         assert(loc.sRegLow != INVALID_SREG);
   1007         dvmClearBit(cUnit->regPool->nullCheckedRegs, loc.sRegLow);
   1008         if (loc.wide) {
   1009             assert(dvmCompilerSRegHi(loc.sRegLow) != INVALID_SREG);
   1010             dvmClearBit(cUnit->regPool->nullCheckedRegs,
   1011                         dvmCompilerSRegHi(loc.sRegLow));
   1012         }
   1013     }
   1014 }
   1015 
   1016 extern void dvmCompilerFlushRegWideForV5TEVFP(CompilationUnit *cUnit,
   1017                                               int reg1, int reg2)
   1018 {
   1019     flushRegWide(cUnit, reg1, reg2);
   1020 }
   1021 
   1022 extern void dvmCompilerFlushRegForV5TEVFP(CompilationUnit *cUnit, int reg)
   1023 {
   1024     flushReg(cUnit, reg);
   1025 }
   1026