aboutsummaryrefslogtreecommitdiff
path: root/vm/compiler/codegen/arm/RallocUtil.c
diff options
context:
space:
mode:
authorbuzbee <buzbee@google.com>2010-09-24 15:37:12 -0700
committerbuzbee <buzbee@google.com>2010-09-24 15:41:05 -0700
commitf6789277a9d25379bf43ffc39ef091db722dd5af (patch)
treeb6d3811de686c62c4c97b5a6f8e7454a5efc6de1 /vm/compiler/codegen/arm/RallocUtil.c
parent810a051d4a6ff5da5c6aad6751bd1a091db12d48 (diff)
JIT: Source code reorganization to isolate target independent code
Much of the register utility code is target independent. Move it up a level so the x86 JIT can use it. Change-Id: Id9895a42281fd836cb1a2c942e106de94df62a9a
Diffstat (limited to 'vm/compiler/codegen/arm/RallocUtil.c')
-rw-r--r--vm/compiler/codegen/arm/RallocUtil.c1010
1 files changed, 0 insertions, 1010 deletions
diff --git a/vm/compiler/codegen/arm/RallocUtil.c b/vm/compiler/codegen/arm/RallocUtil.c
deleted file mode 100644
index ff5d16be1..000000000
--- a/vm/compiler/codegen/arm/RallocUtil.c
+++ /dev/null
@@ -1,1010 +0,0 @@
-/*
- * Copyright (C) 2009 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 "compiler/CompilerUtility.h"
-#include "compiler/CompilerIR.h"
-#include "compiler/Dataflow.h"
-#include "ArmLIR.h"
-#include "Codegen.h"
-#include "Ralloc.h"
-
-/*
- * Register usage for 16-bit Thumb systems:
- * r0-r3: Temp/argument
- * lr(r14): Temp for translations, return address for handlers
- * rGLUE(r6): Pointer to InterpState
- * rFP(r5): Dalvik frame pointer
- * r4, r7: Temp for translations
- * r8, r9, r10: Temp preserved across C calls
- * r11, ip(r12): Temp not preserved across C calls
- *
- * Register usage for 32-bit Thumb systems:
- * r0-r3: Temp/argument
- * lr(r14): Temp for translations, return address for handlers
- * rGLUE(r6): Pointer to InterpState
- * rFP(r5): Dalvik frame pointer
- * r4, r7: Temp for translations
- * r8, r9, r10 Temp preserved across C calls
- * r11, ip(r12): Temp not preserved across C calls
- * fp0-fp15: Hot temps, not preserved across C calls
- * fp16-fp31: Promotion pool
- *
- */
-
-#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 dvmCompilerResetRegPool(CompilationUnit *cUnit)
-{
- int i;
- for (i=0; i < cUnit->regPool->numCoreTemps; i++) {
- cUnit->regPool->coreTemps[i].inUse = false;
- }
- for (i=0; i < cUnit->regPool->numFPTemps; i++) {
- cUnit->regPool->FPTemps[i].inUse = false;
- }
-}
-
- /* Set up temp & preserved register pools specialized by target */
-extern void dvmCompilerInitPool(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].pair = false;
- regs[i].live = false;
- regs[i].dirty = false;
- regs[i].sReg = INVALID_SREG;
- }
-}
-
-static void dumpRegPool(RegisterInfo *p, int numRegs)
-{
- int i;
- LOGE("================================================");
- for (i=0; i < numRegs; i++ ){
- LOGE("R[%d]: U:%d, P:%d, part:%d, LV:%d, D:%d, SR:%d, ST:%x, EN:%x",
- p[i].reg, 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);
- }
- LOGE("================================================");
-}
-
-static RegisterInfo *getRegInfo(CompilationUnit *cUnit, int reg)
-{
- int numTemps = cUnit->regPool->numCoreTemps;
- RegisterInfo *p = cUnit->regPool->coreTemps;
- int i;
- for (i=0; i< numTemps; i++) {
- if (p[i].reg == reg) {
- return &p[i];
- }
- }
- p = cUnit->regPool->FPTemps;
- numTemps = cUnit->regPool->numFPTemps;
- for (i=0; i< numTemps; i++) {
- if (p[i].reg == reg) {
- return &p[i];
- }
- }
- LOGE("Tried to get info on a non-existant temp: r%d",reg);
- dvmCompilerAbort(cUnit);
- return NULL;
-}
-
-static void flushRegWide(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)) {
- info1->dirty = false;
- info2->dirty = false;
- if (dvmCompilerS2VReg(cUnit, info2->sReg) <
- dvmCompilerS2VReg(cUnit, info1->sReg))
- info1 = info2;
- dvmCompilerFlushRegWideImpl(cUnit, rFP,
- dvmCompilerS2VReg(cUnit, info1->sReg) << 2,
- info1->reg, info1->partner);
- }
-}
-
-static void flushReg(CompilationUnit *cUnit, int reg)
-{
- RegisterInfo *info = getRegInfo(cUnit, reg);
- if (info->live && info->dirty) {
- info->dirty = false;
- dvmCompilerFlushRegImpl(cUnit, rFP,
- dvmCompilerS2VReg(cUnit, info->sReg) << 2,
- reg, kWord);
- }
-}
-
-/* return true if found reg to clobber */
-static bool clobberRegBody(CompilationUnit *cUnit, RegisterInfo *p,
- int numTemps, int reg)
-{
- int i;
- for (i=0; i< numTemps; i++) {
- if (p[i].reg == reg) {
- if (p[i].live && p[i].dirty) {
- if (p[i].pair) {
- flushRegWide(cUnit, p[i].reg, p[i].partner);
- } else {
- flushReg(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, numTemps, p[i].partner);
- }
- return true;
- }
- }
- return false;
-}
-
-/* Mark a temp register as dead. Does not affect allocation state. */
-void dvmCompilerClobber(CompilationUnit *cUnit, int reg)
-{
- if (!clobberRegBody(cUnit, cUnit->regPool->coreTemps,
- cUnit->regPool->numCoreTemps, reg)) {
- clobberRegBody(cUnit, cUnit->regPool->FPTemps,
- cUnit->regPool->numFPTemps, reg);
- }
-}
-
-static void clobberSRegBody(RegisterInfo *p, int numTemps, int sReg)
-{
- int i;
- for (i=0; i< numTemps; i++) {
- if (p[i].sReg == sReg) {
- 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 dvmCompilerClobberSReg(CompilationUnit *cUnit, int sReg)
-{
- clobberSRegBody(cUnit->regPool->coreTemps, cUnit->regPool->numCoreTemps,
- sReg);
- clobberSRegBody(cUnit->regPool->FPTemps, cUnit->regPool->numFPTemps,
- sReg);
-}
-
-static int allocTempBody(CompilationUnit *cUnit, RegisterInfo *p, int numTemps,
- int *nextTemp, bool required)
-{
- int i;
- int next = *nextTemp;
- for (i=0; i< numTemps; i++) {
- if (next >= numTemps)
- next = 0;
- if (!p[next].inUse && !p[next].live) {
- dvmCompilerClobber(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< numTemps; i++) {
- if (next >= numTemps)
- next = 0;
- if (!p[next].inUse) {
- dvmCompilerClobber(cUnit, p[next].reg);
- p[next].inUse = true;
- p[next].pair = false;
- *nextTemp = next + 1;
- return p[next].reg;
- }
- next++;
- }
- if (required) {
- LOGE("No free temp registers");
- dvmCompilerAbort(cUnit);
- }
- return -1; // No register available
-}
-
-//REDO: too many assumptions.
-extern int dvmCompilerAllocTempDouble(CompilationUnit *cUnit)
-{
- RegisterInfo *p = cUnit->regPool->FPTemps;
- int numTemps = cUnit->regPool->numFPTemps;
- int next = cUnit->regPool->nextFPTemp;
- int i;
-
- for (i=0; i < numTemps; i+=2) {
- /* Cleanup - not all targets need aligned regs */
- if (next & 1)
- next++;
- if (next >= numTemps)
- next = 0;
- if ((!p[next].inUse && !p[next].live) &&
- (!p[next+1].inUse && !p[next+1].live)) {
- dvmCompilerClobber(cUnit, p[next].reg);
- dvmCompilerClobber(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->nextFPTemp += 2;
- return p[next].reg;
- }
- next += 2;
- }
- next = cUnit->regPool->nextFPTemp;
- for (i=0; i < numTemps; i+=2) {
- if (next >= numTemps)
- next = 0;
- if (!p[next].inUse && !p[next+1].inUse) {
- dvmCompilerClobber(cUnit, p[next].reg);
- dvmCompilerClobber(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->nextFPTemp += 2;
- return p[next].reg;
- }
- next += 2;
- }
- LOGE("No free temp registers");
- dvmCompilerAbort(cUnit);
- return -1;
-}
-
-/* Return a temp if one is available, -1 otherwise */
-extern int dvmCompilerAllocFreeTemp(CompilationUnit *cUnit)
-{
- return allocTempBody(cUnit, cUnit->regPool->coreTemps,
- cUnit->regPool->numCoreTemps,
- &cUnit->regPool->nextCoreTemp, true);
-}
-
-extern int dvmCompilerAllocTemp(CompilationUnit *cUnit)
-{
- return allocTempBody(cUnit, cUnit->regPool->coreTemps,
- cUnit->regPool->numCoreTemps,
- &cUnit->regPool->nextCoreTemp, true);
-}
-
-extern int dvmCompilerAllocTempFloat(CompilationUnit *cUnit)
-{
- return allocTempBody(cUnit, cUnit->regPool->FPTemps,
- cUnit->regPool->numFPTemps,
- &cUnit->regPool->nextFPTemp, true);
-}
-
-static RegisterInfo *allocLiveBody(RegisterInfo *p, int numTemps, int sReg)
-{
- int i;
- if (sReg == -1)
- return NULL;
- for (i=0; i < numTemps; i++) {
- if (p[i].live && (p[i].sReg == sReg)) {
- 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->FPTemps,
- cUnit->regPool->numFPTemps, sReg);
- if (res)
- break;
- /* Intentional fallthrough */
- case kCoreReg:
- res = allocLiveBody(cUnit->regPool->coreTemps,
- cUnit->regPool->numCoreTemps, sReg);
- break;
- case kFPReg:
- res = allocLiveBody(cUnit->regPool->FPTemps,
- cUnit->regPool->numFPTemps, sReg);
- break;
- default:
- LOGE("Invalid register type");
- dvmCompilerAbort(cUnit);
- }
- return res;
-}
-
-extern void dvmCompilerFreeTemp(CompilationUnit *cUnit, int reg)
-{
- RegisterInfo *p = cUnit->regPool->coreTemps;
- int numTemps = cUnit->regPool->numCoreTemps;
- int i;
- for (i=0; i< numTemps; i++) {
- if (p[i].reg == reg) {
- p[i].inUse = false;
- p[i].pair = false;
- return;
- }
- }
- p = cUnit->regPool->FPTemps;
- numTemps = cUnit->regPool->numFPTemps;
- for (i=0; i< numTemps; i++) {
- if (p[i].reg == reg) {
- p[i].inUse = false;
- p[i].pair = false;
- return;
- }
- }
- LOGE("Tried to free a non-existant temp: r%d",reg);
- dvmCompilerAbort(cUnit);
-}
-
-/*
- * FIXME - this needs to also check the preserved pool once we start
- * start using preserved registers.
- */
-extern RegisterInfo *dvmCompilerIsLive(CompilationUnit *cUnit, int reg)
-{
- RegisterInfo *p = cUnit->regPool->coreTemps;
- int numTemps = cUnit->regPool->numCoreTemps;
- int i;
- for (i=0; i< numTemps; i++) {
- if (p[i].reg == reg) {
- return p[i].live ? &p[i] : NULL;
- }
- }
- p = cUnit->regPool->FPTemps;
- numTemps = cUnit->regPool->numFPTemps;
- for (i=0; i< numTemps; i++) {
- if (p[i].reg == reg) {
- return p[i].live ? &p[i] : NULL;
- }
- }
- return NULL;
-}
-
-extern RegisterInfo *dvmCompilerIsTemp(CompilationUnit *cUnit, int reg)
-{
- RegisterInfo *p = cUnit->regPool->coreTemps;
- int numTemps = cUnit->regPool->numCoreTemps;
- int i;
- for (i=0; i< numTemps; i++) {
- if (p[i].reg == reg) {
- return &p[i];
- }
- }
- p = cUnit->regPool->FPTemps;
- numTemps = cUnit->regPool->numFPTemps;
- for (i=0; i< numTemps; i++) {
- if (p[i].reg == reg) {
- return &p[i];
- }
- }
- return NULL;
-}
-
-/*
- * Similar to dvmCompilerAllocTemp(), 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 dvmCompilerLockTemp(CompilationUnit *cUnit, int reg)
-{
- RegisterInfo *p = cUnit->regPool->coreTemps;
- int numTemps = cUnit->regPool->numCoreTemps;
- int i;
- for (i=0; i< numTemps; i++) {
- if (p[i].reg == reg) {
- p[i].inUse = true;
- p[i].live = false;
- return;
- }
- }
- p = cUnit->regPool->FPTemps;
- numTemps = cUnit->regPool->numFPTemps;
- for (i=0; i< numTemps; i++) {
- if (p[i].reg == reg) {
- p[i].inUse = true;
- p[i].live = false;
- return;
- }
- }
- LOGE("Tried to lock a non-existant temp: r%d",reg);
- dvmCompilerAbort(cUnit);
-}
-
-/* Clobber all regs that might be used by an external C call */
-extern void dvmCompilerClobberCallRegs(CompilationUnit *cUnit)
-{
- dvmCompilerClobber(cUnit, r0);
- dvmCompilerClobber(cUnit, r1);
- dvmCompilerClobber(cUnit, r2);
- dvmCompilerClobber(cUnit, r3);
- dvmCompilerClobber(cUnit, r9); // Need to do this?, be conservative
- dvmCompilerClobber(cUnit, r11);
- dvmCompilerClobber(cUnit, r12);
- dvmCompilerClobber(cUnit, rlr);
-}
-
-/* Clobber all of the temps that might be used by a handler. */
-extern void dvmCompilerClobberHandlerRegs(CompilationUnit *cUnit)
-{
- //TUNING: reduce the set of regs used by handlers. Only a few need lots.
- dvmCompilerClobberCallRegs(cUnit);
- dvmCompilerClobber(cUnit, r4PC);
- dvmCompilerClobber(cUnit, r7);
- dvmCompilerClobber(cUnit, r8);
- dvmCompilerClobber(cUnit, r9);
- dvmCompilerClobber(cUnit, r10);
-}
-
-extern void dvmCompilerResetDef(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)->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 dvmCompilerMarkDef(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 dvmCompilerMarkDefWide(CompilationUnit *cUnit, RegLocation rl,
- LIR *start, LIR *finish)
-{
- assert(rl.wide);
- assert(start && start->next);
- assert(finish);
- RegisterInfo *p = getRegInfo(cUnit, rl.lowReg);
- dvmCompilerResetDef(cUnit, rl.highReg); // Only track low of pair
- p->defStart = start->next;
- p->defEnd = finish;
-}
-
-extern RegLocation dvmCompilerWideToNarrow(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->pair) {
- dumpRegPool(cUnit->regPool->coreTemps,
- cUnit->regPool->numCoreTemps);
- assert(infoLo->pair);
- }
- if (!infoHi->pair) {
- dumpRegPool(cUnit->regPool->coreTemps,
- cUnit->regPool->numCoreTemps);
- assert(infoHi->pair);
- }
- assert(infoLo->pair);
- assert(infoHi->pair);
- assert(infoLo->partner == infoHi->reg);
- assert(infoHi->partner == infoLo->reg);
- infoLo->pair = false;
- infoHi->pair = false;
- infoLo->defStart = NULL;
- infoLo->defEnd = NULL;
- infoHi->defStart = NULL;
- infoHi->defEnd = NULL;
- }
- rl.wide = false;
- return rl;
-}
-
-extern void dvmCompilerResetDefLoc(CompilationUnit *cUnit, RegLocation rl)
-{
- assert(!rl.wide);
- if (!(gDvmJit.disableOpt & (1 << kSuppressLoads))) {
- RegisterInfo *p = getRegInfo(cUnit, rl.lowReg);
- assert(!p->pair);
- nullifyRange(cUnit, p->defStart, p->defEnd,
- p->sReg, rl.sRegLow);
- }
- dvmCompilerResetDef(cUnit, rl.lowReg);
-}
-
-extern void dvmCompilerResetDefLocWide(CompilationUnit *cUnit, RegLocation rl)
-{
- assert(rl.wide);
- if (!(gDvmJit.disableOpt & (1 << kSuppressLoads))) {
- RegisterInfo *p = getRegInfo(cUnit, rl.lowReg);
- assert(p->pair);
- nullifyRange(cUnit, p->defStart, p->defEnd,
- p->sReg, rl.sRegLow);
- }
- dvmCompilerResetDef(cUnit, rl.lowReg);
- dvmCompilerResetDef(cUnit, rl.highReg);
-}
-
-extern void dvmCompilerResetDefTracking(CompilationUnit *cUnit)
-{
- int i;
- for (i=0; i< cUnit->regPool->numCoreTemps; i++) {
- dvmCompilerResetDef(cUnit, cUnit->regPool->coreTemps[i].reg);
- }
- for (i=0; i< cUnit->regPool->numFPTemps; i++) {
- dvmCompilerResetDef(cUnit, cUnit->regPool->FPTemps[i].reg);
- }
-}
-
-extern void dvmCompilerClobberAllRegs(CompilationUnit *cUnit)
-{
- int i;
- for (i=0; i< cUnit->regPool->numCoreTemps; i++) {
- dvmCompilerClobber(cUnit, cUnit->regPool->coreTemps[i].reg);
- }
- for (i=0; i< cUnit->regPool->numFPTemps; i++) {
- dvmCompilerClobber(cUnit, cUnit->regPool->FPTemps[i].reg);
- }
-}
-
-/* To be used when explicitly managing register use */
-extern void dvmCompilerLockAllTemps(CompilationUnit *cUnit)
-{
- int i;
- for (i=0; i< cUnit->regPool->numCoreTemps; i++) {
- dvmCompilerLockTemp(cUnit, cUnit->regPool->coreTemps[i].reg);
- }
-}
-
-// 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) {
- flushRegWide(cUnit, info[i].reg, info[i].partner);
- } else {
- flushReg(cUnit, info[i].reg);
- }
- }
- }
-}
-
-extern void dvmCompilerFlushAllRegs(CompilationUnit *cUnit)
-{
- flushAllRegsBody(cUnit, cUnit->regPool->coreTemps,
- cUnit->regPool->numCoreTemps);
- flushAllRegsBody(cUnit, cUnit->regPool->FPTemps,
- cUnit->regPool->numFPTemps);
- dvmCompilerClobberAllRegs(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 dvmCompilerMarkLive(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) {
- dvmCompilerClobberSReg(cUnit, sReg);
- info->live = true;
- } else {
- /* Can't be live if no associated sReg */
- info->live = false;
- }
- info->sReg = sReg;
-}
-
-extern void dvmCompilerMarkPair(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 dvmCompilerMarkClean(CompilationUnit *cUnit, int reg)
-{
- RegisterInfo *info = getRegInfo(cUnit, reg);
- info->dirty = false;
-}
-
-extern void dvmCompilerMarkDirty(CompilationUnit *cUnit, int reg)
-{
- RegisterInfo *info = getRegInfo(cUnit, reg);
- info->dirty = true;
-}
-
-extern void dvmCompilerMarkInUse(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);
- *newInfo = *oldInfo;
- 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 dvmCompilerUpdateLoc(CompilationUnit *cUnit, RegLocation loc)
-{
- assert(!loc.wide);
- if (loc.location == kLocDalvikFrame) {
- RegisterInfo *infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
- if (infoLo) {
- if (infoLo->pair) {
- dvmCompilerClobber(cUnit, infoLo->reg);
- dvmCompilerClobber(cUnit, infoLo->partner);
- } else {
- loc.lowReg = infoLo->reg;
- loc.location = kLocPhysReg;
- }
- }
- }
-
- return loc;
-}
-
-/* see comments for updateLoc */
-extern RegLocation dvmCompilerUpdateLocWide(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,
- dvmCompilerSRegHi(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;
- dvmCompilerMarkPair(cUnit, loc.lowReg, loc.highReg);
- assert(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
- return loc;
- }
- // Can't easily reuse - clobber any overlaps
- if (infoLo) {
- dvmCompilerClobber(cUnit, infoLo->reg);
- if (infoLo->pair)
- dvmCompilerClobber(cUnit, infoLo->partner);
- }
- if (infoHi) {
- dvmCompilerClobber(cUnit, infoHi->reg);
- if (infoHi->pair)
- dvmCompilerClobber(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 = dvmCompilerUpdateLocWide(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 = dvmCompilerAllocTypedTempPair(cUnit, loc.fp, regClass);
- lowReg = newRegs & 0xff;
- highReg = (newRegs >> 8) & 0xff;
- dvmCompilerRegCopyWide(cUnit, lowReg, highReg, loc.lowReg,
- loc.highReg);
- copyRegInfo(cUnit, lowReg, loc.lowReg);
- copyRegInfo(cUnit, highReg, loc.highReg);
- dvmCompilerClobber(cUnit, loc.lowReg);
- dvmCompilerClobber(cUnit, loc.highReg);
- loc.lowReg = lowReg;
- loc.highReg = highReg;
- dvmCompilerMarkPair(cUnit, loc.lowReg, loc.highReg);
- assert(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
- }
- return loc;
- }
-
- assert((loc.location != kLocRetval) || (loc.sRegLow == INVALID_SREG));
- assert((loc.location != kLocRetval) ||
- (dvmCompilerSRegHi(loc.sRegLow) == INVALID_SREG));
-
- newRegs = dvmCompilerAllocTypedTempPair(cUnit, loc.fp, regClass);
- loc.lowReg = newRegs & 0xff;
- loc.highReg = (newRegs >> 8) & 0xff;
-
- dvmCompilerMarkPair(cUnit, loc.lowReg, loc.highReg);
- if (update) {
- loc.location = kLocPhysReg;
- dvmCompilerMarkLive(cUnit, loc.lowReg, loc.sRegLow);
- dvmCompilerMarkLive(cUnit, loc.highReg, dvmCompilerSRegHi(loc.sRegLow));
- }
- assert(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
- return loc;
-}
-
-extern RegLocation dvmCompilerEvalLoc(CompilationUnit *cUnit, RegLocation loc,
- int regClass, bool update)
-{
- int newReg;
- if (loc.wide)
- return evalLocWide(cUnit, loc, regClass, update);
- loc = dvmCompilerUpdateLoc(cUnit, loc);
-
- if (loc.location == kLocPhysReg) {
- if (!regClassMatches(regClass, loc.lowReg)) {
- /* Wrong register class. Realloc, copy and transfer ownership */
- newReg = dvmCompilerAllocTypedTemp(cUnit, loc.fp, regClass);
- dvmCompilerRegCopy(cUnit, newReg, loc.lowReg);
- copyRegInfo(cUnit, newReg, loc.lowReg);
- dvmCompilerClobber(cUnit, loc.lowReg);
- loc.lowReg = newReg;
- }
- return loc;
- }
-
- assert((loc.location != kLocRetval) || (loc.sRegLow == INVALID_SREG));
-
- newReg = dvmCompilerAllocTypedTemp(cUnit, loc.fp, regClass);
- loc.lowReg = newReg;
-
- if (update) {
- loc.location = kLocPhysReg;
- dvmCompilerMarkLive(cUnit, loc.lowReg, loc.sRegLow);
- }
- return loc;
-}
-
-static inline int getDestSSAName(MIR *mir, int num)
-{
- assert(mir->ssaRep->numDefs > num);
- return mir->ssaRep->defs[num];
-}
-
-// Get the LocRecord associated with an SSA name use.
-extern RegLocation dvmCompilerGetSrc(CompilationUnit *cUnit, MIR *mir, int num)
-{
- RegLocation loc = cUnit->regLocation[
- SREG(cUnit, dvmCompilerSSASrc(mir, num))];
- loc.fp = cUnit->regLocation[dvmCompilerSSASrc(mir, num)].fp;
- loc.wide = false;
- return loc;
-}
-
-// Get the LocRecord associated with an SSA name def.
-extern RegLocation dvmCompilerGetDest(CompilationUnit *cUnit, MIR *mir,
- int num)
-{
- RegLocation loc = cUnit->regLocation[SREG(cUnit, getDestSSAName(mir, num))];
- loc.fp = cUnit->regLocation[getDestSSAName(mir, num)].fp;
- loc.wide = false;
- return loc;
-}
-
-static RegLocation getLocWide(CompilationUnit *cUnit, MIR *mir,
- int low, int high, bool isSrc)
-{
- RegLocation lowLoc;
- RegLocation highLoc;
- /* Copy loc record for low word and patch in data from high word */
- if (isSrc) {
- lowLoc = dvmCompilerGetSrc(cUnit, mir, low);
- highLoc = dvmCompilerGetSrc(cUnit, mir, high);
- } else {
- lowLoc = dvmCompilerGetDest(cUnit, mir, low);
- highLoc = dvmCompilerGetDest(cUnit, mir, high);
- }
- /* Avoid this case by either promoting both or neither. */
- assert(lowLoc.location == highLoc.location);
- if (lowLoc.location == kLocPhysReg) {
- /* This case shouldn't happen if we've named correctly */
- assert(lowLoc.fp == highLoc.fp);
- }
- lowLoc.wide = true;
- lowLoc.highReg = highLoc.lowReg;
- return lowLoc;
-}
-
-extern RegLocation dvmCompilerGetDestWide(CompilationUnit *cUnit, MIR *mir,
- int low, int high)
-{
- return getLocWide(cUnit, mir, low, high, false);
-}
-
-extern RegLocation dvmCompilerGetSrcWide(CompilationUnit *cUnit, MIR *mir,
- int low, int high)
-{
- return getLocWide(cUnit, mir, low, high, true);
-}
-
-extern RegLocation dvmCompilerGetReturnWide(CompilationUnit *cUnit)
-{
- RegLocation res = LOC_C_RETURN_WIDE;
- dvmCompilerClobber(cUnit, r0);
- dvmCompilerClobber(cUnit, r1);
- dvmCompilerMarkInUse(cUnit, r0);
- dvmCompilerMarkInUse(cUnit, r1);
- dvmCompilerMarkPair(cUnit, res.lowReg, res.highReg);
- return res;
-}
-
-extern RegLocation dvmCompilerGetReturnWideAlt(CompilationUnit *cUnit)
-{
- RegLocation res = LOC_C_RETURN_WIDE;
- res.lowReg = r2;
- res.highReg = r3;
- dvmCompilerClobber(cUnit, r2);
- dvmCompilerClobber(cUnit, r3);
- dvmCompilerMarkInUse(cUnit, r2);
- dvmCompilerMarkInUse(cUnit, r3);
- dvmCompilerMarkPair(cUnit, res.lowReg, res.highReg);
- return res;
-}
-
-extern RegLocation dvmCompilerGetReturn(CompilationUnit *cUnit)
-{
- RegLocation res = LOC_C_RETURN;
- dvmCompilerClobber(cUnit, r0);
- dvmCompilerMarkInUse(cUnit, r0);
- return res;
-}
-
-extern RegLocation dvmCompilerGetReturnAlt(CompilationUnit *cUnit)
-{
- RegLocation res = LOC_C_RETURN;
- res.lowReg = r1;
- dvmCompilerClobber(cUnit, r1);
- dvmCompilerMarkInUse(cUnit, r1);
- return res;
-}
-
-/* Kill the corresponding bit in the null-checked register list */
-extern void dvmCompilerKillNullCheckedLoc(CompilationUnit *cUnit,
- RegLocation loc)
-{
- if (loc.location != kLocRetval) {
- assert(loc.sRegLow != INVALID_SREG);
- dvmClearBit(cUnit->regPool->nullCheckedRegs, loc.sRegLow);
- if (loc.wide) {
- assert(dvmCompilerSRegHi(loc.sRegLow) != INVALID_SREG);
- dvmClearBit(cUnit->regPool->nullCheckedRegs,
- dvmCompilerSRegHi(loc.sRegLow));
- }
- }
-}
-
-extern void dvmCompilerFlushRegWideForV5TEVFP(CompilationUnit *cUnit,
- int reg1, int reg2)
-{
- flushRegWide(cUnit, reg1, reg2);
-}
-
-extern void dvmCompilerFlushRegForV5TEVFP(CompilationUnit *cUnit, int reg)
-{
- flushReg(cUnit, reg);
-}