blob: e357ba672a5fcb8c7377c47b61fa6b3c5719267b [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);
493 dvmCompilerClobber(cUnit, r9);
494 dvmCompilerClobber(cUnit, r10);
Bill Buzbee1465db52009-09-23 17:17:35 -0700495}
496
Bill Buzbeec6f10662010-02-09 11:16:15 -0800497extern void dvmCompilerResetDef(CompilationUnit *cUnit, int reg)
Bill Buzbee1465db52009-09-23 17:17:35 -0700498{
499 RegisterInfo *p = getRegInfo(cUnit, reg);
500 p->defStart = NULL;
501 p->defEnd = NULL;
502}
503
504static void nullifyRange(CompilationUnit *cUnit, LIR *start, LIR *finish,
505 int sReg1, int sReg2)
506{
507 if (start && finish) {
508 LIR *p;
509 assert(sReg1 == sReg2);
510 for (p = start; ;p = p->next) {
511 ((ArmLIR *)p)->isNop = true;
512 if (p == finish)
513 break;
514 }
515 }
516}
517
518/*
519 * Mark the beginning and end LIR of a def sequence. Note that
520 * on entry start points to the LIR prior to the beginning of the
521 * sequence.
522 */
Bill Buzbeec6f10662010-02-09 11:16:15 -0800523extern void dvmCompilerMarkDef(CompilationUnit *cUnit, RegLocation rl,
Bill Buzbee1465db52009-09-23 17:17:35 -0700524 LIR *start, LIR *finish)
525{
526 assert(!rl.wide);
527 assert(start && start->next);
528 assert(finish);
529 RegisterInfo *p = getRegInfo(cUnit, rl.lowReg);
530 p->defStart = start->next;
531 p->defEnd = finish;
532}
533
534/*
535 * Mark the beginning and end LIR of a def sequence. Note that
536 * on entry start points to the LIR prior to the beginning of the
537 * sequence.
538 */
Bill Buzbeec6f10662010-02-09 11:16:15 -0800539extern void dvmCompilerMarkDefWide(CompilationUnit *cUnit, RegLocation rl,
Bill Buzbee1465db52009-09-23 17:17:35 -0700540 LIR *start, LIR *finish)
541{
542 assert(rl.wide);
543 assert(start && start->next);
544 assert(finish);
545 RegisterInfo *p = getRegInfo(cUnit, rl.lowReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800546 dvmCompilerResetDef(cUnit, rl.highReg); // Only track low of pair
Bill Buzbee1465db52009-09-23 17:17:35 -0700547 p->defStart = start->next;
548 p->defEnd = finish;
549}
550
Bill Buzbeec6f10662010-02-09 11:16:15 -0800551extern RegLocation dvmCompilerWideToNarrow(CompilationUnit *cUnit,
552 RegLocation rl)
Bill Buzbee1465db52009-09-23 17:17:35 -0700553{
554 assert(rl.wide);
555 if (rl.location == kLocPhysReg) {
556 RegisterInfo *infoLo = getRegInfo(cUnit, rl.lowReg);
557 RegisterInfo *infoHi = getRegInfo(cUnit, rl.highReg);
558 if (!infoLo->pair) {
Ben Cheng5d90c202009-11-22 23:31:11 -0800559 dumpRegPool(cUnit->regPool->coreTemps,
560 cUnit->regPool->numCoreTemps);
Bill Buzbee1465db52009-09-23 17:17:35 -0700561 assert(infoLo->pair);
562 }
563 if (!infoHi->pair) {
Ben Cheng5d90c202009-11-22 23:31:11 -0800564 dumpRegPool(cUnit->regPool->coreTemps,
565 cUnit->regPool->numCoreTemps);
Bill Buzbee1465db52009-09-23 17:17:35 -0700566 assert(infoHi->pair);
567 }
568 assert(infoLo->pair);
569 assert(infoHi->pair);
570 assert(infoLo->partner == infoHi->reg);
571 assert(infoHi->partner == infoLo->reg);
572 infoLo->pair = false;
573 infoHi->pair = false;
574 infoLo->defStart = NULL;
575 infoLo->defEnd = NULL;
576 infoHi->defStart = NULL;
577 infoHi->defEnd = NULL;
578 }
579 rl.wide = false;
580 return rl;
581}
582
Bill Buzbeec6f10662010-02-09 11:16:15 -0800583extern void dvmCompilerResetDefLoc(CompilationUnit *cUnit, RegLocation rl)
Bill Buzbee1465db52009-09-23 17:17:35 -0700584{
585 assert(!rl.wide);
586 if (!(gDvmJit.disableOpt & (1 << kSuppressLoads))) {
587 RegisterInfo *p = getRegInfo(cUnit, rl.lowReg);
588 assert(!p->pair);
589 nullifyRange(cUnit, p->defStart, p->defEnd,
590 p->sReg, rl.sRegLow);
591 }
Bill Buzbeec6f10662010-02-09 11:16:15 -0800592 dvmCompilerResetDef(cUnit, rl.lowReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700593}
594
Bill Buzbeec6f10662010-02-09 11:16:15 -0800595extern void dvmCompilerResetDefLocWide(CompilationUnit *cUnit, RegLocation rl)
Bill Buzbee1465db52009-09-23 17:17:35 -0700596{
597 assert(rl.wide);
598 if (!(gDvmJit.disableOpt & (1 << kSuppressLoads))) {
599 RegisterInfo *p = getRegInfo(cUnit, rl.lowReg);
600 assert(p->pair);
601 nullifyRange(cUnit, p->defStart, p->defEnd,
602 p->sReg, rl.sRegLow);
603 }
Bill Buzbeec6f10662010-02-09 11:16:15 -0800604 dvmCompilerResetDef(cUnit, rl.lowReg);
605 dvmCompilerResetDef(cUnit, rl.highReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700606}
607
Bill Buzbeec6f10662010-02-09 11:16:15 -0800608extern void dvmCompilerResetDefTracking(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -0700609{
610 int i;
611 for (i=0; i< cUnit->regPool->numCoreTemps; i++) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800612 dvmCompilerResetDef(cUnit, cUnit->regPool->coreTemps[i].reg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700613 }
614 for (i=0; i< cUnit->regPool->numFPTemps; i++) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800615 dvmCompilerResetDef(cUnit, cUnit->regPool->FPTemps[i].reg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700616 }
617}
618
Bill Buzbeec6f10662010-02-09 11:16:15 -0800619extern void dvmCompilerClobberAllRegs(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -0700620{
621 int i;
622 for (i=0; i< cUnit->regPool->numCoreTemps; i++) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800623 dvmCompilerClobber(cUnit, cUnit->regPool->coreTemps[i].reg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700624 }
625 for (i=0; i< cUnit->regPool->numFPTemps; i++) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800626 dvmCompilerClobber(cUnit, cUnit->regPool->FPTemps[i].reg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700627 }
628}
629
630/* To be used when explicitly managing register use */
Bill Buzbeec6f10662010-02-09 11:16:15 -0800631extern void dvmCompilerLockAllTemps(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -0700632{
633 int i;
634 for (i=0; i< cUnit->regPool->numCoreTemps; i++) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800635 dvmCompilerLockTemp(cUnit, cUnit->regPool->coreTemps[i].reg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700636 }
637}
638
639// Make sure nothing is live and dirty
640static void flushAllRegsBody(CompilationUnit *cUnit, RegisterInfo *info,
641 int numRegs)
642{
643 int i;
644 for (i=0; i < numRegs; i++) {
645 if (info[i].live && info[i].dirty) {
646 if (info[i].pair) {
647 flushRegWide(cUnit, info[i].reg, info[i].partner);
648 } else {
649 flushReg(cUnit, info[i].reg);
650 }
651 }
652 }
653}
654
Bill Buzbeec6f10662010-02-09 11:16:15 -0800655extern void dvmCompilerFlushAllRegs(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -0700656{
657 flushAllRegsBody(cUnit, cUnit->regPool->coreTemps,
658 cUnit->regPool->numCoreTemps);
659 flushAllRegsBody(cUnit, cUnit->regPool->FPTemps,
660 cUnit->regPool->numFPTemps);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800661 dvmCompilerClobberAllRegs(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700662}
663
664
665//TUNING: rewrite all of this reg stuff. Probably use an attribute table
666static bool regClassMatches(int regClass, int reg)
667{
668 if (regClass == kAnyReg) {
669 return true;
670 } else if (regClass == kCoreReg) {
671 return !FPREG(reg);
672 } else {
673 return FPREG(reg);
674 }
675}
676
Bill Buzbeec6f10662010-02-09 11:16:15 -0800677extern void dvmCompilerMarkLive(CompilationUnit *cUnit, int reg, int sReg)
Bill Buzbee1465db52009-09-23 17:17:35 -0700678{
679 RegisterInfo *info = getRegInfo(cUnit, reg);
680 if ((info->reg == reg) && (info->sReg == sReg) && info->live) {
681 return; /* already live */
682 } else if (sReg != INVALID_SREG) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800683 dvmCompilerClobberSReg(cUnit, sReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700684 info->live = true;
685 } else {
686 /* Can't be live if no associated sReg */
687 info->live = false;
688 }
689 info->sReg = sReg;
690}
691
Bill Buzbeec6f10662010-02-09 11:16:15 -0800692extern void dvmCompilerMarkPair(CompilationUnit *cUnit, int lowReg, int highReg)
Bill Buzbee1465db52009-09-23 17:17:35 -0700693{
694 RegisterInfo *infoLo = getRegInfo(cUnit, lowReg);
695 RegisterInfo *infoHi = getRegInfo(cUnit, highReg);
696 infoLo->pair = infoHi->pair = true;
697 infoLo->partner = highReg;
698 infoHi->partner = lowReg;
699}
700
701static void markRegSingle(CompilationUnit *cUnit, int reg)
702{
703 RegisterInfo *info = getRegInfo(cUnit, reg);
704 info->pair = false;
705}
706
Bill Buzbeec6f10662010-02-09 11:16:15 -0800707extern void dvmCompilerMarkClean(CompilationUnit *cUnit, int reg)
Bill Buzbee1465db52009-09-23 17:17:35 -0700708{
709 RegisterInfo *info = getRegInfo(cUnit, reg);
710 info->dirty = false;
711}
712
Bill Buzbeec6f10662010-02-09 11:16:15 -0800713extern void dvmCompilerMarkDirty(CompilationUnit *cUnit, int reg)
Bill Buzbee1465db52009-09-23 17:17:35 -0700714{
715 RegisterInfo *info = getRegInfo(cUnit, reg);
716 info->dirty = true;
717}
718
Elliott Hughes6a555132010-02-25 15:41:42 -0800719extern void dvmCompilerMarkInUse(CompilationUnit *cUnit, int reg)
Bill Buzbee1465db52009-09-23 17:17:35 -0700720{
Ben Cheng5d90c202009-11-22 23:31:11 -0800721 RegisterInfo *info = getRegInfo(cUnit, reg);
722 info->inUse = true;
Bill Buzbee1465db52009-09-23 17:17:35 -0700723}
724
725/* Return true if live & dirty */
726static bool isDirty(CompilationUnit *cUnit, int reg)
727{
728 RegisterInfo *info = getRegInfo(cUnit, reg);
729 return (info && info->live && info->dirty);
730}
731
732void copyRegInfo(CompilationUnit *cUnit, int newReg, int oldReg)
733{
734 RegisterInfo *newInfo = getRegInfo(cUnit, newReg);
735 RegisterInfo *oldInfo = getRegInfo(cUnit, oldReg);
736 *newInfo = *oldInfo;
737 newInfo->reg = newReg;
738}
739
740/*
741 * Return an updated location record with current in-register status.
742 * If the value lives in live temps, reflect that fact. No code
743 * is generated. The the live value is part of an older pair,
744 * clobber both low and high.
745 * TUNING: clobbering both is a bit heavy-handed, but the alternative
746 * is a bit complex when dealing with FP regs. Examine code to see
747 * if it's worthwhile trying to be more clever here.
748 */
Bill Buzbeec6f10662010-02-09 11:16:15 -0800749extern RegLocation dvmCompilerUpdateLoc(CompilationUnit *cUnit, RegLocation loc)
Bill Buzbee1465db52009-09-23 17:17:35 -0700750{
751 assert(!loc.wide);
752 if (loc.location == kLocDalvikFrame) {
753 RegisterInfo *infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
754 if (infoLo) {
755 if (infoLo->pair) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800756 dvmCompilerClobber(cUnit, infoLo->reg);
757 dvmCompilerClobber(cUnit, infoLo->partner);
Bill Buzbee1465db52009-09-23 17:17:35 -0700758 } else {
759 loc.lowReg = infoLo->reg;
760 loc.location = kLocPhysReg;
761 }
762 }
763 }
764
765 return loc;
766}
767
768/* see comments for updateLoc */
Bill Buzbeec6f10662010-02-09 11:16:15 -0800769extern RegLocation dvmCompilerUpdateLocWide(CompilationUnit *cUnit,
770 RegLocation loc)
Bill Buzbee1465db52009-09-23 17:17:35 -0700771{
772 assert(loc.wide);
773 if (loc.location == kLocDalvikFrame) {
Bill Buzbee80cef862010-03-25 10:38:34 -0700774 // Are the dalvik regs already live in physical registers?
Bill Buzbee1465db52009-09-23 17:17:35 -0700775 RegisterInfo *infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800776 RegisterInfo *infoHi = allocLive(cUnit,
777 dvmCompilerSRegHi(loc.sRegLow), kAnyReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700778 bool match = true;
779 match = match && (infoLo != NULL);
780 match = match && (infoHi != NULL);
Bill Buzbee80cef862010-03-25 10:38:34 -0700781 // Are they both core or both FP?
Bill Buzbee1465db52009-09-23 17:17:35 -0700782 match = match && (FPREG(infoLo->reg) == FPREG(infoHi->reg));
Bill Buzbee80cef862010-03-25 10:38:34 -0700783 // If a pair of floating point singles, are they properly aligned?
Bill Buzbee1465db52009-09-23 17:17:35 -0700784 if (match && FPREG(infoLo->reg)) {
785 match &= ((infoLo->reg & 0x1) == 0);
786 match &= ((infoHi->reg - infoLo->reg) == 1);
787 }
Bill Buzbee80cef862010-03-25 10:38:34 -0700788 // If previously used as a pair, it is the same pair?
789 if (match && (infoLo->pair || infoHi->pair)) {
790 match = (infoLo->pair == infoHi->pair);
791 match &= ((infoLo->reg == infoHi->partner) &&
792 (infoHi->reg == infoLo->partner));
793 }
Bill Buzbee1465db52009-09-23 17:17:35 -0700794 if (match) {
Bill Buzbee80cef862010-03-25 10:38:34 -0700795 // Can reuse - update the register usage info
Bill Buzbee1465db52009-09-23 17:17:35 -0700796 loc.lowReg = infoLo->reg;
797 loc.highReg = infoHi->reg;
798 loc.location = kLocPhysReg;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800799 dvmCompilerMarkPair(cUnit, loc.lowReg, loc.highReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700800 assert(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
801 return loc;
802 }
Bill Buzbee80cef862010-03-25 10:38:34 -0700803 // Can't easily reuse - clobber any overlaps
Bill Buzbee1465db52009-09-23 17:17:35 -0700804 if (infoLo) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800805 dvmCompilerClobber(cUnit, infoLo->reg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700806 if (infoLo->pair)
Bill Buzbeec6f10662010-02-09 11:16:15 -0800807 dvmCompilerClobber(cUnit, infoLo->partner);
Bill Buzbee1465db52009-09-23 17:17:35 -0700808 }
809 if (infoHi) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800810 dvmCompilerClobber(cUnit, infoHi->reg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700811 if (infoHi->pair)
Bill Buzbeec6f10662010-02-09 11:16:15 -0800812 dvmCompilerClobber(cUnit, infoHi->partner);
Bill Buzbee1465db52009-09-23 17:17:35 -0700813 }
814 }
815
816 return loc;
817}
818
819static RegLocation evalLocWide(CompilationUnit *cUnit, RegLocation loc,
820 int regClass, bool update)
821{
822 assert(loc.wide);
823 int newRegs;
824 int lowReg;
825 int highReg;
826
Bill Buzbeec6f10662010-02-09 11:16:15 -0800827 loc = dvmCompilerUpdateLocWide(cUnit, loc);
Bill Buzbee1465db52009-09-23 17:17:35 -0700828
829 /* If already in registers, we can assume proper form. Right reg class? */
830 if (loc.location == kLocPhysReg) {
831 assert(FPREG(loc.lowReg) == FPREG(loc.highReg));
832 assert(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
833 if (!regClassMatches(regClass, loc.lowReg)) {
834 /* Wrong register class. Reallocate and copy */
Ben Cheng5d90c202009-11-22 23:31:11 -0800835 newRegs = dvmCompilerAllocTypedTempPair(cUnit, loc.fp, regClass);
Bill Buzbee1465db52009-09-23 17:17:35 -0700836 lowReg = newRegs & 0xff;
837 highReg = (newRegs >> 8) & 0xff;
Ben Cheng5d90c202009-11-22 23:31:11 -0800838 dvmCompilerRegCopyWide(cUnit, lowReg, highReg, loc.lowReg,
839 loc.highReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700840 copyRegInfo(cUnit, lowReg, loc.lowReg);
841 copyRegInfo(cUnit, highReg, loc.highReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800842 dvmCompilerClobber(cUnit, loc.lowReg);
843 dvmCompilerClobber(cUnit, loc.highReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700844 loc.lowReg = lowReg;
845 loc.highReg = highReg;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800846 dvmCompilerMarkPair(cUnit, loc.lowReg, loc.highReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700847 assert(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
848 }
849 return loc;
850 }
851
852 assert((loc.location != kLocRetval) || (loc.sRegLow == INVALID_SREG));
Ben Cheng5d90c202009-11-22 23:31:11 -0800853 assert((loc.location != kLocRetval) ||
Bill Buzbeec6f10662010-02-09 11:16:15 -0800854 (dvmCompilerSRegHi(loc.sRegLow) == INVALID_SREG));
Bill Buzbee1465db52009-09-23 17:17:35 -0700855
Ben Cheng5d90c202009-11-22 23:31:11 -0800856 newRegs = dvmCompilerAllocTypedTempPair(cUnit, loc.fp, regClass);
Bill Buzbee1465db52009-09-23 17:17:35 -0700857 loc.lowReg = newRegs & 0xff;
858 loc.highReg = (newRegs >> 8) & 0xff;
859
Bill Buzbeec6f10662010-02-09 11:16:15 -0800860 dvmCompilerMarkPair(cUnit, loc.lowReg, loc.highReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700861 if (update) {
862 loc.location = kLocPhysReg;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800863 dvmCompilerMarkLive(cUnit, loc.lowReg, loc.sRegLow);
864 dvmCompilerMarkLive(cUnit, loc.highReg, dvmCompilerSRegHi(loc.sRegLow));
Bill Buzbee1465db52009-09-23 17:17:35 -0700865 }
866 assert(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
867 return loc;
868}
869
Bill Buzbeec6f10662010-02-09 11:16:15 -0800870extern RegLocation dvmCompilerEvalLoc(CompilationUnit *cUnit, RegLocation loc,
871 int regClass, bool update)
Bill Buzbee1465db52009-09-23 17:17:35 -0700872{
873 RegisterInfo *infoLo = NULL;
874 int newReg;
875 if (loc.wide)
876 return evalLocWide(cUnit, loc, regClass, update);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800877 loc = dvmCompilerUpdateLoc(cUnit, loc);
Bill Buzbee1465db52009-09-23 17:17:35 -0700878
879 if (loc.location == kLocPhysReg) {
880 if (!regClassMatches(regClass, loc.lowReg)) {
881 /* Wrong register class. Realloc, copy and transfer ownership */
Ben Cheng5d90c202009-11-22 23:31:11 -0800882 newReg = dvmCompilerAllocTypedTemp(cUnit, loc.fp, regClass);
883 dvmCompilerRegCopy(cUnit, newReg, loc.lowReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700884 copyRegInfo(cUnit, newReg, loc.lowReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800885 dvmCompilerClobber(cUnit, loc.lowReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700886 loc.lowReg = newReg;
887 }
888 return loc;
889 }
890
891 assert((loc.location != kLocRetval) || (loc.sRegLow == INVALID_SREG));
892
Ben Cheng5d90c202009-11-22 23:31:11 -0800893 newReg = dvmCompilerAllocTypedTemp(cUnit, loc.fp, regClass);
Bill Buzbee1465db52009-09-23 17:17:35 -0700894 loc.lowReg = newReg;
895
896 if (update) {
897 loc.location = kLocPhysReg;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800898 dvmCompilerMarkLive(cUnit, loc.lowReg, loc.sRegLow);
Bill Buzbee1465db52009-09-23 17:17:35 -0700899 }
900 return loc;
901}
902
Bill Buzbee1465db52009-09-23 17:17:35 -0700903static inline int getDestSSAName(MIR *mir, int num)
904{
905 assert(mir->ssaRep->numDefs > num);
906 return mir->ssaRep->defs[num];
907}
908
909// Get the LocRecord associated with an SSA name use.
Bill Buzbeec6f10662010-02-09 11:16:15 -0800910extern RegLocation dvmCompilerGetSrc(CompilationUnit *cUnit, MIR *mir, int num)
Bill Buzbee1465db52009-09-23 17:17:35 -0700911{
Bill Buzbeec6f10662010-02-09 11:16:15 -0800912 RegLocation loc = cUnit->regLocation[
913 SREG(cUnit, dvmCompilerSSASrc(mir, num))];
914 loc.fp = cUnit->regLocation[dvmCompilerSSASrc(mir, num)].fp;
Bill Buzbee1465db52009-09-23 17:17:35 -0700915 loc.wide = false;
916 return loc;
917}
918
919// Get the LocRecord associated with an SSA name def.
Bill Buzbeec6f10662010-02-09 11:16:15 -0800920extern RegLocation dvmCompilerGetDest(CompilationUnit *cUnit, MIR *mir,
921 int num)
Bill Buzbee1465db52009-09-23 17:17:35 -0700922{
923 RegLocation loc = cUnit->regLocation[SREG(cUnit, getDestSSAName(mir, num))];
924 loc.fp = cUnit->regLocation[getDestSSAName(mir, num)].fp;
925 loc.wide = false;
926 return loc;
927}
928
929static RegLocation getLocWide(CompilationUnit *cUnit, MIR *mir,
Bill Buzbeec6f10662010-02-09 11:16:15 -0800930 int low, int high, bool isSrc)
Bill Buzbee1465db52009-09-23 17:17:35 -0700931{
932 RegLocation lowLoc;
933 RegLocation highLoc;
934 /* Copy loc record for low word and patch in data from high word */
935 if (isSrc) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800936 lowLoc = dvmCompilerGetSrc(cUnit, mir, low);
937 highLoc = dvmCompilerGetSrc(cUnit, mir, high);
Bill Buzbee1465db52009-09-23 17:17:35 -0700938 } else {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800939 lowLoc = dvmCompilerGetDest(cUnit, mir, low);
940 highLoc = dvmCompilerGetDest(cUnit, mir, high);
Bill Buzbee1465db52009-09-23 17:17:35 -0700941 }
942 /* Avoid this case by either promoting both or neither. */
943 assert(lowLoc.location == highLoc.location);
944 if (lowLoc.location == kLocPhysReg) {
945 /* This case shouldn't happen if we've named correctly */
946 assert(lowLoc.fp == highLoc.fp);
947 }
948 lowLoc.wide = true;
949 lowLoc.highReg = highLoc.lowReg;
950 return lowLoc;
951}
Ben Cheng5d90c202009-11-22 23:31:11 -0800952
Bill Buzbeec6f10662010-02-09 11:16:15 -0800953extern RegLocation dvmCompilerGetDestWide(CompilationUnit *cUnit, MIR *mir,
954 int low, int high)
Bill Buzbee1465db52009-09-23 17:17:35 -0700955{
956 return getLocWide(cUnit, mir, low, high, false);
957}
958
Bill Buzbeec6f10662010-02-09 11:16:15 -0800959extern RegLocation dvmCompilerGetSrcWide(CompilationUnit *cUnit, MIR *mir,
Bill Buzbee1465db52009-09-23 17:17:35 -0700960 int low, int high)
961{
962 return getLocWide(cUnit, mir, low, high, true);
963}
964
Bill Buzbeec6f10662010-02-09 11:16:15 -0800965extern RegLocation dvmCompilerGetReturnWide(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -0700966{
967 RegLocation res = LOC_C_RETURN_WIDE;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800968 dvmCompilerClobber(cUnit, r0);
969 dvmCompilerClobber(cUnit, r1);
Elliott Hughes6a555132010-02-25 15:41:42 -0800970 dvmCompilerMarkInUse(cUnit, r0);
971 dvmCompilerMarkInUse(cUnit, r1);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800972 dvmCompilerMarkPair(cUnit, res.lowReg, res.highReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700973 return res;
974}
975
Bill Buzbeec6f10662010-02-09 11:16:15 -0800976extern RegLocation dvmCompilerGetReturnWideAlt(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -0700977{
978 RegLocation res = LOC_C_RETURN_WIDE;
979 res.lowReg = r2;
980 res.highReg = r3;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800981 dvmCompilerClobber(cUnit, r2);
982 dvmCompilerClobber(cUnit, r3);
Elliott Hughes6a555132010-02-25 15:41:42 -0800983 dvmCompilerMarkInUse(cUnit, r2);
984 dvmCompilerMarkInUse(cUnit, r3);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800985 dvmCompilerMarkPair(cUnit, res.lowReg, res.highReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700986 return res;
987}
988
Bill Buzbeec6f10662010-02-09 11:16:15 -0800989extern RegLocation dvmCompilerGetReturn(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -0700990{
991 RegLocation res = LOC_C_RETURN;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800992 dvmCompilerClobber(cUnit, r0);
Elliott Hughes6a555132010-02-25 15:41:42 -0800993 dvmCompilerMarkInUse(cUnit, r0);
Bill Buzbee1465db52009-09-23 17:17:35 -0700994 return res;
995}
996
Bill Buzbeec6f10662010-02-09 11:16:15 -0800997extern RegLocation dvmCompilerGetReturnAlt(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -0700998{
999 RegLocation res = LOC_C_RETURN;
1000 res.lowReg = r1;
Bill Buzbeec6f10662010-02-09 11:16:15 -08001001 dvmCompilerClobber(cUnit, r1);
Elliott Hughes6a555132010-02-25 15:41:42 -08001002 dvmCompilerMarkInUse(cUnit, r1);
Bill Buzbee1465db52009-09-23 17:17:35 -07001003 return res;
1004}
1005
1006/* Kill the corresponding bit in the null-checked register list */
Bill Buzbeec6f10662010-02-09 11:16:15 -08001007extern void dvmCompilerKillNullCheckedLoc(CompilationUnit *cUnit,
1008 RegLocation loc)
Bill Buzbee1465db52009-09-23 17:17:35 -07001009{
1010 if (loc.location != kLocRetval) {
1011 assert(loc.sRegLow != INVALID_SREG);
1012 dvmClearBit(cUnit->regPool->nullCheckedRegs, loc.sRegLow);
1013 if (loc.wide) {
Bill Buzbeec6f10662010-02-09 11:16:15 -08001014 assert(dvmCompilerSRegHi(loc.sRegLow) != INVALID_SREG);
1015 dvmClearBit(cUnit->regPool->nullCheckedRegs,
1016 dvmCompilerSRegHi(loc.sRegLow));
Bill Buzbee1465db52009-09-23 17:17:35 -07001017 }
1018 }
1019}
Ben Cheng5d90c202009-11-22 23:31:11 -08001020
1021extern void dvmCompilerFlushRegWideForV5TEVFP(CompilationUnit *cUnit,
1022 int reg1, int reg2)
1023{
1024 flushRegWide(cUnit, reg1, reg2);
1025}
1026
1027extern void dvmCompilerFlushRegForV5TEVFP(CompilationUnit *cUnit, int reg)
1028{
1029 flushReg(cUnit, reg);
1030}