blob: 80ce968204333849d64337996ff3f3298b6e5ee2 [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
Bill Buzbee1465db52009-09-23 17:17:35 -0700466/* Clobber all regs that might be used by an external C call */
Elliott Hughes6a555132010-02-25 15:41:42 -0800467extern void dvmCompilerClobberCallRegs(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -0700468{
Bill Buzbeec6f10662010-02-09 11:16:15 -0800469 dvmCompilerClobber(cUnit, r0);
470 dvmCompilerClobber(cUnit, r1);
471 dvmCompilerClobber(cUnit, r2);
472 dvmCompilerClobber(cUnit, r3);
Elliott Hughes6a555132010-02-25 15:41:42 -0800473 dvmCompilerClobber(cUnit, r9); // Need to do this?, be conservative
Bill Buzbeec6f10662010-02-09 11:16:15 -0800474 dvmCompilerClobber(cUnit, r11);
475 dvmCompilerClobber(cUnit, r12);
476 dvmCompilerClobber(cUnit, rlr);
Bill Buzbee1465db52009-09-23 17:17:35 -0700477}
478
479/* Clobber all of the temps that might be used by a handler. */
Bill Buzbeec6f10662010-02-09 11:16:15 -0800480extern void dvmCompilerClobberHandlerRegs(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -0700481{
482 //TUNING: reduce the set of regs used by handlers. Only a few need lots.
Elliott Hughes6a555132010-02-25 15:41:42 -0800483 dvmCompilerClobberCallRegs(cUnit);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800484 dvmCompilerClobber(cUnit, r4PC);
485 dvmCompilerClobber(cUnit, r9);
486 dvmCompilerClobber(cUnit, r10);
Bill Buzbee1465db52009-09-23 17:17:35 -0700487}
488
Bill Buzbeec6f10662010-02-09 11:16:15 -0800489extern void dvmCompilerResetDef(CompilationUnit *cUnit, int reg)
Bill Buzbee1465db52009-09-23 17:17:35 -0700490{
491 RegisterInfo *p = getRegInfo(cUnit, reg);
492 p->defStart = NULL;
493 p->defEnd = NULL;
494}
495
496static void nullifyRange(CompilationUnit *cUnit, LIR *start, LIR *finish,
497 int sReg1, int sReg2)
498{
499 if (start && finish) {
500 LIR *p;
501 assert(sReg1 == sReg2);
502 for (p = start; ;p = p->next) {
503 ((ArmLIR *)p)->isNop = true;
504 if (p == finish)
505 break;
506 }
507 }
508}
509
510/*
511 * Mark the beginning and end LIR of a def sequence. Note that
512 * on entry start points to the LIR prior to the beginning of the
513 * sequence.
514 */
Bill Buzbeec6f10662010-02-09 11:16:15 -0800515extern void dvmCompilerMarkDef(CompilationUnit *cUnit, RegLocation rl,
Bill Buzbee1465db52009-09-23 17:17:35 -0700516 LIR *start, LIR *finish)
517{
518 assert(!rl.wide);
519 assert(start && start->next);
520 assert(finish);
521 RegisterInfo *p = getRegInfo(cUnit, rl.lowReg);
522 p->defStart = start->next;
523 p->defEnd = finish;
524}
525
526/*
527 * Mark the beginning and end LIR of a def sequence. Note that
528 * on entry start points to the LIR prior to the beginning of the
529 * sequence.
530 */
Bill Buzbeec6f10662010-02-09 11:16:15 -0800531extern void dvmCompilerMarkDefWide(CompilationUnit *cUnit, RegLocation rl,
Bill Buzbee1465db52009-09-23 17:17:35 -0700532 LIR *start, LIR *finish)
533{
534 assert(rl.wide);
535 assert(start && start->next);
536 assert(finish);
537 RegisterInfo *p = getRegInfo(cUnit, rl.lowReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800538 dvmCompilerResetDef(cUnit, rl.highReg); // Only track low of pair
Bill Buzbee1465db52009-09-23 17:17:35 -0700539 p->defStart = start->next;
540 p->defEnd = finish;
541}
542
Bill Buzbeec6f10662010-02-09 11:16:15 -0800543extern RegLocation dvmCompilerWideToNarrow(CompilationUnit *cUnit,
544 RegLocation rl)
Bill Buzbee1465db52009-09-23 17:17:35 -0700545{
546 assert(rl.wide);
547 if (rl.location == kLocPhysReg) {
548 RegisterInfo *infoLo = getRegInfo(cUnit, rl.lowReg);
549 RegisterInfo *infoHi = getRegInfo(cUnit, rl.highReg);
550 if (!infoLo->pair) {
Ben Cheng5d90c202009-11-22 23:31:11 -0800551 dumpRegPool(cUnit->regPool->coreTemps,
552 cUnit->regPool->numCoreTemps);
Bill Buzbee1465db52009-09-23 17:17:35 -0700553 assert(infoLo->pair);
554 }
555 if (!infoHi->pair) {
Ben Cheng5d90c202009-11-22 23:31:11 -0800556 dumpRegPool(cUnit->regPool->coreTemps,
557 cUnit->regPool->numCoreTemps);
Bill Buzbee1465db52009-09-23 17:17:35 -0700558 assert(infoHi->pair);
559 }
560 assert(infoLo->pair);
561 assert(infoHi->pair);
562 assert(infoLo->partner == infoHi->reg);
563 assert(infoHi->partner == infoLo->reg);
564 infoLo->pair = false;
565 infoHi->pair = false;
566 infoLo->defStart = NULL;
567 infoLo->defEnd = NULL;
568 infoHi->defStart = NULL;
569 infoHi->defEnd = NULL;
570 }
571 rl.wide = false;
572 return rl;
573}
574
Bill Buzbeec6f10662010-02-09 11:16:15 -0800575extern void dvmCompilerResetDefLoc(CompilationUnit *cUnit, RegLocation rl)
Bill Buzbee1465db52009-09-23 17:17:35 -0700576{
577 assert(!rl.wide);
578 if (!(gDvmJit.disableOpt & (1 << kSuppressLoads))) {
579 RegisterInfo *p = getRegInfo(cUnit, rl.lowReg);
580 assert(!p->pair);
581 nullifyRange(cUnit, p->defStart, p->defEnd,
582 p->sReg, rl.sRegLow);
583 }
Bill Buzbeec6f10662010-02-09 11:16:15 -0800584 dvmCompilerResetDef(cUnit, rl.lowReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700585}
586
Bill Buzbeec6f10662010-02-09 11:16:15 -0800587extern void dvmCompilerResetDefLocWide(CompilationUnit *cUnit, RegLocation rl)
Bill Buzbee1465db52009-09-23 17:17:35 -0700588{
589 assert(rl.wide);
590 if (!(gDvmJit.disableOpt & (1 << kSuppressLoads))) {
591 RegisterInfo *p = getRegInfo(cUnit, rl.lowReg);
592 assert(p->pair);
593 nullifyRange(cUnit, p->defStart, p->defEnd,
594 p->sReg, rl.sRegLow);
595 }
Bill Buzbeec6f10662010-02-09 11:16:15 -0800596 dvmCompilerResetDef(cUnit, rl.lowReg);
597 dvmCompilerResetDef(cUnit, rl.highReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700598}
599
Bill Buzbeec6f10662010-02-09 11:16:15 -0800600extern void dvmCompilerResetDefTracking(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -0700601{
602 int i;
603 for (i=0; i< cUnit->regPool->numCoreTemps; i++) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800604 dvmCompilerResetDef(cUnit, cUnit->regPool->coreTemps[i].reg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700605 }
606 for (i=0; i< cUnit->regPool->numFPTemps; i++) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800607 dvmCompilerResetDef(cUnit, cUnit->regPool->FPTemps[i].reg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700608 }
609}
610
Bill Buzbeec6f10662010-02-09 11:16:15 -0800611extern void dvmCompilerClobberAllRegs(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -0700612{
613 int i;
614 for (i=0; i< cUnit->regPool->numCoreTemps; i++) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800615 dvmCompilerClobber(cUnit, cUnit->regPool->coreTemps[i].reg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700616 }
617 for (i=0; i< cUnit->regPool->numFPTemps; i++) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800618 dvmCompilerClobber(cUnit, cUnit->regPool->FPTemps[i].reg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700619 }
620}
621
622/* To be used when explicitly managing register use */
Bill Buzbeec6f10662010-02-09 11:16:15 -0800623extern void dvmCompilerLockAllTemps(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -0700624{
625 int i;
626 for (i=0; i< cUnit->regPool->numCoreTemps; i++) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800627 dvmCompilerLockTemp(cUnit, cUnit->regPool->coreTemps[i].reg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700628 }
629}
630
631// Make sure nothing is live and dirty
632static void flushAllRegsBody(CompilationUnit *cUnit, RegisterInfo *info,
633 int numRegs)
634{
635 int i;
636 for (i=0; i < numRegs; i++) {
637 if (info[i].live && info[i].dirty) {
638 if (info[i].pair) {
639 flushRegWide(cUnit, info[i].reg, info[i].partner);
640 } else {
641 flushReg(cUnit, info[i].reg);
642 }
643 }
644 }
645}
646
Bill Buzbeec6f10662010-02-09 11:16:15 -0800647extern void dvmCompilerFlushAllRegs(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -0700648{
649 flushAllRegsBody(cUnit, cUnit->regPool->coreTemps,
650 cUnit->regPool->numCoreTemps);
651 flushAllRegsBody(cUnit, cUnit->regPool->FPTemps,
652 cUnit->regPool->numFPTemps);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800653 dvmCompilerClobberAllRegs(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700654}
655
656
657//TUNING: rewrite all of this reg stuff. Probably use an attribute table
658static bool regClassMatches(int regClass, int reg)
659{
660 if (regClass == kAnyReg) {
661 return true;
662 } else if (regClass == kCoreReg) {
663 return !FPREG(reg);
664 } else {
665 return FPREG(reg);
666 }
667}
668
Bill Buzbeec6f10662010-02-09 11:16:15 -0800669extern void dvmCompilerMarkLive(CompilationUnit *cUnit, int reg, int sReg)
Bill Buzbee1465db52009-09-23 17:17:35 -0700670{
671 RegisterInfo *info = getRegInfo(cUnit, reg);
672 if ((info->reg == reg) && (info->sReg == sReg) && info->live) {
673 return; /* already live */
674 } else if (sReg != INVALID_SREG) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800675 dvmCompilerClobberSReg(cUnit, sReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700676 info->live = true;
677 } else {
678 /* Can't be live if no associated sReg */
679 info->live = false;
680 }
681 info->sReg = sReg;
682}
683
Bill Buzbeec6f10662010-02-09 11:16:15 -0800684extern void dvmCompilerMarkPair(CompilationUnit *cUnit, int lowReg, int highReg)
Bill Buzbee1465db52009-09-23 17:17:35 -0700685{
686 RegisterInfo *infoLo = getRegInfo(cUnit, lowReg);
687 RegisterInfo *infoHi = getRegInfo(cUnit, highReg);
688 infoLo->pair = infoHi->pair = true;
689 infoLo->partner = highReg;
690 infoHi->partner = lowReg;
691}
692
Bill Buzbeec6f10662010-02-09 11:16:15 -0800693extern void dvmCompilerMarkClean(CompilationUnit *cUnit, int reg)
Bill Buzbee1465db52009-09-23 17:17:35 -0700694{
695 RegisterInfo *info = getRegInfo(cUnit, reg);
696 info->dirty = false;
697}
698
Bill Buzbeec6f10662010-02-09 11:16:15 -0800699extern void dvmCompilerMarkDirty(CompilationUnit *cUnit, int reg)
Bill Buzbee1465db52009-09-23 17:17:35 -0700700{
701 RegisterInfo *info = getRegInfo(cUnit, reg);
702 info->dirty = true;
703}
704
Elliott Hughes6a555132010-02-25 15:41:42 -0800705extern void dvmCompilerMarkInUse(CompilationUnit *cUnit, int reg)
Bill Buzbee1465db52009-09-23 17:17:35 -0700706{
Ben Cheng5d90c202009-11-22 23:31:11 -0800707 RegisterInfo *info = getRegInfo(cUnit, reg);
708 info->inUse = true;
Bill Buzbee1465db52009-09-23 17:17:35 -0700709}
710
Bill Buzbee1465db52009-09-23 17:17:35 -0700711void copyRegInfo(CompilationUnit *cUnit, int newReg, int oldReg)
712{
713 RegisterInfo *newInfo = getRegInfo(cUnit, newReg);
714 RegisterInfo *oldInfo = getRegInfo(cUnit, oldReg);
715 *newInfo = *oldInfo;
716 newInfo->reg = newReg;
717}
718
719/*
720 * Return an updated location record with current in-register status.
721 * If the value lives in live temps, reflect that fact. No code
722 * is generated. The the live value is part of an older pair,
723 * clobber both low and high.
724 * TUNING: clobbering both is a bit heavy-handed, but the alternative
725 * is a bit complex when dealing with FP regs. Examine code to see
726 * if it's worthwhile trying to be more clever here.
727 */
Bill Buzbeec6f10662010-02-09 11:16:15 -0800728extern RegLocation dvmCompilerUpdateLoc(CompilationUnit *cUnit, RegLocation loc)
Bill Buzbee1465db52009-09-23 17:17:35 -0700729{
730 assert(!loc.wide);
731 if (loc.location == kLocDalvikFrame) {
732 RegisterInfo *infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
733 if (infoLo) {
734 if (infoLo->pair) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800735 dvmCompilerClobber(cUnit, infoLo->reg);
736 dvmCompilerClobber(cUnit, infoLo->partner);
Bill Buzbee1465db52009-09-23 17:17:35 -0700737 } else {
738 loc.lowReg = infoLo->reg;
739 loc.location = kLocPhysReg;
740 }
741 }
742 }
743
744 return loc;
745}
746
747/* see comments for updateLoc */
Bill Buzbeec6f10662010-02-09 11:16:15 -0800748extern RegLocation dvmCompilerUpdateLocWide(CompilationUnit *cUnit,
749 RegLocation loc)
Bill Buzbee1465db52009-09-23 17:17:35 -0700750{
751 assert(loc.wide);
752 if (loc.location == kLocDalvikFrame) {
Bill Buzbee80cef862010-03-25 10:38:34 -0700753 // Are the dalvik regs already live in physical registers?
Bill Buzbee1465db52009-09-23 17:17:35 -0700754 RegisterInfo *infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800755 RegisterInfo *infoHi = allocLive(cUnit,
756 dvmCompilerSRegHi(loc.sRegLow), kAnyReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700757 bool match = true;
758 match = match && (infoLo != NULL);
759 match = match && (infoHi != NULL);
Bill Buzbee80cef862010-03-25 10:38:34 -0700760 // Are they both core or both FP?
Bill Buzbee1465db52009-09-23 17:17:35 -0700761 match = match && (FPREG(infoLo->reg) == FPREG(infoHi->reg));
Bill Buzbee80cef862010-03-25 10:38:34 -0700762 // If a pair of floating point singles, are they properly aligned?
Bill Buzbee1465db52009-09-23 17:17:35 -0700763 if (match && FPREG(infoLo->reg)) {
764 match &= ((infoLo->reg & 0x1) == 0);
765 match &= ((infoHi->reg - infoLo->reg) == 1);
766 }
Bill Buzbee80cef862010-03-25 10:38:34 -0700767 // If previously used as a pair, it is the same pair?
768 if (match && (infoLo->pair || infoHi->pair)) {
769 match = (infoLo->pair == infoHi->pair);
770 match &= ((infoLo->reg == infoHi->partner) &&
771 (infoHi->reg == infoLo->partner));
772 }
Bill Buzbee1465db52009-09-23 17:17:35 -0700773 if (match) {
Bill Buzbee80cef862010-03-25 10:38:34 -0700774 // Can reuse - update the register usage info
Bill Buzbee1465db52009-09-23 17:17:35 -0700775 loc.lowReg = infoLo->reg;
776 loc.highReg = infoHi->reg;
777 loc.location = kLocPhysReg;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800778 dvmCompilerMarkPair(cUnit, loc.lowReg, loc.highReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700779 assert(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
780 return loc;
781 }
Bill Buzbee80cef862010-03-25 10:38:34 -0700782 // Can't easily reuse - clobber any overlaps
Bill Buzbee1465db52009-09-23 17:17:35 -0700783 if (infoLo) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800784 dvmCompilerClobber(cUnit, infoLo->reg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700785 if (infoLo->pair)
Bill Buzbeec6f10662010-02-09 11:16:15 -0800786 dvmCompilerClobber(cUnit, infoLo->partner);
Bill Buzbee1465db52009-09-23 17:17:35 -0700787 }
788 if (infoHi) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800789 dvmCompilerClobber(cUnit, infoHi->reg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700790 if (infoHi->pair)
Bill Buzbeec6f10662010-02-09 11:16:15 -0800791 dvmCompilerClobber(cUnit, infoHi->partner);
Bill Buzbee1465db52009-09-23 17:17:35 -0700792 }
793 }
794
795 return loc;
796}
797
798static RegLocation evalLocWide(CompilationUnit *cUnit, RegLocation loc,
799 int regClass, bool update)
800{
801 assert(loc.wide);
802 int newRegs;
803 int lowReg;
804 int highReg;
805
Bill Buzbeec6f10662010-02-09 11:16:15 -0800806 loc = dvmCompilerUpdateLocWide(cUnit, loc);
Bill Buzbee1465db52009-09-23 17:17:35 -0700807
808 /* If already in registers, we can assume proper form. Right reg class? */
809 if (loc.location == kLocPhysReg) {
810 assert(FPREG(loc.lowReg) == FPREG(loc.highReg));
811 assert(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
812 if (!regClassMatches(regClass, loc.lowReg)) {
813 /* Wrong register class. Reallocate and copy */
Ben Cheng5d90c202009-11-22 23:31:11 -0800814 newRegs = dvmCompilerAllocTypedTempPair(cUnit, loc.fp, regClass);
Bill Buzbee1465db52009-09-23 17:17:35 -0700815 lowReg = newRegs & 0xff;
816 highReg = (newRegs >> 8) & 0xff;
Ben Cheng5d90c202009-11-22 23:31:11 -0800817 dvmCompilerRegCopyWide(cUnit, lowReg, highReg, loc.lowReg,
818 loc.highReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700819 copyRegInfo(cUnit, lowReg, loc.lowReg);
820 copyRegInfo(cUnit, highReg, loc.highReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800821 dvmCompilerClobber(cUnit, loc.lowReg);
822 dvmCompilerClobber(cUnit, loc.highReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700823 loc.lowReg = lowReg;
824 loc.highReg = highReg;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800825 dvmCompilerMarkPair(cUnit, loc.lowReg, loc.highReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700826 assert(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
827 }
828 return loc;
829 }
830
831 assert((loc.location != kLocRetval) || (loc.sRegLow == INVALID_SREG));
Ben Cheng5d90c202009-11-22 23:31:11 -0800832 assert((loc.location != kLocRetval) ||
Bill Buzbeec6f10662010-02-09 11:16:15 -0800833 (dvmCompilerSRegHi(loc.sRegLow) == INVALID_SREG));
Bill Buzbee1465db52009-09-23 17:17:35 -0700834
Ben Cheng5d90c202009-11-22 23:31:11 -0800835 newRegs = dvmCompilerAllocTypedTempPair(cUnit, loc.fp, regClass);
Bill Buzbee1465db52009-09-23 17:17:35 -0700836 loc.lowReg = newRegs & 0xff;
837 loc.highReg = (newRegs >> 8) & 0xff;
838
Bill Buzbeec6f10662010-02-09 11:16:15 -0800839 dvmCompilerMarkPair(cUnit, loc.lowReg, loc.highReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700840 if (update) {
841 loc.location = kLocPhysReg;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800842 dvmCompilerMarkLive(cUnit, loc.lowReg, loc.sRegLow);
843 dvmCompilerMarkLive(cUnit, loc.highReg, dvmCompilerSRegHi(loc.sRegLow));
Bill Buzbee1465db52009-09-23 17:17:35 -0700844 }
845 assert(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
846 return loc;
847}
848
Bill Buzbeec6f10662010-02-09 11:16:15 -0800849extern RegLocation dvmCompilerEvalLoc(CompilationUnit *cUnit, RegLocation loc,
850 int regClass, bool update)
Bill Buzbee1465db52009-09-23 17:17:35 -0700851{
Bill Buzbee1465db52009-09-23 17:17:35 -0700852 int newReg;
853 if (loc.wide)
854 return evalLocWide(cUnit, loc, regClass, update);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800855 loc = dvmCompilerUpdateLoc(cUnit, loc);
Bill Buzbee1465db52009-09-23 17:17:35 -0700856
857 if (loc.location == kLocPhysReg) {
858 if (!regClassMatches(regClass, loc.lowReg)) {
859 /* Wrong register class. Realloc, copy and transfer ownership */
Ben Cheng5d90c202009-11-22 23:31:11 -0800860 newReg = dvmCompilerAllocTypedTemp(cUnit, loc.fp, regClass);
861 dvmCompilerRegCopy(cUnit, newReg, loc.lowReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700862 copyRegInfo(cUnit, newReg, loc.lowReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800863 dvmCompilerClobber(cUnit, loc.lowReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700864 loc.lowReg = newReg;
865 }
866 return loc;
867 }
868
869 assert((loc.location != kLocRetval) || (loc.sRegLow == INVALID_SREG));
870
Ben Cheng5d90c202009-11-22 23:31:11 -0800871 newReg = dvmCompilerAllocTypedTemp(cUnit, loc.fp, regClass);
Bill Buzbee1465db52009-09-23 17:17:35 -0700872 loc.lowReg = newReg;
873
874 if (update) {
875 loc.location = kLocPhysReg;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800876 dvmCompilerMarkLive(cUnit, loc.lowReg, loc.sRegLow);
Bill Buzbee1465db52009-09-23 17:17:35 -0700877 }
878 return loc;
879}
880
Bill Buzbee1465db52009-09-23 17:17:35 -0700881static inline int getDestSSAName(MIR *mir, int num)
882{
883 assert(mir->ssaRep->numDefs > num);
884 return mir->ssaRep->defs[num];
885}
886
887// Get the LocRecord associated with an SSA name use.
Bill Buzbeec6f10662010-02-09 11:16:15 -0800888extern RegLocation dvmCompilerGetSrc(CompilationUnit *cUnit, MIR *mir, int num)
Bill Buzbee1465db52009-09-23 17:17:35 -0700889{
Bill Buzbeec6f10662010-02-09 11:16:15 -0800890 RegLocation loc = cUnit->regLocation[
891 SREG(cUnit, dvmCompilerSSASrc(mir, num))];
892 loc.fp = cUnit->regLocation[dvmCompilerSSASrc(mir, num)].fp;
Bill Buzbee1465db52009-09-23 17:17:35 -0700893 loc.wide = false;
894 return loc;
895}
896
897// Get the LocRecord associated with an SSA name def.
Bill Buzbeec6f10662010-02-09 11:16:15 -0800898extern RegLocation dvmCompilerGetDest(CompilationUnit *cUnit, MIR *mir,
899 int num)
Bill Buzbee1465db52009-09-23 17:17:35 -0700900{
901 RegLocation loc = cUnit->regLocation[SREG(cUnit, getDestSSAName(mir, num))];
902 loc.fp = cUnit->regLocation[getDestSSAName(mir, num)].fp;
903 loc.wide = false;
904 return loc;
905}
906
907static RegLocation getLocWide(CompilationUnit *cUnit, MIR *mir,
Bill Buzbeec6f10662010-02-09 11:16:15 -0800908 int low, int high, bool isSrc)
Bill Buzbee1465db52009-09-23 17:17:35 -0700909{
910 RegLocation lowLoc;
911 RegLocation highLoc;
912 /* Copy loc record for low word and patch in data from high word */
913 if (isSrc) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800914 lowLoc = dvmCompilerGetSrc(cUnit, mir, low);
915 highLoc = dvmCompilerGetSrc(cUnit, mir, high);
Bill Buzbee1465db52009-09-23 17:17:35 -0700916 } else {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800917 lowLoc = dvmCompilerGetDest(cUnit, mir, low);
918 highLoc = dvmCompilerGetDest(cUnit, mir, high);
Bill Buzbee1465db52009-09-23 17:17:35 -0700919 }
920 /* Avoid this case by either promoting both or neither. */
921 assert(lowLoc.location == highLoc.location);
922 if (lowLoc.location == kLocPhysReg) {
923 /* This case shouldn't happen if we've named correctly */
924 assert(lowLoc.fp == highLoc.fp);
925 }
926 lowLoc.wide = true;
927 lowLoc.highReg = highLoc.lowReg;
928 return lowLoc;
929}
Ben Cheng5d90c202009-11-22 23:31:11 -0800930
Bill Buzbeec6f10662010-02-09 11:16:15 -0800931extern RegLocation dvmCompilerGetDestWide(CompilationUnit *cUnit, MIR *mir,
932 int low, int high)
Bill Buzbee1465db52009-09-23 17:17:35 -0700933{
934 return getLocWide(cUnit, mir, low, high, false);
935}
936
Bill Buzbeec6f10662010-02-09 11:16:15 -0800937extern RegLocation dvmCompilerGetSrcWide(CompilationUnit *cUnit, MIR *mir,
Bill Buzbee1465db52009-09-23 17:17:35 -0700938 int low, int high)
939{
940 return getLocWide(cUnit, mir, low, high, true);
941}
942
Bill Buzbeec6f10662010-02-09 11:16:15 -0800943extern RegLocation dvmCompilerGetReturnWide(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -0700944{
945 RegLocation res = LOC_C_RETURN_WIDE;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800946 dvmCompilerClobber(cUnit, r0);
947 dvmCompilerClobber(cUnit, r1);
Elliott Hughes6a555132010-02-25 15:41:42 -0800948 dvmCompilerMarkInUse(cUnit, r0);
949 dvmCompilerMarkInUse(cUnit, r1);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800950 dvmCompilerMarkPair(cUnit, res.lowReg, res.highReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700951 return res;
952}
953
Bill Buzbeec6f10662010-02-09 11:16:15 -0800954extern RegLocation dvmCompilerGetReturnWideAlt(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -0700955{
956 RegLocation res = LOC_C_RETURN_WIDE;
957 res.lowReg = r2;
958 res.highReg = r3;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800959 dvmCompilerClobber(cUnit, r2);
960 dvmCompilerClobber(cUnit, r3);
Elliott Hughes6a555132010-02-25 15:41:42 -0800961 dvmCompilerMarkInUse(cUnit, r2);
962 dvmCompilerMarkInUse(cUnit, r3);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800963 dvmCompilerMarkPair(cUnit, res.lowReg, res.highReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700964 return res;
965}
966
Bill Buzbeec6f10662010-02-09 11:16:15 -0800967extern RegLocation dvmCompilerGetReturn(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -0700968{
969 RegLocation res = LOC_C_RETURN;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800970 dvmCompilerClobber(cUnit, r0);
Elliott Hughes6a555132010-02-25 15:41:42 -0800971 dvmCompilerMarkInUse(cUnit, r0);
Bill Buzbee1465db52009-09-23 17:17:35 -0700972 return res;
973}
974
Bill Buzbeec6f10662010-02-09 11:16:15 -0800975extern RegLocation dvmCompilerGetReturnAlt(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -0700976{
977 RegLocation res = LOC_C_RETURN;
978 res.lowReg = r1;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800979 dvmCompilerClobber(cUnit, r1);
Elliott Hughes6a555132010-02-25 15:41:42 -0800980 dvmCompilerMarkInUse(cUnit, r1);
Bill Buzbee1465db52009-09-23 17:17:35 -0700981 return res;
982}
983
984/* Kill the corresponding bit in the null-checked register list */
Bill Buzbeec6f10662010-02-09 11:16:15 -0800985extern void dvmCompilerKillNullCheckedLoc(CompilationUnit *cUnit,
986 RegLocation loc)
Bill Buzbee1465db52009-09-23 17:17:35 -0700987{
988 if (loc.location != kLocRetval) {
989 assert(loc.sRegLow != INVALID_SREG);
990 dvmClearBit(cUnit->regPool->nullCheckedRegs, loc.sRegLow);
991 if (loc.wide) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800992 assert(dvmCompilerSRegHi(loc.sRegLow) != INVALID_SREG);
993 dvmClearBit(cUnit->regPool->nullCheckedRegs,
994 dvmCompilerSRegHi(loc.sRegLow));
Bill Buzbee1465db52009-09-23 17:17:35 -0700995 }
996 }
997}
Ben Cheng5d90c202009-11-22 23:31:11 -0800998
999extern void dvmCompilerFlushRegWideForV5TEVFP(CompilationUnit *cUnit,
1000 int reg1, int reg2)
1001{
1002 flushRegWide(cUnit, reg1, reg2);
1003}
1004
1005extern void dvmCompilerFlushRegForV5TEVFP(CompilationUnit *cUnit, int reg)
1006{
1007 flushReg(cUnit, reg);
1008}