OSDN Git Service

Jit: Fix for 2793725 SIGSEGV in JIT code cache
[android-x86/dalvik.git] / vm / compiler / codegen / arm / RallocUtil.c
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 "ArmLIR.h"
29 #include "Codegen.h"
30 #include "Ralloc.h"
31
32 /*
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
41  *
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
52  *
53  */
54
55 #define SREG(c, s) ((c)->regLocation[(s)].sRegLow)
56 /*
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.
64  */
65
66 /*
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.
70  */
71 extern void dvmCompilerResetRegPool(CompilationUnit *cUnit)
72 {
73     int i;
74     for (i=0; i < cUnit->regPool->numCoreTemps; i++) {
75         cUnit->regPool->coreTemps[i].inUse = false;
76     }
77     for (i=0; i < cUnit->regPool->numFPTemps; i++) {
78         cUnit->regPool->FPTemps[i].inUse = false;
79     }
80 }
81
82  /* Set up temp & preserved register pools specialized by target */
83 extern void dvmCompilerInitPool(RegisterInfo *regs, int *regNums, int num)
84 {
85     int i;
86     for (i=0; i < num; i++) {
87         regs[i].reg = regNums[i];
88         regs[i].inUse = false;
89         regs[i].pair = false;
90         regs[i].live = false;
91         regs[i].dirty = false;
92         regs[i].sReg = INVALID_SREG;
93     }
94 }
95
96 static void dumpRegPool(RegisterInfo *p, int numRegs)
97 {
98     int i;
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);
104     }
105     LOGE("================================================");
106 }
107
108 static RegisterInfo *getRegInfo(CompilationUnit *cUnit, int reg)
109 {
110     int numTemps = cUnit->regPool->numCoreTemps;
111     RegisterInfo *p = cUnit->regPool->coreTemps;
112     int i;
113     for (i=0; i< numTemps; i++) {
114         if (p[i].reg == reg) {
115             return &p[i];
116         }
117     }
118     p = cUnit->regPool->FPTemps;
119     numTemps = cUnit->regPool->numFPTemps;
120     for (i=0; i< numTemps; i++) {
121         if (p[i].reg == reg) {
122             return &p[i];
123         }
124     }
125     LOGE("Tried to get info on a non-existant temp: r%d",reg);
126     dvmCompilerAbort(cUnit);
127     return NULL;
128 }
129
130 static void flushRegWide(CompilationUnit *cUnit, int reg1, int reg2)
131 {
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))
142             info1 = info2;
143         dvmCompilerFlushRegWideImpl(cUnit, rFP,
144                                     dvmCompilerS2VReg(cUnit, info1->sReg) << 2,
145                                     info1->reg, info1->partner);
146     }
147 }
148
149 static void flushReg(CompilationUnit *cUnit, int reg)
150 {
151     RegisterInfo *info = getRegInfo(cUnit, reg);
152     if (info->live && info->dirty) {
153         info->dirty = false;
154         dvmCompilerFlushRegImpl(cUnit, rFP,
155                                 dvmCompilerS2VReg(cUnit, info->sReg) << 2,
156                                 reg, kWord);
157     }
158 }
159
160 /* return true if found reg to clobber */
161 static bool clobberRegBody(CompilationUnit *cUnit, RegisterInfo *p,
162                            int numTemps, int reg)
163 {
164     int i;
165     for (i=0; i< numTemps; i++) {
166         if (p[i].reg == reg) {
167             if (p[i].live && p[i].dirty) {
168                 if (p[i].pair) {
169                     flushRegWide(cUnit, p[i].reg, p[i].partner);
170                 } else {
171                     flushReg(cUnit, p[i].reg);
172                 }
173             }
174             p[i].live = false;
175             p[i].sReg = INVALID_SREG;
176             p[i].defStart = NULL;
177             p[i].defEnd = NULL;
178             if (p[i].pair) {
179                 p[i].pair = false;
180                 /* partners should be in same pool */
181                 clobberRegBody(cUnit, p, numTemps, p[i].partner);
182             }
183             return true;
184         }
185     }
186     return false;
187 }
188
189 /* Mark a temp register as dead.  Does not affect allocation state. */
190 void dvmCompilerClobber(CompilationUnit *cUnit, int reg)
191 {
192     if (!clobberRegBody(cUnit, cUnit->regPool->coreTemps,
193                         cUnit->regPool->numCoreTemps, reg)) {
194         clobberRegBody(cUnit, cUnit->regPool->FPTemps,
195                        cUnit->regPool->numFPTemps, reg);
196     }
197 }
198
199 static void clobberSRegBody(RegisterInfo *p, int numTemps, int sReg)
200 {
201     int i;
202     for (i=0; i< numTemps; i++) {
203         if (p[i].sReg == sReg) {
204             p[i].live = false;
205             p[i].defStart = NULL;
206             p[i].defEnd = NULL;
207         }
208     }
209 }
210
211 /* Clobber any temp associated with an sReg.  Could be in either class */
212 extern void dvmCompilerClobberSReg(CompilationUnit *cUnit, int sReg)
213 {
214     clobberSRegBody(cUnit->regPool->coreTemps, cUnit->regPool->numCoreTemps,
215                     sReg);
216     clobberSRegBody(cUnit->regPool->FPTemps, cUnit->regPool->numFPTemps,
217                     sReg);
218 }
219
220 static int allocTempBody(CompilationUnit *cUnit, RegisterInfo *p, int numTemps,
221                          int *nextTemp, bool required)
222 {
223     int i;
224     int next = *nextTemp;
225     for (i=0; i< numTemps; i++) {
226         if (next >= numTemps)
227             next = 0;
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;
233             return p[next].reg;
234         }
235         next++;
236     }
237     next = *nextTemp;
238     for (i=0; i< numTemps; i++) {
239         if (next >= numTemps)
240             next = 0;
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;
246             return p[next].reg;
247         }
248         next++;
249     }
250     if (required) {
251         LOGE("No free temp registers");
252         dvmCompilerAbort(cUnit);
253     }
254     return -1;  // No register available
255 }
256
257 //REDO: too many assumptions.
258 extern int dvmCompilerAllocTempDouble(CompilationUnit *cUnit)
259 {
260     RegisterInfo *p = cUnit->regPool->FPTemps;
261     int numTemps = cUnit->regPool->numFPTemps;
262     int next = cUnit->regPool->nextFPTemp;
263     int i;
264
265     for (i=0; i < numTemps; i+=2) {
266         /* Cleanup - not all targets need aligned regs */
267         if (next & 1)
268             next++;
269         if (next >= numTemps)
270             next = 0;
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;
280             return p[next].reg;
281         }
282         next += 2;
283     }
284     next = cUnit->regPool->nextFPTemp;
285     for (i=0; i < numTemps; i+=2) {
286         if (next >= numTemps)
287             next = 0;
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;
296             return p[next].reg;
297         }
298         next += 2;
299     }
300     LOGE("No free temp registers");
301     dvmCompilerAbort(cUnit);
302     return -1;
303 }
304
305 /* Return a temp if one is available, -1 otherwise */
306 extern int dvmCompilerAllocFreeTemp(CompilationUnit *cUnit)
307 {
308     return allocTempBody(cUnit, cUnit->regPool->coreTemps,
309                          cUnit->regPool->numCoreTemps,
310                          &cUnit->regPool->nextCoreTemp, true);
311 }
312
313 extern int dvmCompilerAllocTemp(CompilationUnit *cUnit)
314 {
315     return allocTempBody(cUnit, cUnit->regPool->coreTemps,
316                          cUnit->regPool->numCoreTemps,
317                          &cUnit->regPool->nextCoreTemp, true);
318 }
319
320 extern int dvmCompilerAllocTempFloat(CompilationUnit *cUnit)
321 {
322     return allocTempBody(cUnit, cUnit->regPool->FPTemps,
323                          cUnit->regPool->numFPTemps,
324                          &cUnit->regPool->nextFPTemp, true);
325 }
326
327 static RegisterInfo *allocLiveBody(RegisterInfo *p, int numTemps, int sReg)
328 {
329     int i;
330     if (sReg == -1)
331         return NULL;
332     for (i=0; i < numTemps; i++) {
333         if (p[i].live && (p[i].sReg == sReg)) {
334             p[i].inUse = true;
335             return &p[i];
336         }
337     }
338     return NULL;
339 }
340
341 static RegisterInfo *allocLive(CompilationUnit *cUnit, int sReg,
342                                int regClass)
343 {
344     RegisterInfo *res = NULL;
345     switch(regClass) {
346         case kAnyReg:
347             res = allocLiveBody(cUnit->regPool->FPTemps,
348                                 cUnit->regPool->numFPTemps, sReg);
349             if (res)
350                 break;
351             /* Intentional fallthrough */
352         case kCoreReg:
353             res = allocLiveBody(cUnit->regPool->coreTemps,
354                                 cUnit->regPool->numCoreTemps, sReg);
355             break;
356         case kFPReg:
357             res = allocLiveBody(cUnit->regPool->FPTemps,
358                                 cUnit->regPool->numFPTemps, sReg);
359             break;
360         default:
361             LOGE("Invalid register type");
362             dvmCompilerAbort(cUnit);
363     }
364     return res;
365 }
366
367 extern void dvmCompilerFreeTemp(CompilationUnit *cUnit, int reg)
368 {
369     RegisterInfo *p = cUnit->regPool->coreTemps;
370     int numTemps = cUnit->regPool->numCoreTemps;
371     int i;
372     for (i=0; i< numTemps; i++) {
373         if (p[i].reg == reg) {
374             p[i].inUse = false;
375             p[i].pair = false;
376             return;
377         }
378     }
379     p = cUnit->regPool->FPTemps;
380     numTemps = cUnit->regPool->numFPTemps;
381     for (i=0; i< numTemps; i++) {
382         if (p[i].reg == reg) {
383             p[i].inUse = false;
384             p[i].pair = false;
385             return;
386         }
387     }
388     LOGE("Tried to free a non-existant temp: r%d",reg);
389     dvmCompilerAbort(cUnit);
390 }
391
392 /*
393  * FIXME - this needs to also check the preserved pool once we start
394  * start using preserved registers.
395  */
396 extern RegisterInfo *dvmCompilerIsLive(CompilationUnit *cUnit, int reg)
397 {
398     RegisterInfo *p = cUnit->regPool->coreTemps;
399     int numTemps = cUnit->regPool->numCoreTemps;
400     int i;
401     for (i=0; i< numTemps; i++) {
402         if (p[i].reg == reg) {
403             return p[i].live ? &p[i] : NULL;
404         }
405     }
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;
411         }
412     }
413     return NULL;
414 }
415
416 extern RegisterInfo *dvmCompilerIsTemp(CompilationUnit *cUnit, int reg)
417 {
418     RegisterInfo *p = cUnit->regPool->coreTemps;
419     int numTemps = cUnit->regPool->numCoreTemps;
420     int i;
421     for (i=0; i< numTemps; i++) {
422         if (p[i].reg == reg) {
423             return &p[i];
424         }
425     }
426     p = cUnit->regPool->FPTemps;
427     numTemps = cUnit->regPool->numFPTemps;
428     for (i=0; i< numTemps; i++) {
429         if (p[i].reg == reg) {
430             return &p[i];
431         }
432     }
433     return NULL;
434 }
435
436 /*
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.
440  */
441 extern void dvmCompilerLockTemp(CompilationUnit *cUnit, int reg)
442 {
443     RegisterInfo *p = cUnit->regPool->coreTemps;
444     int numTemps = cUnit->regPool->numCoreTemps;
445     int i;
446     for (i=0; i< numTemps; i++) {
447         if (p[i].reg == reg) {
448             p[i].inUse = true;
449             p[i].live = false;
450             return;
451         }
452     }
453     p = cUnit->regPool->FPTemps;
454     numTemps = cUnit->regPool->numFPTemps;
455     for (i=0; i< numTemps; i++) {
456         if (p[i].reg == reg) {
457             p[i].inUse = true;
458             p[i].live = false;
459             return;
460         }
461     }
462     LOGE("Tried to lock a non-existant temp: r%d",reg);
463     dvmCompilerAbort(cUnit);
464 }
465
466 static void lockArgRegs(CompilationUnit *cUnit)
467 {
468     dvmCompilerLockTemp(cUnit, r0);
469     dvmCompilerLockTemp(cUnit, r1);
470     dvmCompilerLockTemp(cUnit, r2);
471     dvmCompilerLockTemp(cUnit, r3);
472 }
473
474 /* Clobber all regs that might be used by an external C call */
475 extern void dvmCompilerClobberCallRegs(CompilationUnit *cUnit)
476 {
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);
485 }
486
487 /* Clobber all of the temps that might be used by a handler. */
488 extern void dvmCompilerClobberHandlerRegs(CompilationUnit *cUnit)
489 {
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);
497 }
498
499 extern void dvmCompilerResetDef(CompilationUnit *cUnit, int reg)
500 {
501     RegisterInfo *p = getRegInfo(cUnit, reg);
502     p->defStart = NULL;
503     p->defEnd = NULL;
504 }
505
506 static void nullifyRange(CompilationUnit *cUnit, LIR *start, LIR *finish,
507                          int sReg1, int sReg2)
508 {
509     if (start && finish) {
510         LIR *p;
511         assert(sReg1 == sReg2);
512         for (p = start; ;p = p->next) {
513             ((ArmLIR *)p)->isNop = true;
514             if (p == finish)
515                 break;
516         }
517     }
518 }
519
520 /*
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
523  * sequence.
524  */
525 extern void dvmCompilerMarkDef(CompilationUnit *cUnit, RegLocation rl,
526                     LIR *start, LIR *finish)
527 {
528     assert(!rl.wide);
529     assert(start && start->next);
530     assert(finish);
531     RegisterInfo *p = getRegInfo(cUnit, rl.lowReg);
532     p->defStart = start->next;
533     p->defEnd = finish;
534 }
535
536 /*
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
539  * sequence.
540  */
541 extern void dvmCompilerMarkDefWide(CompilationUnit *cUnit, RegLocation rl,
542                         LIR *start, LIR *finish)
543 {
544     assert(rl.wide);
545     assert(start && start->next);
546     assert(finish);
547     RegisterInfo *p = getRegInfo(cUnit, rl.lowReg);
548     dvmCompilerResetDef(cUnit, rl.highReg);  // Only track low of pair
549     p->defStart = start->next;
550     p->defEnd = finish;
551 }
552
553 extern RegLocation dvmCompilerWideToNarrow(CompilationUnit *cUnit,
554                                            RegLocation rl)
555 {
556     assert(rl.wide);
557     if (rl.location == kLocPhysReg) {
558         RegisterInfo *infoLo = getRegInfo(cUnit, rl.lowReg);
559         RegisterInfo *infoHi = getRegInfo(cUnit, rl.highReg);
560         if (!infoLo->pair) {
561             dumpRegPool(cUnit->regPool->coreTemps,
562                         cUnit->regPool->numCoreTemps);
563             assert(infoLo->pair);
564         }
565         if (!infoHi->pair) {
566             dumpRegPool(cUnit->regPool->coreTemps,
567                         cUnit->regPool->numCoreTemps);
568             assert(infoHi->pair);
569         }
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;
580     }
581     rl.wide = false;
582     return rl;
583 }
584
585 extern void dvmCompilerResetDefLoc(CompilationUnit *cUnit, RegLocation rl)
586 {
587     assert(!rl.wide);
588     if (!(gDvmJit.disableOpt & (1 << kSuppressLoads))) {
589         RegisterInfo *p = getRegInfo(cUnit, rl.lowReg);
590         assert(!p->pair);
591         nullifyRange(cUnit, p->defStart, p->defEnd,
592                      p->sReg, rl.sRegLow);
593     }
594     dvmCompilerResetDef(cUnit, rl.lowReg);
595 }
596
597 extern void dvmCompilerResetDefLocWide(CompilationUnit *cUnit, RegLocation rl)
598 {
599     assert(rl.wide);
600     if (!(gDvmJit.disableOpt & (1 << kSuppressLoads))) {
601         RegisterInfo *p = getRegInfo(cUnit, rl.lowReg);
602         assert(p->pair);
603         nullifyRange(cUnit, p->defStart, p->defEnd,
604                      p->sReg, rl.sRegLow);
605     }
606     dvmCompilerResetDef(cUnit, rl.lowReg);
607     dvmCompilerResetDef(cUnit, rl.highReg);
608 }
609
610 extern void dvmCompilerResetDefTracking(CompilationUnit *cUnit)
611 {
612     int i;
613     for (i=0; i< cUnit->regPool->numCoreTemps; i++) {
614         dvmCompilerResetDef(cUnit, cUnit->regPool->coreTemps[i].reg);
615     }
616     for (i=0; i< cUnit->regPool->numFPTemps; i++) {
617         dvmCompilerResetDef(cUnit, cUnit->regPool->FPTemps[i].reg);
618     }
619 }
620
621 extern void dvmCompilerClobberAllRegs(CompilationUnit *cUnit)
622 {
623     int i;
624     for (i=0; i< cUnit->regPool->numCoreTemps; i++) {
625         dvmCompilerClobber(cUnit, cUnit->regPool->coreTemps[i].reg);
626     }
627     for (i=0; i< cUnit->regPool->numFPTemps; i++) {
628         dvmCompilerClobber(cUnit, cUnit->regPool->FPTemps[i].reg);
629     }
630 }
631
632 /* To be used when explicitly managing register use */
633 extern void dvmCompilerLockAllTemps(CompilationUnit *cUnit)
634 {
635     int i;
636     for (i=0; i< cUnit->regPool->numCoreTemps; i++) {
637         dvmCompilerLockTemp(cUnit, cUnit->regPool->coreTemps[i].reg);
638     }
639 }
640
641 // Make sure nothing is live and dirty
642 static void flushAllRegsBody(CompilationUnit *cUnit, RegisterInfo *info,
643                              int numRegs)
644 {
645     int i;
646     for (i=0; i < numRegs; i++) {
647         if (info[i].live && info[i].dirty) {
648             if (info[i].pair) {
649                 flushRegWide(cUnit, info[i].reg, info[i].partner);
650             } else {
651                 flushReg(cUnit, info[i].reg);
652             }
653         }
654     }
655 }
656
657 extern void dvmCompilerFlushAllRegs(CompilationUnit *cUnit)
658 {
659     flushAllRegsBody(cUnit, cUnit->regPool->coreTemps,
660                      cUnit->regPool->numCoreTemps);
661     flushAllRegsBody(cUnit, cUnit->regPool->FPTemps,
662                      cUnit->regPool->numFPTemps);
663     dvmCompilerClobberAllRegs(cUnit);
664 }
665
666
667 //TUNING: rewrite all of this reg stuff.  Probably use an attribute table
668 static bool regClassMatches(int regClass, int reg)
669 {
670     if (regClass == kAnyReg) {
671         return true;
672     } else if (regClass == kCoreReg) {
673         return !FPREG(reg);
674     } else {
675         return FPREG(reg);
676     }
677 }
678
679 extern void dvmCompilerMarkLive(CompilationUnit *cUnit, int reg, int sReg)
680 {
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);
686         info->live = true;
687     } else {
688         /* Can't be live if no associated sReg */
689         info->live = false;
690     }
691     info->sReg = sReg;
692 }
693
694 extern void dvmCompilerMarkPair(CompilationUnit *cUnit, int lowReg, int highReg)
695 {
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;
701 }
702
703 static void markRegSingle(CompilationUnit *cUnit, int reg)
704 {
705     RegisterInfo *info = getRegInfo(cUnit, reg);
706     info->pair = false;
707 }
708
709 extern void dvmCompilerMarkClean(CompilationUnit *cUnit, int reg)
710 {
711     RegisterInfo *info = getRegInfo(cUnit, reg);
712     info->dirty = false;
713 }
714
715 extern void dvmCompilerMarkDirty(CompilationUnit *cUnit, int reg)
716 {
717     RegisterInfo *info = getRegInfo(cUnit, reg);
718     info->dirty = true;
719 }
720
721 extern void dvmCompilerMarkInUse(CompilationUnit *cUnit, int reg)
722 {
723       RegisterInfo *info = getRegInfo(cUnit, reg);
724           info->inUse = true;
725 }
726
727 /* Return true if live & dirty */
728 static bool isDirty(CompilationUnit *cUnit, int reg)
729 {
730     RegisterInfo *info = getRegInfo(cUnit, reg);
731     return (info && info->live && info->dirty);
732 }
733
734 void copyRegInfo(CompilationUnit *cUnit, int newReg, int oldReg)
735 {
736     RegisterInfo *newInfo = getRegInfo(cUnit, newReg);
737     RegisterInfo *oldInfo = getRegInfo(cUnit, oldReg);
738     *newInfo = *oldInfo;
739     newInfo->reg = newReg;
740 }
741
742 /*
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.
750  */
751 extern RegLocation dvmCompilerUpdateLoc(CompilationUnit *cUnit, RegLocation loc)
752 {
753     assert(!loc.wide);
754     if (loc.location == kLocDalvikFrame) {
755         RegisterInfo *infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
756         if (infoLo) {
757             if (infoLo->pair) {
758                 dvmCompilerClobber(cUnit, infoLo->reg);
759                 dvmCompilerClobber(cUnit, infoLo->partner);
760             } else {
761                 loc.lowReg = infoLo->reg;
762                 loc.location = kLocPhysReg;
763             }
764         }
765     }
766
767     return loc;
768 }
769
770 /* see comments for updateLoc */
771 extern RegLocation dvmCompilerUpdateLocWide(CompilationUnit *cUnit,
772                                             RegLocation loc)
773 {
774     assert(loc.wide);
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);
780         bool match = true;
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);
789         }
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));
795         }
796         if (match) {
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));
803             return loc;
804         }
805         // Can't easily reuse - clobber any overlaps
806         if (infoLo) {
807             dvmCompilerClobber(cUnit, infoLo->reg);
808             if (infoLo->pair)
809                 dvmCompilerClobber(cUnit, infoLo->partner);
810         }
811         if (infoHi) {
812             dvmCompilerClobber(cUnit, infoHi->reg);
813             if (infoHi->pair)
814                 dvmCompilerClobber(cUnit, infoHi->partner);
815         }
816     }
817
818     return loc;
819 }
820
821 static RegLocation evalLocWide(CompilationUnit *cUnit, RegLocation loc,
822                                int regClass, bool update)
823 {
824     assert(loc.wide);
825     int newRegs;
826     int lowReg;
827     int highReg;
828
829     loc = dvmCompilerUpdateLocWide(cUnit, loc);
830
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,
841                                    loc.highReg);
842             copyRegInfo(cUnit, lowReg, loc.lowReg);
843             copyRegInfo(cUnit, highReg, loc.highReg);
844             dvmCompilerClobber(cUnit, loc.lowReg);
845             dvmCompilerClobber(cUnit, loc.highReg);
846             loc.lowReg = lowReg;
847             loc.highReg = highReg;
848             dvmCompilerMarkPair(cUnit, loc.lowReg, loc.highReg);
849             assert(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
850         }
851         return loc;
852     }
853
854     assert((loc.location != kLocRetval) || (loc.sRegLow == INVALID_SREG));
855     assert((loc.location != kLocRetval) ||
856            (dvmCompilerSRegHi(loc.sRegLow) == INVALID_SREG));
857
858     newRegs = dvmCompilerAllocTypedTempPair(cUnit, loc.fp, regClass);
859     loc.lowReg = newRegs & 0xff;
860     loc.highReg = (newRegs >> 8) & 0xff;
861
862     dvmCompilerMarkPair(cUnit, loc.lowReg, loc.highReg);
863     if (update) {
864         loc.location = kLocPhysReg;
865         dvmCompilerMarkLive(cUnit, loc.lowReg, loc.sRegLow);
866         dvmCompilerMarkLive(cUnit, loc.highReg, dvmCompilerSRegHi(loc.sRegLow));
867     }
868     assert(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
869     return loc;
870 }
871
872 extern RegLocation dvmCompilerEvalLoc(CompilationUnit *cUnit, RegLocation loc,
873                                       int regClass, bool update)
874 {
875     RegisterInfo *infoLo = NULL;
876     int newReg;
877     if (loc.wide)
878         return evalLocWide(cUnit, loc, regClass, update);
879     loc = dvmCompilerUpdateLoc(cUnit, loc);
880
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);
888             loc.lowReg = newReg;
889         }
890         return loc;
891     }
892
893     assert((loc.location != kLocRetval) || (loc.sRegLow == INVALID_SREG));
894
895     newReg = dvmCompilerAllocTypedTemp(cUnit, loc.fp, regClass);
896     loc.lowReg = newReg;
897
898     if (update) {
899         loc.location = kLocPhysReg;
900         dvmCompilerMarkLive(cUnit, loc.lowReg, loc.sRegLow);
901     }
902     return loc;
903 }
904
905 static inline int getDestSSAName(MIR *mir, int num)
906 {
907     assert(mir->ssaRep->numDefs > num);
908     return mir->ssaRep->defs[num];
909 }
910
911 // Get the LocRecord associated with an SSA name use.
912 extern RegLocation dvmCompilerGetSrc(CompilationUnit *cUnit, MIR *mir, int num)
913 {
914     RegLocation loc = cUnit->regLocation[
915          SREG(cUnit, dvmCompilerSSASrc(mir, num))];
916     loc.fp = cUnit->regLocation[dvmCompilerSSASrc(mir, num)].fp;
917     loc.wide = false;
918     return loc;
919 }
920
921 // Get the LocRecord associated with an SSA name def.
922 extern RegLocation dvmCompilerGetDest(CompilationUnit *cUnit, MIR *mir,
923                                       int num)
924 {
925     RegLocation loc = cUnit->regLocation[SREG(cUnit, getDestSSAName(mir, num))];
926     loc.fp = cUnit->regLocation[getDestSSAName(mir, num)].fp;
927     loc.wide = false;
928     return loc;
929 }
930
931 static RegLocation getLocWide(CompilationUnit *cUnit, MIR *mir,
932                               int low, int high, bool isSrc)
933 {
934     RegLocation lowLoc;
935     RegLocation highLoc;
936     /* Copy loc record for low word and patch in data from high word */
937     if (isSrc) {
938         lowLoc = dvmCompilerGetSrc(cUnit, mir, low);
939         highLoc = dvmCompilerGetSrc(cUnit, mir, high);
940     } else {
941         lowLoc = dvmCompilerGetDest(cUnit, mir, low);
942         highLoc = dvmCompilerGetDest(cUnit, mir, high);
943     }
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);
949     }
950     lowLoc.wide = true;
951     lowLoc.highReg = highLoc.lowReg;
952     return lowLoc;
953 }
954
955 extern RegLocation dvmCompilerGetDestWide(CompilationUnit *cUnit, MIR *mir,
956                                           int low, int high)
957 {
958     return getLocWide(cUnit, mir, low, high, false);
959 }
960
961 extern RegLocation dvmCompilerGetSrcWide(CompilationUnit *cUnit, MIR *mir,
962                                          int low, int high)
963 {
964     return getLocWide(cUnit, mir, low, high, true);
965 }
966
967 extern RegLocation dvmCompilerGetReturnWide(CompilationUnit *cUnit)
968 {
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);
975     return res;
976 }
977
978 extern RegLocation dvmCompilerGetReturnWideAlt(CompilationUnit *cUnit)
979 {
980     RegLocation res = LOC_C_RETURN_WIDE;
981     res.lowReg = r2;
982     res.highReg = r3;
983     dvmCompilerClobber(cUnit, r2);
984     dvmCompilerClobber(cUnit, r3);
985     dvmCompilerMarkInUse(cUnit, r2);
986     dvmCompilerMarkInUse(cUnit, r3);
987     dvmCompilerMarkPair(cUnit, res.lowReg, res.highReg);
988     return res;
989 }
990
991 extern RegLocation dvmCompilerGetReturn(CompilationUnit *cUnit)
992 {
993     RegLocation res = LOC_C_RETURN;
994     dvmCompilerClobber(cUnit, r0);
995     dvmCompilerMarkInUse(cUnit, r0);
996     return res;
997 }
998
999 extern RegLocation dvmCompilerGetReturnAlt(CompilationUnit *cUnit)
1000 {
1001     RegLocation res = LOC_C_RETURN;
1002     res.lowReg = r1;
1003     dvmCompilerClobber(cUnit, r1);
1004     dvmCompilerMarkInUse(cUnit, r1);
1005     return res;
1006 }
1007
1008 /* Kill the corresponding bit in the null-checked register list */
1009 extern void dvmCompilerKillNullCheckedLoc(CompilationUnit *cUnit,
1010                                           RegLocation loc)
1011 {
1012     if (loc.location != kLocRetval) {
1013         assert(loc.sRegLow != INVALID_SREG);
1014         dvmClearBit(cUnit->regPool->nullCheckedRegs, loc.sRegLow);
1015         if (loc.wide) {
1016             assert(dvmCompilerSRegHi(loc.sRegLow) != INVALID_SREG);
1017             dvmClearBit(cUnit->regPool->nullCheckedRegs,
1018                         dvmCompilerSRegHi(loc.sRegLow));
1019         }
1020     }
1021 }
1022
1023 extern void dvmCompilerFlushRegWideForV5TEVFP(CompilationUnit *cUnit,
1024                                               int reg1, int reg2)
1025 {
1026     flushRegWide(cUnit, reg1, reg2);
1027 }
1028
1029 extern void dvmCompilerFlushRegForV5TEVFP(CompilationUnit *cUnit, int reg)
1030 {
1031     flushReg(cUnit, reg);
1032 }