2 * Copyright (C) 2009 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 * This file contains register alloction support and is intended to be
21 * Codegen-$(TARGET_ARCH_VARIANT).c
25 #include "compiler/CompilerUtility.h"
26 #include "compiler/CompilerIR.h"
27 #include "compiler/Dataflow.h"
33 * Register usage for 16-bit Thumb systems:
34 * r0-r3: Temp/argument
35 * lr(r14): Temp for translations, return address for handlers
36 * rGLUE(r6): Pointer to InterpState
37 * rFP(r5): Dalvik frame pointer
38 * r4, r7: Temp for translations
39 * r8, r9, r10: Temp preserved across C calls
40 * r11, ip(r12): Temp not preserved across C calls
42 * Register usage for 32-bit Thumb systems:
43 * r0-r3: Temp/argument
44 * lr(r14): Temp for translations, return address for handlers
45 * rGLUE(r6): Pointer to InterpState
46 * rFP(r5): Dalvik frame pointer
47 * r4, r7: Temp for translations
48 * r8, r9, r10 Temp preserved across C calls
49 * r11, ip(r12): Temp not preserved across C calls
50 * fp0-fp15: Hot temps, not preserved across C calls
51 * fp16-fp31: Promotion pool
55 #define SREG(c, s) ((c)->regLocation[(s)].sRegLow)
57 * Get the "real" sreg number associated with an sReg slot. In general,
58 * sReg values passed through codegen are the SSA names created by
59 * dataflow analysis and refer to slot numbers in the cUnit->regLocation
60 * array. However, renaming is accomplished by simply replacing RegLocation
61 * entries in the cUnit->reglocation[] array. Therefore, when location
62 * records for operands are first created, we need to ask the locRecord
63 * identified by the dataflow pass what it's new name is.
67 * Free all allocated temps in the temp pools. Note that this does
68 * not affect the "liveness" of a temp register, which will stay
69 * live until it is either explicitly killed or reallocated.
71 extern void dvmCompilerResetRegPool(CompilationUnit *cUnit)
74 for (i=0; i < cUnit->regPool->numCoreTemps; i++) {
75 cUnit->regPool->coreTemps[i].inUse = false;
77 for (i=0; i < cUnit->regPool->numFPTemps; i++) {
78 cUnit->regPool->FPTemps[i].inUse = false;
82 /* Set up temp & preserved register pools specialized by target */
83 extern void dvmCompilerInitPool(RegisterInfo *regs, int *regNums, int num)
86 for (i=0; i < num; i++) {
87 regs[i].reg = regNums[i];
88 regs[i].inUse = false;
91 regs[i].dirty = false;
92 regs[i].sReg = INVALID_SREG;
96 static void dumpRegPool(RegisterInfo *p, int numRegs)
99 LOGE("================================================");
100 for (i=0; i < numRegs; i++ ){
101 LOGE("R[%d]: U:%d, P:%d, part:%d, LV:%d, D:%d, SR:%d, ST:%x, EN:%x",
102 p[i].reg, p[i].inUse, p[i].pair, p[i].partner, p[i].live,
103 p[i].dirty, p[i].sReg,(int)p[i].defStart, (int)p[i].defEnd);
105 LOGE("================================================");
108 static RegisterInfo *getRegInfo(CompilationUnit *cUnit, int reg)
110 int numTemps = cUnit->regPool->numCoreTemps;
111 RegisterInfo *p = cUnit->regPool->coreTemps;
113 for (i=0; i< numTemps; i++) {
114 if (p[i].reg == reg) {
118 p = cUnit->regPool->FPTemps;
119 numTemps = cUnit->regPool->numFPTemps;
120 for (i=0; i< numTemps; i++) {
121 if (p[i].reg == reg) {
125 LOGE("Tried to get info on a non-existant temp: r%d",reg);
126 dvmCompilerAbort(cUnit);
130 static void flushRegWide(CompilationUnit *cUnit, int reg1, int reg2)
132 RegisterInfo *info1 = getRegInfo(cUnit, reg1);
133 RegisterInfo *info2 = getRegInfo(cUnit, reg2);
134 assert(info1 && info2 && info1->pair && info2->pair &&
135 (info1->partner == info2->reg) &&
136 (info2->partner == info1->reg));
137 if ((info1->live && info1->dirty) || (info2->live && info2->dirty)) {
138 info1->dirty = false;
139 info2->dirty = false;
140 if (dvmCompilerS2VReg(cUnit, info2->sReg) <
141 dvmCompilerS2VReg(cUnit, info1->sReg))
143 dvmCompilerFlushRegWideImpl(cUnit, rFP,
144 dvmCompilerS2VReg(cUnit, info1->sReg) << 2,
145 info1->reg, info1->partner);
149 static void flushReg(CompilationUnit *cUnit, int reg)
151 RegisterInfo *info = getRegInfo(cUnit, reg);
152 if (info->live && info->dirty) {
154 dvmCompilerFlushRegImpl(cUnit, rFP,
155 dvmCompilerS2VReg(cUnit, info->sReg) << 2,
160 /* return true if found reg to clobber */
161 static bool clobberRegBody(CompilationUnit *cUnit, RegisterInfo *p,
162 int numTemps, int reg)
165 for (i=0; i< numTemps; i++) {
166 if (p[i].reg == reg) {
167 if (p[i].live && p[i].dirty) {
169 flushRegWide(cUnit, p[i].reg, p[i].partner);
171 flushReg(cUnit, p[i].reg);
175 p[i].sReg = INVALID_SREG;
176 p[i].defStart = NULL;
180 /* partners should be in same pool */
181 clobberRegBody(cUnit, p, numTemps, p[i].partner);
189 /* Mark a temp register as dead. Does not affect allocation state. */
190 void dvmCompilerClobber(CompilationUnit *cUnit, int reg)
192 if (!clobberRegBody(cUnit, cUnit->regPool->coreTemps,
193 cUnit->regPool->numCoreTemps, reg)) {
194 clobberRegBody(cUnit, cUnit->regPool->FPTemps,
195 cUnit->regPool->numFPTemps, reg);
199 static void clobberSRegBody(RegisterInfo *p, int numTemps, int sReg)
202 for (i=0; i< numTemps; i++) {
203 if (p[i].sReg == sReg) {
205 p[i].defStart = NULL;
211 /* Clobber any temp associated with an sReg. Could be in either class */
212 extern void dvmCompilerClobberSReg(CompilationUnit *cUnit, int sReg)
214 clobberSRegBody(cUnit->regPool->coreTemps, cUnit->regPool->numCoreTemps,
216 clobberSRegBody(cUnit->regPool->FPTemps, cUnit->regPool->numFPTemps,
220 static int allocTempBody(CompilationUnit *cUnit, RegisterInfo *p, int numTemps,
221 int *nextTemp, bool required)
224 int next = *nextTemp;
225 for (i=0; i< numTemps; i++) {
226 if (next >= numTemps)
228 if (!p[next].inUse && !p[next].live) {
229 dvmCompilerClobber(cUnit, p[next].reg);
230 p[next].inUse = true;
231 p[next].pair = false;
232 *nextTemp = next + 1;
238 for (i=0; i< numTemps; i++) {
239 if (next >= numTemps)
241 if (!p[next].inUse) {
242 dvmCompilerClobber(cUnit, p[next].reg);
243 p[next].inUse = true;
244 p[next].pair = false;
245 *nextTemp = next + 1;
251 LOGE("No free temp registers");
252 dvmCompilerAbort(cUnit);
254 return -1; // No register available
257 //REDO: too many assumptions.
258 extern int dvmCompilerAllocTempDouble(CompilationUnit *cUnit)
260 RegisterInfo *p = cUnit->regPool->FPTemps;
261 int numTemps = cUnit->regPool->numFPTemps;
262 int next = cUnit->regPool->nextFPTemp;
265 for (i=0; i < numTemps; i+=2) {
266 /* Cleanup - not all targets need aligned regs */
269 if (next >= numTemps)
271 if ((!p[next].inUse && !p[next].live) &&
272 (!p[next+1].inUse && !p[next+1].live)) {
273 dvmCompilerClobber(cUnit, p[next].reg);
274 dvmCompilerClobber(cUnit, p[next+1].reg);
275 p[next].inUse = true;
276 p[next+1].inUse = true;
277 assert((p[next].reg+1) == p[next+1].reg);
278 assert((p[next].reg & 0x1) == 0);
279 cUnit->regPool->nextFPTemp += 2;
284 next = cUnit->regPool->nextFPTemp;
285 for (i=0; i < numTemps; i+=2) {
286 if (next >= numTemps)
288 if (!p[next].inUse && !p[next+1].inUse) {
289 dvmCompilerClobber(cUnit, p[next].reg);
290 dvmCompilerClobber(cUnit, p[next+1].reg);
291 p[next].inUse = true;
292 p[next+1].inUse = true;
293 assert((p[next].reg+1) == p[next+1].reg);
294 assert((p[next].reg & 0x1) == 0);
295 cUnit->regPool->nextFPTemp += 2;
300 LOGE("No free temp registers");
301 dvmCompilerAbort(cUnit);
305 /* Return a temp if one is available, -1 otherwise */
306 extern int dvmCompilerAllocFreeTemp(CompilationUnit *cUnit)
308 return allocTempBody(cUnit, cUnit->regPool->coreTemps,
309 cUnit->regPool->numCoreTemps,
310 &cUnit->regPool->nextCoreTemp, true);
313 extern int dvmCompilerAllocTemp(CompilationUnit *cUnit)
315 return allocTempBody(cUnit, cUnit->regPool->coreTemps,
316 cUnit->regPool->numCoreTemps,
317 &cUnit->regPool->nextCoreTemp, true);
320 extern int dvmCompilerAllocTempFloat(CompilationUnit *cUnit)
322 return allocTempBody(cUnit, cUnit->regPool->FPTemps,
323 cUnit->regPool->numFPTemps,
324 &cUnit->regPool->nextFPTemp, true);
327 static RegisterInfo *allocLiveBody(RegisterInfo *p, int numTemps, int sReg)
332 for (i=0; i < numTemps; i++) {
333 if (p[i].live && (p[i].sReg == sReg)) {
341 static RegisterInfo *allocLive(CompilationUnit *cUnit, int sReg,
344 RegisterInfo *res = NULL;
347 res = allocLiveBody(cUnit->regPool->FPTemps,
348 cUnit->regPool->numFPTemps, sReg);
351 /* Intentional fallthrough */
353 res = allocLiveBody(cUnit->regPool->coreTemps,
354 cUnit->regPool->numCoreTemps, sReg);
357 res = allocLiveBody(cUnit->regPool->FPTemps,
358 cUnit->regPool->numFPTemps, sReg);
361 LOGE("Invalid register type");
362 dvmCompilerAbort(cUnit);
367 extern void dvmCompilerFreeTemp(CompilationUnit *cUnit, int reg)
369 RegisterInfo *p = cUnit->regPool->coreTemps;
370 int numTemps = cUnit->regPool->numCoreTemps;
372 for (i=0; i< numTemps; i++) {
373 if (p[i].reg == reg) {
379 p = cUnit->regPool->FPTemps;
380 numTemps = cUnit->regPool->numFPTemps;
381 for (i=0; i< numTemps; i++) {
382 if (p[i].reg == reg) {
388 LOGE("Tried to free a non-existant temp: r%d",reg);
389 dvmCompilerAbort(cUnit);
393 * FIXME - this needs to also check the preserved pool once we start
394 * start using preserved registers.
396 extern RegisterInfo *dvmCompilerIsLive(CompilationUnit *cUnit, int reg)
398 RegisterInfo *p = cUnit->regPool->coreTemps;
399 int numTemps = cUnit->regPool->numCoreTemps;
401 for (i=0; i< numTemps; i++) {
402 if (p[i].reg == reg) {
403 return p[i].live ? &p[i] : NULL;
406 p = cUnit->regPool->FPTemps;
407 numTemps = cUnit->regPool->numFPTemps;
408 for (i=0; i< numTemps; i++) {
409 if (p[i].reg == reg) {
410 return p[i].live ? &p[i] : NULL;
416 extern RegisterInfo *dvmCompilerIsTemp(CompilationUnit *cUnit, int reg)
418 RegisterInfo *p = cUnit->regPool->coreTemps;
419 int numTemps = cUnit->regPool->numCoreTemps;
421 for (i=0; i< numTemps; i++) {
422 if (p[i].reg == reg) {
426 p = cUnit->regPool->FPTemps;
427 numTemps = cUnit->regPool->numFPTemps;
428 for (i=0; i< numTemps; i++) {
429 if (p[i].reg == reg) {
437 * Similar to dvmCompilerAllocTemp(), but forces the allocation of a specific
438 * register. No check is made to see if the register was previously
439 * allocated. Use with caution.
441 extern void dvmCompilerLockTemp(CompilationUnit *cUnit, int reg)
443 RegisterInfo *p = cUnit->regPool->coreTemps;
444 int numTemps = cUnit->regPool->numCoreTemps;
446 for (i=0; i< numTemps; i++) {
447 if (p[i].reg == reg) {
453 p = cUnit->regPool->FPTemps;
454 numTemps = cUnit->regPool->numFPTemps;
455 for (i=0; i< numTemps; i++) {
456 if (p[i].reg == reg) {
462 LOGE("Tried to lock a non-existant temp: r%d",reg);
463 dvmCompilerAbort(cUnit);
466 static void lockArgRegs(CompilationUnit *cUnit)
468 dvmCompilerLockTemp(cUnit, r0);
469 dvmCompilerLockTemp(cUnit, r1);
470 dvmCompilerLockTemp(cUnit, r2);
471 dvmCompilerLockTemp(cUnit, r3);
474 /* Clobber all regs that might be used by an external C call */
475 extern void dvmCompilerClobberCallRegs(CompilationUnit *cUnit)
477 dvmCompilerClobber(cUnit, r0);
478 dvmCompilerClobber(cUnit, r1);
479 dvmCompilerClobber(cUnit, r2);
480 dvmCompilerClobber(cUnit, r3);
481 dvmCompilerClobber(cUnit, r9); // Need to do this?, be conservative
482 dvmCompilerClobber(cUnit, r11);
483 dvmCompilerClobber(cUnit, r12);
484 dvmCompilerClobber(cUnit, rlr);
487 /* Clobber all of the temps that might be used by a handler. */
488 extern void dvmCompilerClobberHandlerRegs(CompilationUnit *cUnit)
490 //TUNING: reduce the set of regs used by handlers. Only a few need lots.
491 dvmCompilerClobberCallRegs(cUnit);
492 dvmCompilerClobber(cUnit, r4PC);
493 dvmCompilerClobber(cUnit, r7);
494 dvmCompilerClobber(cUnit, r8);
495 dvmCompilerClobber(cUnit, r9);
496 dvmCompilerClobber(cUnit, r10);
499 extern void dvmCompilerResetDef(CompilationUnit *cUnit, int reg)
501 RegisterInfo *p = getRegInfo(cUnit, reg);
506 static void nullifyRange(CompilationUnit *cUnit, LIR *start, LIR *finish,
507 int sReg1, int sReg2)
509 if (start && finish) {
511 assert(sReg1 == sReg2);
512 for (p = start; ;p = p->next) {
513 ((ArmLIR *)p)->isNop = true;
521 * Mark the beginning and end LIR of a def sequence. Note that
522 * on entry start points to the LIR prior to the beginning of the
525 extern void dvmCompilerMarkDef(CompilationUnit *cUnit, RegLocation rl,
526 LIR *start, LIR *finish)
529 assert(start && start->next);
531 RegisterInfo *p = getRegInfo(cUnit, rl.lowReg);
532 p->defStart = start->next;
537 * Mark the beginning and end LIR of a def sequence. Note that
538 * on entry start points to the LIR prior to the beginning of the
541 extern void dvmCompilerMarkDefWide(CompilationUnit *cUnit, RegLocation rl,
542 LIR *start, LIR *finish)
545 assert(start && start->next);
547 RegisterInfo *p = getRegInfo(cUnit, rl.lowReg);
548 dvmCompilerResetDef(cUnit, rl.highReg); // Only track low of pair
549 p->defStart = start->next;
553 extern RegLocation dvmCompilerWideToNarrow(CompilationUnit *cUnit,
557 if (rl.location == kLocPhysReg) {
558 RegisterInfo *infoLo = getRegInfo(cUnit, rl.lowReg);
559 RegisterInfo *infoHi = getRegInfo(cUnit, rl.highReg);
561 dumpRegPool(cUnit->regPool->coreTemps,
562 cUnit->regPool->numCoreTemps);
563 assert(infoLo->pair);
566 dumpRegPool(cUnit->regPool->coreTemps,
567 cUnit->regPool->numCoreTemps);
568 assert(infoHi->pair);
570 assert(infoLo->pair);
571 assert(infoHi->pair);
572 assert(infoLo->partner == infoHi->reg);
573 assert(infoHi->partner == infoLo->reg);
574 infoLo->pair = false;
575 infoHi->pair = false;
576 infoLo->defStart = NULL;
577 infoLo->defEnd = NULL;
578 infoHi->defStart = NULL;
579 infoHi->defEnd = NULL;
585 extern void dvmCompilerResetDefLoc(CompilationUnit *cUnit, RegLocation rl)
588 if (!(gDvmJit.disableOpt & (1 << kSuppressLoads))) {
589 RegisterInfo *p = getRegInfo(cUnit, rl.lowReg);
591 nullifyRange(cUnit, p->defStart, p->defEnd,
592 p->sReg, rl.sRegLow);
594 dvmCompilerResetDef(cUnit, rl.lowReg);
597 extern void dvmCompilerResetDefLocWide(CompilationUnit *cUnit, RegLocation rl)
600 if (!(gDvmJit.disableOpt & (1 << kSuppressLoads))) {
601 RegisterInfo *p = getRegInfo(cUnit, rl.lowReg);
603 nullifyRange(cUnit, p->defStart, p->defEnd,
604 p->sReg, rl.sRegLow);
606 dvmCompilerResetDef(cUnit, rl.lowReg);
607 dvmCompilerResetDef(cUnit, rl.highReg);
610 extern void dvmCompilerResetDefTracking(CompilationUnit *cUnit)
613 for (i=0; i< cUnit->regPool->numCoreTemps; i++) {
614 dvmCompilerResetDef(cUnit, cUnit->regPool->coreTemps[i].reg);
616 for (i=0; i< cUnit->regPool->numFPTemps; i++) {
617 dvmCompilerResetDef(cUnit, cUnit->regPool->FPTemps[i].reg);
621 extern void dvmCompilerClobberAllRegs(CompilationUnit *cUnit)
624 for (i=0; i< cUnit->regPool->numCoreTemps; i++) {
625 dvmCompilerClobber(cUnit, cUnit->regPool->coreTemps[i].reg);
627 for (i=0; i< cUnit->regPool->numFPTemps; i++) {
628 dvmCompilerClobber(cUnit, cUnit->regPool->FPTemps[i].reg);
632 /* To be used when explicitly managing register use */
633 extern void dvmCompilerLockAllTemps(CompilationUnit *cUnit)
636 for (i=0; i< cUnit->regPool->numCoreTemps; i++) {
637 dvmCompilerLockTemp(cUnit, cUnit->regPool->coreTemps[i].reg);
641 // Make sure nothing is live and dirty
642 static void flushAllRegsBody(CompilationUnit *cUnit, RegisterInfo *info,
646 for (i=0; i < numRegs; i++) {
647 if (info[i].live && info[i].dirty) {
649 flushRegWide(cUnit, info[i].reg, info[i].partner);
651 flushReg(cUnit, info[i].reg);
657 extern void dvmCompilerFlushAllRegs(CompilationUnit *cUnit)
659 flushAllRegsBody(cUnit, cUnit->regPool->coreTemps,
660 cUnit->regPool->numCoreTemps);
661 flushAllRegsBody(cUnit, cUnit->regPool->FPTemps,
662 cUnit->regPool->numFPTemps);
663 dvmCompilerClobberAllRegs(cUnit);
667 //TUNING: rewrite all of this reg stuff. Probably use an attribute table
668 static bool regClassMatches(int regClass, int reg)
670 if (regClass == kAnyReg) {
672 } else if (regClass == kCoreReg) {
679 extern void dvmCompilerMarkLive(CompilationUnit *cUnit, int reg, int sReg)
681 RegisterInfo *info = getRegInfo(cUnit, reg);
682 if ((info->reg == reg) && (info->sReg == sReg) && info->live) {
683 return; /* already live */
684 } else if (sReg != INVALID_SREG) {
685 dvmCompilerClobberSReg(cUnit, sReg);
688 /* Can't be live if no associated sReg */
694 extern void dvmCompilerMarkPair(CompilationUnit *cUnit, int lowReg, int highReg)
696 RegisterInfo *infoLo = getRegInfo(cUnit, lowReg);
697 RegisterInfo *infoHi = getRegInfo(cUnit, highReg);
698 infoLo->pair = infoHi->pair = true;
699 infoLo->partner = highReg;
700 infoHi->partner = lowReg;
703 static void markRegSingle(CompilationUnit *cUnit, int reg)
705 RegisterInfo *info = getRegInfo(cUnit, reg);
709 extern void dvmCompilerMarkClean(CompilationUnit *cUnit, int reg)
711 RegisterInfo *info = getRegInfo(cUnit, reg);
715 extern void dvmCompilerMarkDirty(CompilationUnit *cUnit, int reg)
717 RegisterInfo *info = getRegInfo(cUnit, reg);
721 extern void dvmCompilerMarkInUse(CompilationUnit *cUnit, int reg)
723 RegisterInfo *info = getRegInfo(cUnit, reg);
727 /* Return true if live & dirty */
728 static bool isDirty(CompilationUnit *cUnit, int reg)
730 RegisterInfo *info = getRegInfo(cUnit, reg);
731 return (info && info->live && info->dirty);
734 void copyRegInfo(CompilationUnit *cUnit, int newReg, int oldReg)
736 RegisterInfo *newInfo = getRegInfo(cUnit, newReg);
737 RegisterInfo *oldInfo = getRegInfo(cUnit, oldReg);
739 newInfo->reg = newReg;
743 * Return an updated location record with current in-register status.
744 * If the value lives in live temps, reflect that fact. No code
745 * is generated. The the live value is part of an older pair,
746 * clobber both low and high.
747 * TUNING: clobbering both is a bit heavy-handed, but the alternative
748 * is a bit complex when dealing with FP regs. Examine code to see
749 * if it's worthwhile trying to be more clever here.
751 extern RegLocation dvmCompilerUpdateLoc(CompilationUnit *cUnit, RegLocation loc)
754 if (loc.location == kLocDalvikFrame) {
755 RegisterInfo *infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
758 dvmCompilerClobber(cUnit, infoLo->reg);
759 dvmCompilerClobber(cUnit, infoLo->partner);
761 loc.lowReg = infoLo->reg;
762 loc.location = kLocPhysReg;
770 /* see comments for updateLoc */
771 extern RegLocation dvmCompilerUpdateLocWide(CompilationUnit *cUnit,
775 if (loc.location == kLocDalvikFrame) {
776 // Are the dalvik regs already live in physical registers?
777 RegisterInfo *infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
778 RegisterInfo *infoHi = allocLive(cUnit,
779 dvmCompilerSRegHi(loc.sRegLow), kAnyReg);
781 match = match && (infoLo != NULL);
782 match = match && (infoHi != NULL);
783 // Are they both core or both FP?
784 match = match && (FPREG(infoLo->reg) == FPREG(infoHi->reg));
785 // If a pair of floating point singles, are they properly aligned?
786 if (match && FPREG(infoLo->reg)) {
787 match &= ((infoLo->reg & 0x1) == 0);
788 match &= ((infoHi->reg - infoLo->reg) == 1);
790 // If previously used as a pair, it is the same pair?
791 if (match && (infoLo->pair || infoHi->pair)) {
792 match = (infoLo->pair == infoHi->pair);
793 match &= ((infoLo->reg == infoHi->partner) &&
794 (infoHi->reg == infoLo->partner));
797 // Can reuse - update the register usage info
798 loc.lowReg = infoLo->reg;
799 loc.highReg = infoHi->reg;
800 loc.location = kLocPhysReg;
801 dvmCompilerMarkPair(cUnit, loc.lowReg, loc.highReg);
802 assert(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
805 // Can't easily reuse - clobber any overlaps
807 dvmCompilerClobber(cUnit, infoLo->reg);
809 dvmCompilerClobber(cUnit, infoLo->partner);
812 dvmCompilerClobber(cUnit, infoHi->reg);
814 dvmCompilerClobber(cUnit, infoHi->partner);
821 static RegLocation evalLocWide(CompilationUnit *cUnit, RegLocation loc,
822 int regClass, bool update)
829 loc = dvmCompilerUpdateLocWide(cUnit, loc);
831 /* If already in registers, we can assume proper form. Right reg class? */
832 if (loc.location == kLocPhysReg) {
833 assert(FPREG(loc.lowReg) == FPREG(loc.highReg));
834 assert(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
835 if (!regClassMatches(regClass, loc.lowReg)) {
836 /* Wrong register class. Reallocate and copy */
837 newRegs = dvmCompilerAllocTypedTempPair(cUnit, loc.fp, regClass);
838 lowReg = newRegs & 0xff;
839 highReg = (newRegs >> 8) & 0xff;
840 dvmCompilerRegCopyWide(cUnit, lowReg, highReg, loc.lowReg,
842 copyRegInfo(cUnit, lowReg, loc.lowReg);
843 copyRegInfo(cUnit, highReg, loc.highReg);
844 dvmCompilerClobber(cUnit, loc.lowReg);
845 dvmCompilerClobber(cUnit, loc.highReg);
847 loc.highReg = highReg;
848 dvmCompilerMarkPair(cUnit, loc.lowReg, loc.highReg);
849 assert(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
854 assert((loc.location != kLocRetval) || (loc.sRegLow == INVALID_SREG));
855 assert((loc.location != kLocRetval) ||
856 (dvmCompilerSRegHi(loc.sRegLow) == INVALID_SREG));
858 newRegs = dvmCompilerAllocTypedTempPair(cUnit, loc.fp, regClass);
859 loc.lowReg = newRegs & 0xff;
860 loc.highReg = (newRegs >> 8) & 0xff;
862 dvmCompilerMarkPair(cUnit, loc.lowReg, loc.highReg);
864 loc.location = kLocPhysReg;
865 dvmCompilerMarkLive(cUnit, loc.lowReg, loc.sRegLow);
866 dvmCompilerMarkLive(cUnit, loc.highReg, dvmCompilerSRegHi(loc.sRegLow));
868 assert(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
872 extern RegLocation dvmCompilerEvalLoc(CompilationUnit *cUnit, RegLocation loc,
873 int regClass, bool update)
875 RegisterInfo *infoLo = NULL;
878 return evalLocWide(cUnit, loc, regClass, update);
879 loc = dvmCompilerUpdateLoc(cUnit, loc);
881 if (loc.location == kLocPhysReg) {
882 if (!regClassMatches(regClass, loc.lowReg)) {
883 /* Wrong register class. Realloc, copy and transfer ownership */
884 newReg = dvmCompilerAllocTypedTemp(cUnit, loc.fp, regClass);
885 dvmCompilerRegCopy(cUnit, newReg, loc.lowReg);
886 copyRegInfo(cUnit, newReg, loc.lowReg);
887 dvmCompilerClobber(cUnit, loc.lowReg);
893 assert((loc.location != kLocRetval) || (loc.sRegLow == INVALID_SREG));
895 newReg = dvmCompilerAllocTypedTemp(cUnit, loc.fp, regClass);
899 loc.location = kLocPhysReg;
900 dvmCompilerMarkLive(cUnit, loc.lowReg, loc.sRegLow);
905 static inline int getDestSSAName(MIR *mir, int num)
907 assert(mir->ssaRep->numDefs > num);
908 return mir->ssaRep->defs[num];
911 // Get the LocRecord associated with an SSA name use.
912 extern RegLocation dvmCompilerGetSrc(CompilationUnit *cUnit, MIR *mir, int num)
914 RegLocation loc = cUnit->regLocation[
915 SREG(cUnit, dvmCompilerSSASrc(mir, num))];
916 loc.fp = cUnit->regLocation[dvmCompilerSSASrc(mir, num)].fp;
921 // Get the LocRecord associated with an SSA name def.
922 extern RegLocation dvmCompilerGetDest(CompilationUnit *cUnit, MIR *mir,
925 RegLocation loc = cUnit->regLocation[SREG(cUnit, getDestSSAName(mir, num))];
926 loc.fp = cUnit->regLocation[getDestSSAName(mir, num)].fp;
931 static RegLocation getLocWide(CompilationUnit *cUnit, MIR *mir,
932 int low, int high, bool isSrc)
936 /* Copy loc record for low word and patch in data from high word */
938 lowLoc = dvmCompilerGetSrc(cUnit, mir, low);
939 highLoc = dvmCompilerGetSrc(cUnit, mir, high);
941 lowLoc = dvmCompilerGetDest(cUnit, mir, low);
942 highLoc = dvmCompilerGetDest(cUnit, mir, high);
944 /* Avoid this case by either promoting both or neither. */
945 assert(lowLoc.location == highLoc.location);
946 if (lowLoc.location == kLocPhysReg) {
947 /* This case shouldn't happen if we've named correctly */
948 assert(lowLoc.fp == highLoc.fp);
951 lowLoc.highReg = highLoc.lowReg;
955 extern RegLocation dvmCompilerGetDestWide(CompilationUnit *cUnit, MIR *mir,
958 return getLocWide(cUnit, mir, low, high, false);
961 extern RegLocation dvmCompilerGetSrcWide(CompilationUnit *cUnit, MIR *mir,
964 return getLocWide(cUnit, mir, low, high, true);
967 extern RegLocation dvmCompilerGetReturnWide(CompilationUnit *cUnit)
969 RegLocation res = LOC_C_RETURN_WIDE;
970 dvmCompilerClobber(cUnit, r0);
971 dvmCompilerClobber(cUnit, r1);
972 dvmCompilerMarkInUse(cUnit, r0);
973 dvmCompilerMarkInUse(cUnit, r1);
974 dvmCompilerMarkPair(cUnit, res.lowReg, res.highReg);
978 extern RegLocation dvmCompilerGetReturnWideAlt(CompilationUnit *cUnit)
980 RegLocation res = LOC_C_RETURN_WIDE;
983 dvmCompilerClobber(cUnit, r2);
984 dvmCompilerClobber(cUnit, r3);
985 dvmCompilerMarkInUse(cUnit, r2);
986 dvmCompilerMarkInUse(cUnit, r3);
987 dvmCompilerMarkPair(cUnit, res.lowReg, res.highReg);
991 extern RegLocation dvmCompilerGetReturn(CompilationUnit *cUnit)
993 RegLocation res = LOC_C_RETURN;
994 dvmCompilerClobber(cUnit, r0);
995 dvmCompilerMarkInUse(cUnit, r0);
999 extern RegLocation dvmCompilerGetReturnAlt(CompilationUnit *cUnit)
1001 RegLocation res = LOC_C_RETURN;
1003 dvmCompilerClobber(cUnit, r1);
1004 dvmCompilerMarkInUse(cUnit, r1);
1008 /* Kill the corresponding bit in the null-checked register list */
1009 extern void dvmCompilerKillNullCheckedLoc(CompilationUnit *cUnit,
1012 if (loc.location != kLocRetval) {
1013 assert(loc.sRegLow != INVALID_SREG);
1014 dvmClearBit(cUnit->regPool->nullCheckedRegs, loc.sRegLow);
1016 assert(dvmCompilerSRegHi(loc.sRegLow) != INVALID_SREG);
1017 dvmClearBit(cUnit->regPool->nullCheckedRegs,
1018 dvmCompilerSRegHi(loc.sRegLow));
1023 extern void dvmCompilerFlushRegWideForV5TEVFP(CompilationUnit *cUnit,
1026 flushRegWide(cUnit, reg1, reg2);
1029 extern void dvmCompilerFlushRegForV5TEVFP(CompilationUnit *cUnit, int reg)
1031 flushReg(cUnit, reg);