blob: 2b0af830d7b03a873a7f254a055320d543169509 [file] [log] [blame]
Bill Buzbee1465db52009-09-23 17:17:35 -07001/*
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
Ben Cheng5d90c202009-11-22 23:31:11 -080025#include "compiler/CompilerUtility.h"
26#include "compiler/CompilerIR.h"
27#include "compiler/Dataflow.h"
28#include "ArmLIR.h"
Bill Buzbee1465db52009-09-23 17:17:35 -070029#include "Codegen.h"
Ben Cheng5d90c202009-11-22 23:31:11 -080030#include "Ralloc.h"
31
32/*
Bill Buzbee1465db52009-09-23 17:17:35 -070033 * 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
Bill Buzbee1465db52009-09-23 17:17:35 -070055#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
Bill Buzbee1465db52009-09-23 17:17:35 -070066/*
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 */
Bill Buzbeec6f10662010-02-09 11:16:15 -080071extern void dvmCompilerResetRegPool(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -070072{
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 */
Bill Buzbeec6f10662010-02-09 11:16:15 -080083extern void dvmCompilerInitPool(RegisterInfo *regs, int *regNums, int num)
Bill Buzbee1465db52009-09-23 17:17:35 -070084{
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
96static 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
Ben Cheng5d90c202009-11-22 23:31:11 -0800108static 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);
Bill Buzbeefc519dc2010-03-06 23:30:57 -0800126 dvmCompilerAbort(cUnit);
Ben Cheng5d90c202009-11-22 23:31:11 -0800127 return NULL;
128}
129
130static 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;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800140 if (dvmCompilerS2VReg(cUnit, info2->sReg) <
141 dvmCompilerS2VReg(cUnit, info1->sReg))
Ben Cheng5d90c202009-11-22 23:31:11 -0800142 info1 = info2;
143 dvmCompilerFlushRegWideImpl(cUnit, rFP,
Bill Buzbeec6f10662010-02-09 11:16:15 -0800144 dvmCompilerS2VReg(cUnit, info1->sReg) << 2,
Ben Cheng5d90c202009-11-22 23:31:11 -0800145 info1->reg, info1->partner);
146 }
147}
148
149static void flushReg(CompilationUnit *cUnit, int reg)
150{
151 RegisterInfo *info = getRegInfo(cUnit, reg);
152 if (info->live && info->dirty) {
153 info->dirty = false;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800154 dvmCompilerFlushRegImpl(cUnit, rFP,
155 dvmCompilerS2VReg(cUnit, info->sReg) << 2,
Ben Cheng5d90c202009-11-22 23:31:11 -0800156 reg, kWord);
157 }
158}
159
160/* return true if found reg to clobber */
161static 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. */
Bill Buzbeec6f10662010-02-09 11:16:15 -0800190void dvmCompilerClobber(CompilationUnit *cUnit, int reg)
Ben Cheng5d90c202009-11-22 23:31:11 -0800191{
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
199static 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 */
Bill Buzbeec6f10662010-02-09 11:16:15 -0800212extern void dvmCompilerClobberSReg(CompilationUnit *cUnit, int sReg)
Ben Cheng5d90c202009-11-22 23:31:11 -0800213{
214 clobberSRegBody(cUnit->regPool->coreTemps, cUnit->regPool->numCoreTemps,
215 sReg);
216 clobberSRegBody(cUnit->regPool->FPTemps, cUnit->regPool->numFPTemps,
217 sReg);
218}
219
Bill Buzbee1465db52009-09-23 17:17:35 -0700220static int allocTempBody(CompilationUnit *cUnit, RegisterInfo *p, int numTemps,
Bill Buzbee1f748632010-03-02 16:14:41 -0800221 int *nextTemp, bool required)
Bill Buzbee1465db52009-09-23 17:17:35 -0700222{
223 int i;
Bill Buzbee1f748632010-03-02 16:14:41 -0800224 int next = *nextTemp;
Bill Buzbee1465db52009-09-23 17:17:35 -0700225 for (i=0; i< numTemps; i++) {
Bill Buzbee1f748632010-03-02 16:14:41 -0800226 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;
Bill Buzbee1465db52009-09-23 17:17:35 -0700234 }
Bill Buzbee1f748632010-03-02 16:14:41 -0800235 next++;
Bill Buzbee1465db52009-09-23 17:17:35 -0700236 }
Bill Buzbee1f748632010-03-02 16:14:41 -0800237 next = *nextTemp;
Bill Buzbee1465db52009-09-23 17:17:35 -0700238 for (i=0; i< numTemps; i++) {
Bill Buzbee1f748632010-03-02 16:14:41 -0800239 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;
Bill Buzbee1465db52009-09-23 17:17:35 -0700247 }
Bill Buzbee1f748632010-03-02 16:14:41 -0800248 next++;
Bill Buzbee1465db52009-09-23 17:17:35 -0700249 }
250 if (required) {
251 LOGE("No free temp registers");
Bill Buzbeefc519dc2010-03-06 23:30:57 -0800252 dvmCompilerAbort(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700253 }
254 return -1; // No register available
255}
256
257//REDO: too many assumptions.
Bill Buzbeec6f10662010-02-09 11:16:15 -0800258extern int dvmCompilerAllocTempDouble(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -0700259{
260 RegisterInfo *p = cUnit->regPool->FPTemps;
261 int numTemps = cUnit->regPool->numFPTemps;
Bill Buzbee1f748632010-03-02 16:14:41 -0800262 int next = cUnit->regPool->nextFPTemp;
Bill Buzbee1465db52009-09-23 17:17:35 -0700263 int i;
264
265 for (i=0; i < numTemps; i+=2) {
Bill Buzbee1f748632010-03-02 16:14:41 -0800266 /* 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;
Bill Buzbee1465db52009-09-23 17:17:35 -0700281 }
Bill Buzbee1f748632010-03-02 16:14:41 -0800282 next += 2;
Bill Buzbee1465db52009-09-23 17:17:35 -0700283 }
Bill Buzbee1f748632010-03-02 16:14:41 -0800284 next = cUnit->regPool->nextFPTemp;
Bill Buzbee1465db52009-09-23 17:17:35 -0700285 for (i=0; i < numTemps; i+=2) {
Bill Buzbee1f748632010-03-02 16:14:41 -0800286 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;
Bill Buzbee1465db52009-09-23 17:17:35 -0700297 }
Bill Buzbee1f748632010-03-02 16:14:41 -0800298 next += 2;
Bill Buzbee1465db52009-09-23 17:17:35 -0700299 }
300 LOGE("No free temp registers");
Bill Buzbeefc519dc2010-03-06 23:30:57 -0800301 dvmCompilerAbort(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700302 return -1;
303}
304
305/* Return a temp if one is available, -1 otherwise */
Bill Buzbeec6f10662010-02-09 11:16:15 -0800306extern int dvmCompilerAllocFreeTemp(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -0700307{
308 return allocTempBody(cUnit, cUnit->regPool->coreTemps,
Bill Buzbee1f748632010-03-02 16:14:41 -0800309 cUnit->regPool->numCoreTemps,
310 &cUnit->regPool->nextCoreTemp, true);
Bill Buzbee1465db52009-09-23 17:17:35 -0700311}
312
Bill Buzbeec6f10662010-02-09 11:16:15 -0800313extern int dvmCompilerAllocTemp(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -0700314{
315 return allocTempBody(cUnit, cUnit->regPool->coreTemps,
Bill Buzbee1f748632010-03-02 16:14:41 -0800316 cUnit->regPool->numCoreTemps,
317 &cUnit->regPool->nextCoreTemp, true);
Bill Buzbee1465db52009-09-23 17:17:35 -0700318}
319
Bill Buzbeec6f10662010-02-09 11:16:15 -0800320extern int dvmCompilerAllocTempFloat(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -0700321{
322 return allocTempBody(cUnit, cUnit->regPool->FPTemps,
Bill Buzbee1f748632010-03-02 16:14:41 -0800323 cUnit->regPool->numFPTemps,
324 &cUnit->regPool->nextFPTemp, true);
Bill Buzbee1465db52009-09-23 17:17:35 -0700325}
326
327static 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
341static 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");
Bill Buzbeefc519dc2010-03-06 23:30:57 -0800362 dvmCompilerAbort(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700363 }
364 return res;
365}
366
Bill Buzbeec6f10662010-02-09 11:16:15 -0800367extern void dvmCompilerFreeTemp(CompilationUnit *cUnit, int reg)
Bill Buzbee1465db52009-09-23 17:17:35 -0700368{
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);
Bill Buzbeefc519dc2010-03-06 23:30:57 -0800389 dvmCompilerAbort(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700390}
391
Bill Buzbee1f748632010-03-02 16:14:41 -0800392/*
393 * FIXME - this needs to also check the preserved pool once we start
394 * start using preserved registers.
395 */
Bill Buzbeec6f10662010-02-09 11:16:15 -0800396extern RegisterInfo *dvmCompilerIsLive(CompilationUnit *cUnit, int reg)
Bill Buzbee1465db52009-09-23 17:17:35 -0700397{
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
Bill Buzbeec6f10662010-02-09 11:16:15 -0800416extern RegisterInfo *dvmCompilerIsTemp(CompilationUnit *cUnit, int reg)
Bill Buzbee1465db52009-09-23 17:17:35 -0700417{
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
Bill Buzbee1465db52009-09-23 17:17:35 -0700436/*
Bill Buzbeec6f10662010-02-09 11:16:15 -0800437 * Similar to dvmCompilerAllocTemp(), but forces the allocation of a specific
Bill Buzbee1465db52009-09-23 17:17:35 -0700438 * register. No check is made to see if the register was previously
439 * allocated. Use with caution.
440 */
Bill Buzbeec6f10662010-02-09 11:16:15 -0800441extern void dvmCompilerLockTemp(CompilationUnit *cUnit, int reg)
Bill Buzbee1465db52009-09-23 17:17:35 -0700442{
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);
Bill Buzbeefc519dc2010-03-06 23:30:57 -0800463 dvmCompilerAbort(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700464}
465
466static void lockArgRegs(CompilationUnit *cUnit)
467{
Bill Buzbeec6f10662010-02-09 11:16:15 -0800468 dvmCompilerLockTemp(cUnit, r0);
469 dvmCompilerLockTemp(cUnit, r1);
470 dvmCompilerLockTemp(cUnit, r2);
471 dvmCompilerLockTemp(cUnit, r3);
Bill Buzbee1465db52009-09-23 17:17:35 -0700472}
473
474/* Clobber all regs that might be used by an external C call */
Elliott Hughes6a555132010-02-25 15:41:42 -0800475extern void dvmCompilerClobberCallRegs(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -0700476{
Bill Buzbeec6f10662010-02-09 11:16:15 -0800477 dvmCompilerClobber(cUnit, r0);
478 dvmCompilerClobber(cUnit, r1);
479 dvmCompilerClobber(cUnit, r2);
480 dvmCompilerClobber(cUnit, r3);
Elliott Hughes6a555132010-02-25 15:41:42 -0800481 dvmCompilerClobber(cUnit, r9); // Need to do this?, be conservative
Bill Buzbeec6f10662010-02-09 11:16:15 -0800482 dvmCompilerClobber(cUnit, r11);
483 dvmCompilerClobber(cUnit, r12);
484 dvmCompilerClobber(cUnit, rlr);
Bill Buzbee1465db52009-09-23 17:17:35 -0700485}
486
487/* Clobber all of the temps that might be used by a handler. */
Bill Buzbeec6f10662010-02-09 11:16:15 -0800488extern void dvmCompilerClobberHandlerRegs(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -0700489{
490 //TUNING: reduce the set of regs used by handlers. Only a few need lots.
Elliott Hughes6a555132010-02-25 15:41:42 -0800491 dvmCompilerClobberCallRegs(cUnit);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800492 dvmCompilerClobber(cUnit, r4PC);
Bill Buzbee6296a2e2010-06-23 16:36:50 -0700493 dvmCompilerClobber(cUnit, r7);
494 dvmCompilerClobber(cUnit, r8);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800495 dvmCompilerClobber(cUnit, r9);
496 dvmCompilerClobber(cUnit, r10);
Bill Buzbee1465db52009-09-23 17:17:35 -0700497}
498
Bill Buzbeec6f10662010-02-09 11:16:15 -0800499extern void dvmCompilerResetDef(CompilationUnit *cUnit, int reg)
Bill Buzbee1465db52009-09-23 17:17:35 -0700500{
501 RegisterInfo *p = getRegInfo(cUnit, reg);
502 p->defStart = NULL;
503 p->defEnd = NULL;
504}
505
506static 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 */
Bill Buzbeec6f10662010-02-09 11:16:15 -0800525extern void dvmCompilerMarkDef(CompilationUnit *cUnit, RegLocation rl,
Bill Buzbee1465db52009-09-23 17:17:35 -0700526 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 */
Bill Buzbeec6f10662010-02-09 11:16:15 -0800541extern void dvmCompilerMarkDefWide(CompilationUnit *cUnit, RegLocation rl,
Bill Buzbee1465db52009-09-23 17:17:35 -0700542 LIR *start, LIR *finish)
543{
544 assert(rl.wide);
545 assert(start && start->next);
546 assert(finish);
547 RegisterInfo *p = getRegInfo(cUnit, rl.lowReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800548 dvmCompilerResetDef(cUnit, rl.highReg); // Only track low of pair
Bill Buzbee1465db52009-09-23 17:17:35 -0700549 p->defStart = start->next;
550 p->defEnd = finish;
551}
552
Bill Buzbeec6f10662010-02-09 11:16:15 -0800553extern RegLocation dvmCompilerWideToNarrow(CompilationUnit *cUnit,
554 RegLocation rl)
Bill Buzbee1465db52009-09-23 17:17:35 -0700555{
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) {
Ben Cheng5d90c202009-11-22 23:31:11 -0800561 dumpRegPool(cUnit->regPool->coreTemps,
562 cUnit->regPool->numCoreTemps);
Bill Buzbee1465db52009-09-23 17:17:35 -0700563 assert(infoLo->pair);
564 }
565 if (!infoHi->pair) {
Ben Cheng5d90c202009-11-22 23:31:11 -0800566 dumpRegPool(cUnit->regPool->coreTemps,
567 cUnit->regPool->numCoreTemps);
Bill Buzbee1465db52009-09-23 17:17:35 -0700568 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
Bill Buzbeec6f10662010-02-09 11:16:15 -0800585extern void dvmCompilerResetDefLoc(CompilationUnit *cUnit, RegLocation rl)
Bill Buzbee1465db52009-09-23 17:17:35 -0700586{
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 }
Bill Buzbeec6f10662010-02-09 11:16:15 -0800594 dvmCompilerResetDef(cUnit, rl.lowReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700595}
596
Bill Buzbeec6f10662010-02-09 11:16:15 -0800597extern void dvmCompilerResetDefLocWide(CompilationUnit *cUnit, RegLocation rl)
Bill Buzbee1465db52009-09-23 17:17:35 -0700598{
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 }
Bill Buzbeec6f10662010-02-09 11:16:15 -0800606 dvmCompilerResetDef(cUnit, rl.lowReg);
607 dvmCompilerResetDef(cUnit, rl.highReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700608}
609
Bill Buzbeec6f10662010-02-09 11:16:15 -0800610extern void dvmCompilerResetDefTracking(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -0700611{
612 int i;
613 for (i=0; i< cUnit->regPool->numCoreTemps; i++) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800614 dvmCompilerResetDef(cUnit, cUnit->regPool->coreTemps[i].reg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700615 }
616 for (i=0; i< cUnit->regPool->numFPTemps; i++) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800617 dvmCompilerResetDef(cUnit, cUnit->regPool->FPTemps[i].reg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700618 }
619}
620
Bill Buzbeec6f10662010-02-09 11:16:15 -0800621extern void dvmCompilerClobberAllRegs(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -0700622{
623 int i;
624 for (i=0; i< cUnit->regPool->numCoreTemps; i++) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800625 dvmCompilerClobber(cUnit, cUnit->regPool->coreTemps[i].reg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700626 }
627 for (i=0; i< cUnit->regPool->numFPTemps; i++) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800628 dvmCompilerClobber(cUnit, cUnit->regPool->FPTemps[i].reg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700629 }
630}
631
632/* To be used when explicitly managing register use */
Bill Buzbeec6f10662010-02-09 11:16:15 -0800633extern void dvmCompilerLockAllTemps(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -0700634{
635 int i;
636 for (i=0; i< cUnit->regPool->numCoreTemps; i++) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800637 dvmCompilerLockTemp(cUnit, cUnit->regPool->coreTemps[i].reg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700638 }
639}
640
641// Make sure nothing is live and dirty
642static 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
Bill Buzbeec6f10662010-02-09 11:16:15 -0800657extern void dvmCompilerFlushAllRegs(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -0700658{
659 flushAllRegsBody(cUnit, cUnit->regPool->coreTemps,
660 cUnit->regPool->numCoreTemps);
661 flushAllRegsBody(cUnit, cUnit->regPool->FPTemps,
662 cUnit->regPool->numFPTemps);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800663 dvmCompilerClobberAllRegs(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700664}
665
666
667//TUNING: rewrite all of this reg stuff. Probably use an attribute table
668static 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
Bill Buzbeec6f10662010-02-09 11:16:15 -0800679extern void dvmCompilerMarkLive(CompilationUnit *cUnit, int reg, int sReg)
Bill Buzbee1465db52009-09-23 17:17:35 -0700680{
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) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800685 dvmCompilerClobberSReg(cUnit, sReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700686 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
Bill Buzbeec6f10662010-02-09 11:16:15 -0800694extern void dvmCompilerMarkPair(CompilationUnit *cUnit, int lowReg, int highReg)
Bill Buzbee1465db52009-09-23 17:17:35 -0700695{
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
703static void markRegSingle(CompilationUnit *cUnit, int reg)
704{
705 RegisterInfo *info = getRegInfo(cUnit, reg);
706 info->pair = false;
707}
708
Bill Buzbeec6f10662010-02-09 11:16:15 -0800709extern void dvmCompilerMarkClean(CompilationUnit *cUnit, int reg)
Bill Buzbee1465db52009-09-23 17:17:35 -0700710{
711 RegisterInfo *info = getRegInfo(cUnit, reg);
712 info->dirty = false;
713}
714
Bill Buzbeec6f10662010-02-09 11:16:15 -0800715extern void dvmCompilerMarkDirty(CompilationUnit *cUnit, int reg)
Bill Buzbee1465db52009-09-23 17:17:35 -0700716{
717 RegisterInfo *info = getRegInfo(cUnit, reg);
718 info->dirty = true;
719}
720
Elliott Hughes6a555132010-02-25 15:41:42 -0800721extern void dvmCompilerMarkInUse(CompilationUnit *cUnit, int reg)
Bill Buzbee1465db52009-09-23 17:17:35 -0700722{
Ben Cheng5d90c202009-11-22 23:31:11 -0800723 RegisterInfo *info = getRegInfo(cUnit, reg);
724 info->inUse = true;
Bill Buzbee1465db52009-09-23 17:17:35 -0700725}
726
727/* Return true if live & dirty */
728static bool isDirty(CompilationUnit *cUnit, int reg)
729{
730 RegisterInfo *info = getRegInfo(cUnit, reg);
731 return (info && info->live && info->dirty);
732}
733
734void 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 */
Bill Buzbeec6f10662010-02-09 11:16:15 -0800751extern RegLocation dvmCompilerUpdateLoc(CompilationUnit *cUnit, RegLocation loc)
Bill Buzbee1465db52009-09-23 17:17:35 -0700752{
753 assert(!loc.wide);
754 if (loc.location == kLocDalvikFrame) {
755 RegisterInfo *infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
756 if (infoLo) {
757 if (infoLo->pair) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800758 dvmCompilerClobber(cUnit, infoLo->reg);
759 dvmCompilerClobber(cUnit, infoLo->partner);
Bill Buzbee1465db52009-09-23 17:17:35 -0700760 } else {
761 loc.lowReg = infoLo->reg;
762 loc.location = kLocPhysReg;
763 }
764 }
765 }
766
767 return loc;
768}
769
770/* see comments for updateLoc */
Bill Buzbeec6f10662010-02-09 11:16:15 -0800771extern RegLocation dvmCompilerUpdateLocWide(CompilationUnit *cUnit,
772 RegLocation loc)
Bill Buzbee1465db52009-09-23 17:17:35 -0700773{
774 assert(loc.wide);
775 if (loc.location == kLocDalvikFrame) {
Bill Buzbee80cef862010-03-25 10:38:34 -0700776 // Are the dalvik regs already live in physical registers?
Bill Buzbee1465db52009-09-23 17:17:35 -0700777 RegisterInfo *infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800778 RegisterInfo *infoHi = allocLive(cUnit,
779 dvmCompilerSRegHi(loc.sRegLow), kAnyReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700780 bool match = true;
781 match = match && (infoLo != NULL);
782 match = match && (infoHi != NULL);
Bill Buzbee80cef862010-03-25 10:38:34 -0700783 // Are they both core or both FP?
Bill Buzbee1465db52009-09-23 17:17:35 -0700784 match = match && (FPREG(infoLo->reg) == FPREG(infoHi->reg));
Bill Buzbee80cef862010-03-25 10:38:34 -0700785 // If a pair of floating point singles, are they properly aligned?
Bill Buzbee1465db52009-09-23 17:17:35 -0700786 if (match && FPREG(infoLo->reg)) {
787 match &= ((infoLo->reg & 0x1) == 0);
788 match &= ((infoHi->reg - infoLo->reg) == 1);
789 }
Bill Buzbee80cef862010-03-25 10:38:34 -0700790 // 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 }
Bill Buzbee1465db52009-09-23 17:17:35 -0700796 if (match) {
Bill Buzbee80cef862010-03-25 10:38:34 -0700797 // Can reuse - update the register usage info
Bill Buzbee1465db52009-09-23 17:17:35 -0700798 loc.lowReg = infoLo->reg;
799 loc.highReg = infoHi->reg;
800 loc.location = kLocPhysReg;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800801 dvmCompilerMarkPair(cUnit, loc.lowReg, loc.highReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700802 assert(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
803 return loc;
804 }
Bill Buzbee80cef862010-03-25 10:38:34 -0700805 // Can't easily reuse - clobber any overlaps
Bill Buzbee1465db52009-09-23 17:17:35 -0700806 if (infoLo) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800807 dvmCompilerClobber(cUnit, infoLo->reg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700808 if (infoLo->pair)
Bill Buzbeec6f10662010-02-09 11:16:15 -0800809 dvmCompilerClobber(cUnit, infoLo->partner);
Bill Buzbee1465db52009-09-23 17:17:35 -0700810 }
811 if (infoHi) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800812 dvmCompilerClobber(cUnit, infoHi->reg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700813 if (infoHi->pair)
Bill Buzbeec6f10662010-02-09 11:16:15 -0800814 dvmCompilerClobber(cUnit, infoHi->partner);
Bill Buzbee1465db52009-09-23 17:17:35 -0700815 }
816 }
817
818 return loc;
819}
820
821static 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
Bill Buzbeec6f10662010-02-09 11:16:15 -0800829 loc = dvmCompilerUpdateLocWide(cUnit, loc);
Bill Buzbee1465db52009-09-23 17:17:35 -0700830
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 */
Ben Cheng5d90c202009-11-22 23:31:11 -0800837 newRegs = dvmCompilerAllocTypedTempPair(cUnit, loc.fp, regClass);
Bill Buzbee1465db52009-09-23 17:17:35 -0700838 lowReg = newRegs & 0xff;
839 highReg = (newRegs >> 8) & 0xff;
Ben Cheng5d90c202009-11-22 23:31:11 -0800840 dvmCompilerRegCopyWide(cUnit, lowReg, highReg, loc.lowReg,
841 loc.highReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700842 copyRegInfo(cUnit, lowReg, loc.lowReg);
843 copyRegInfo(cUnit, highReg, loc.highReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800844 dvmCompilerClobber(cUnit, loc.lowReg);
845 dvmCompilerClobber(cUnit, loc.highReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700846 loc.lowReg = lowReg;
847 loc.highReg = highReg;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800848 dvmCompilerMarkPair(cUnit, loc.lowReg, loc.highReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700849 assert(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
850 }
851 return loc;
852 }
853
854 assert((loc.location != kLocRetval) || (loc.sRegLow == INVALID_SREG));
Ben Cheng5d90c202009-11-22 23:31:11 -0800855 assert((loc.location != kLocRetval) ||
Bill Buzbeec6f10662010-02-09 11:16:15 -0800856 (dvmCompilerSRegHi(loc.sRegLow) == INVALID_SREG));
Bill Buzbee1465db52009-09-23 17:17:35 -0700857
Ben Cheng5d90c202009-11-22 23:31:11 -0800858 newRegs = dvmCompilerAllocTypedTempPair(cUnit, loc.fp, regClass);
Bill Buzbee1465db52009-09-23 17:17:35 -0700859 loc.lowReg = newRegs & 0xff;
860 loc.highReg = (newRegs >> 8) & 0xff;
861
Bill Buzbeec6f10662010-02-09 11:16:15 -0800862 dvmCompilerMarkPair(cUnit, loc.lowReg, loc.highReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700863 if (update) {
864 loc.location = kLocPhysReg;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800865 dvmCompilerMarkLive(cUnit, loc.lowReg, loc.sRegLow);
866 dvmCompilerMarkLive(cUnit, loc.highReg, dvmCompilerSRegHi(loc.sRegLow));
Bill Buzbee1465db52009-09-23 17:17:35 -0700867 }
868 assert(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
869 return loc;
870}
871
Bill Buzbeec6f10662010-02-09 11:16:15 -0800872extern RegLocation dvmCompilerEvalLoc(CompilationUnit *cUnit, RegLocation loc,
873 int regClass, bool update)
Bill Buzbee1465db52009-09-23 17:17:35 -0700874{
875 RegisterInfo *infoLo = NULL;
876 int newReg;
877 if (loc.wide)
878 return evalLocWide(cUnit, loc, regClass, update);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800879 loc = dvmCompilerUpdateLoc(cUnit, loc);
Bill Buzbee1465db52009-09-23 17:17:35 -0700880
881 if (loc.location == kLocPhysReg) {
882 if (!regClassMatches(regClass, loc.lowReg)) {
883 /* Wrong register class. Realloc, copy and transfer ownership */
Ben Cheng5d90c202009-11-22 23:31:11 -0800884 newReg = dvmCompilerAllocTypedTemp(cUnit, loc.fp, regClass);
885 dvmCompilerRegCopy(cUnit, newReg, loc.lowReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700886 copyRegInfo(cUnit, newReg, loc.lowReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800887 dvmCompilerClobber(cUnit, loc.lowReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700888 loc.lowReg = newReg;
889 }
890 return loc;
891 }
892
893 assert((loc.location != kLocRetval) || (loc.sRegLow == INVALID_SREG));
894
Ben Cheng5d90c202009-11-22 23:31:11 -0800895 newReg = dvmCompilerAllocTypedTemp(cUnit, loc.fp, regClass);
Bill Buzbee1465db52009-09-23 17:17:35 -0700896 loc.lowReg = newReg;
897
898 if (update) {
899 loc.location = kLocPhysReg;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800900 dvmCompilerMarkLive(cUnit, loc.lowReg, loc.sRegLow);
Bill Buzbee1465db52009-09-23 17:17:35 -0700901 }
902 return loc;
903}
904
Bill Buzbee1465db52009-09-23 17:17:35 -0700905static 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.
Bill Buzbeec6f10662010-02-09 11:16:15 -0800912extern RegLocation dvmCompilerGetSrc(CompilationUnit *cUnit, MIR *mir, int num)
Bill Buzbee1465db52009-09-23 17:17:35 -0700913{
Bill Buzbeec6f10662010-02-09 11:16:15 -0800914 RegLocation loc = cUnit->regLocation[
915 SREG(cUnit, dvmCompilerSSASrc(mir, num))];
916 loc.fp = cUnit->regLocation[dvmCompilerSSASrc(mir, num)].fp;
Bill Buzbee1465db52009-09-23 17:17:35 -0700917 loc.wide = false;
918 return loc;
919}
920
921// Get the LocRecord associated with an SSA name def.
Bill Buzbeec6f10662010-02-09 11:16:15 -0800922extern RegLocation dvmCompilerGetDest(CompilationUnit *cUnit, MIR *mir,
923 int num)
Bill Buzbee1465db52009-09-23 17:17:35 -0700924{
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
931static RegLocation getLocWide(CompilationUnit *cUnit, MIR *mir,
Bill Buzbeec6f10662010-02-09 11:16:15 -0800932 int low, int high, bool isSrc)
Bill Buzbee1465db52009-09-23 17:17:35 -0700933{
934 RegLocation lowLoc;
935 RegLocation highLoc;
936 /* Copy loc record for low word and patch in data from high word */
937 if (isSrc) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800938 lowLoc = dvmCompilerGetSrc(cUnit, mir, low);
939 highLoc = dvmCompilerGetSrc(cUnit, mir, high);
Bill Buzbee1465db52009-09-23 17:17:35 -0700940 } else {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800941 lowLoc = dvmCompilerGetDest(cUnit, mir, low);
942 highLoc = dvmCompilerGetDest(cUnit, mir, high);
Bill Buzbee1465db52009-09-23 17:17:35 -0700943 }
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}
Ben Cheng5d90c202009-11-22 23:31:11 -0800954
Bill Buzbeec6f10662010-02-09 11:16:15 -0800955extern RegLocation dvmCompilerGetDestWide(CompilationUnit *cUnit, MIR *mir,
956 int low, int high)
Bill Buzbee1465db52009-09-23 17:17:35 -0700957{
958 return getLocWide(cUnit, mir, low, high, false);
959}
960
Bill Buzbeec6f10662010-02-09 11:16:15 -0800961extern RegLocation dvmCompilerGetSrcWide(CompilationUnit *cUnit, MIR *mir,
Bill Buzbee1465db52009-09-23 17:17:35 -0700962 int low, int high)
963{
964 return getLocWide(cUnit, mir, low, high, true);
965}
966
Bill Buzbeec6f10662010-02-09 11:16:15 -0800967extern RegLocation dvmCompilerGetReturnWide(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -0700968{
969 RegLocation res = LOC_C_RETURN_WIDE;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800970 dvmCompilerClobber(cUnit, r0);
971 dvmCompilerClobber(cUnit, r1);
Elliott Hughes6a555132010-02-25 15:41:42 -0800972 dvmCompilerMarkInUse(cUnit, r0);
973 dvmCompilerMarkInUse(cUnit, r1);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800974 dvmCompilerMarkPair(cUnit, res.lowReg, res.highReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700975 return res;
976}
977
Bill Buzbeec6f10662010-02-09 11:16:15 -0800978extern RegLocation dvmCompilerGetReturnWideAlt(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -0700979{
980 RegLocation res = LOC_C_RETURN_WIDE;
981 res.lowReg = r2;
982 res.highReg = r3;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800983 dvmCompilerClobber(cUnit, r2);
984 dvmCompilerClobber(cUnit, r3);
Elliott Hughes6a555132010-02-25 15:41:42 -0800985 dvmCompilerMarkInUse(cUnit, r2);
986 dvmCompilerMarkInUse(cUnit, r3);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800987 dvmCompilerMarkPair(cUnit, res.lowReg, res.highReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700988 return res;
989}
990
Bill Buzbeec6f10662010-02-09 11:16:15 -0800991extern RegLocation dvmCompilerGetReturn(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -0700992{
993 RegLocation res = LOC_C_RETURN;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800994 dvmCompilerClobber(cUnit, r0);
Elliott Hughes6a555132010-02-25 15:41:42 -0800995 dvmCompilerMarkInUse(cUnit, r0);
Bill Buzbee1465db52009-09-23 17:17:35 -0700996 return res;
997}
998
Bill Buzbeec6f10662010-02-09 11:16:15 -0800999extern RegLocation dvmCompilerGetReturnAlt(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -07001000{
1001 RegLocation res = LOC_C_RETURN;
1002 res.lowReg = r1;
Bill Buzbeec6f10662010-02-09 11:16:15 -08001003 dvmCompilerClobber(cUnit, r1);
Elliott Hughes6a555132010-02-25 15:41:42 -08001004 dvmCompilerMarkInUse(cUnit, r1);
Bill Buzbee1465db52009-09-23 17:17:35 -07001005 return res;
1006}
1007
1008/* Kill the corresponding bit in the null-checked register list */
Bill Buzbeec6f10662010-02-09 11:16:15 -08001009extern void dvmCompilerKillNullCheckedLoc(CompilationUnit *cUnit,
1010 RegLocation loc)
Bill Buzbee1465db52009-09-23 17:17:35 -07001011{
1012 if (loc.location != kLocRetval) {
1013 assert(loc.sRegLow != INVALID_SREG);
1014 dvmClearBit(cUnit->regPool->nullCheckedRegs, loc.sRegLow);
1015 if (loc.wide) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001016 assert(dvmCompilerSRegHi(loc.sRegLow) != INVALID_SREG);
1017 dvmClearBit(cUnit->regPool->nullCheckedRegs,
1018 dvmCompilerSRegHi(loc.sRegLow));
Bill Buzbee1465db52009-09-23 17:17:35 -07001019 }
1020 }
1021}
Ben Cheng5d90c202009-11-22 23:31:11 -08001022
1023extern void dvmCompilerFlushRegWideForV5TEVFP(CompilationUnit *cUnit,
1024 int reg1, int reg2)
1025{
1026 flushRegWide(cUnit, reg1, reg2);
1027}
1028
1029extern void dvmCompilerFlushRegForV5TEVFP(CompilationUnit *cUnit, int reg)
1030{
1031 flushReg(cUnit, reg);
1032}