blob: ff5d16be11e30177f3cddb303bdbaa468308633a [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);
Bill Buzbeef8315e22010-06-23 16:36:50 -0700485 dvmCompilerClobber(cUnit, r7);
486 dvmCompilerClobber(cUnit, r8);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800487 dvmCompilerClobber(cUnit, r9);
488 dvmCompilerClobber(cUnit, r10);
Bill Buzbee1465db52009-09-23 17:17:35 -0700489}
490
Bill Buzbeec6f10662010-02-09 11:16:15 -0800491extern void dvmCompilerResetDef(CompilationUnit *cUnit, int reg)
Bill Buzbee1465db52009-09-23 17:17:35 -0700492{
493 RegisterInfo *p = getRegInfo(cUnit, reg);
494 p->defStart = NULL;
495 p->defEnd = NULL;
496}
497
498static void nullifyRange(CompilationUnit *cUnit, LIR *start, LIR *finish,
499 int sReg1, int sReg2)
500{
501 if (start && finish) {
502 LIR *p;
503 assert(sReg1 == sReg2);
504 for (p = start; ;p = p->next) {
505 ((ArmLIR *)p)->isNop = true;
506 if (p == finish)
507 break;
508 }
509 }
510}
511
512/*
513 * Mark the beginning and end LIR of a def sequence. Note that
514 * on entry start points to the LIR prior to the beginning of the
515 * sequence.
516 */
Bill Buzbeec6f10662010-02-09 11:16:15 -0800517extern void dvmCompilerMarkDef(CompilationUnit *cUnit, RegLocation rl,
Bill Buzbee1465db52009-09-23 17:17:35 -0700518 LIR *start, LIR *finish)
519{
520 assert(!rl.wide);
521 assert(start && start->next);
522 assert(finish);
523 RegisterInfo *p = getRegInfo(cUnit, rl.lowReg);
524 p->defStart = start->next;
525 p->defEnd = finish;
526}
527
528/*
529 * Mark the beginning and end LIR of a def sequence. Note that
530 * on entry start points to the LIR prior to the beginning of the
531 * sequence.
532 */
Bill Buzbeec6f10662010-02-09 11:16:15 -0800533extern void dvmCompilerMarkDefWide(CompilationUnit *cUnit, RegLocation rl,
Bill Buzbee1465db52009-09-23 17:17:35 -0700534 LIR *start, LIR *finish)
535{
536 assert(rl.wide);
537 assert(start && start->next);
538 assert(finish);
539 RegisterInfo *p = getRegInfo(cUnit, rl.lowReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800540 dvmCompilerResetDef(cUnit, rl.highReg); // Only track low of pair
Bill Buzbee1465db52009-09-23 17:17:35 -0700541 p->defStart = start->next;
542 p->defEnd = finish;
543}
544
Bill Buzbeec6f10662010-02-09 11:16:15 -0800545extern RegLocation dvmCompilerWideToNarrow(CompilationUnit *cUnit,
546 RegLocation rl)
Bill Buzbee1465db52009-09-23 17:17:35 -0700547{
548 assert(rl.wide);
549 if (rl.location == kLocPhysReg) {
550 RegisterInfo *infoLo = getRegInfo(cUnit, rl.lowReg);
551 RegisterInfo *infoHi = getRegInfo(cUnit, rl.highReg);
552 if (!infoLo->pair) {
Ben Cheng5d90c202009-11-22 23:31:11 -0800553 dumpRegPool(cUnit->regPool->coreTemps,
554 cUnit->regPool->numCoreTemps);
Bill Buzbee1465db52009-09-23 17:17:35 -0700555 assert(infoLo->pair);
556 }
557 if (!infoHi->pair) {
Ben Cheng5d90c202009-11-22 23:31:11 -0800558 dumpRegPool(cUnit->regPool->coreTemps,
559 cUnit->regPool->numCoreTemps);
Bill Buzbee1465db52009-09-23 17:17:35 -0700560 assert(infoHi->pair);
561 }
562 assert(infoLo->pair);
563 assert(infoHi->pair);
564 assert(infoLo->partner == infoHi->reg);
565 assert(infoHi->partner == infoLo->reg);
566 infoLo->pair = false;
567 infoHi->pair = false;
568 infoLo->defStart = NULL;
569 infoLo->defEnd = NULL;
570 infoHi->defStart = NULL;
571 infoHi->defEnd = NULL;
572 }
573 rl.wide = false;
574 return rl;
575}
576
Bill Buzbeec6f10662010-02-09 11:16:15 -0800577extern void dvmCompilerResetDefLoc(CompilationUnit *cUnit, RegLocation rl)
Bill Buzbee1465db52009-09-23 17:17:35 -0700578{
579 assert(!rl.wide);
580 if (!(gDvmJit.disableOpt & (1 << kSuppressLoads))) {
581 RegisterInfo *p = getRegInfo(cUnit, rl.lowReg);
582 assert(!p->pair);
583 nullifyRange(cUnit, p->defStart, p->defEnd,
584 p->sReg, rl.sRegLow);
585 }
Bill Buzbeec6f10662010-02-09 11:16:15 -0800586 dvmCompilerResetDef(cUnit, rl.lowReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700587}
588
Bill Buzbeec6f10662010-02-09 11:16:15 -0800589extern void dvmCompilerResetDefLocWide(CompilationUnit *cUnit, RegLocation rl)
Bill Buzbee1465db52009-09-23 17:17:35 -0700590{
591 assert(rl.wide);
592 if (!(gDvmJit.disableOpt & (1 << kSuppressLoads))) {
593 RegisterInfo *p = getRegInfo(cUnit, rl.lowReg);
594 assert(p->pair);
595 nullifyRange(cUnit, p->defStart, p->defEnd,
596 p->sReg, rl.sRegLow);
597 }
Bill Buzbeec6f10662010-02-09 11:16:15 -0800598 dvmCompilerResetDef(cUnit, rl.lowReg);
599 dvmCompilerResetDef(cUnit, rl.highReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700600}
601
Bill Buzbeec6f10662010-02-09 11:16:15 -0800602extern void dvmCompilerResetDefTracking(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -0700603{
604 int i;
605 for (i=0; i< cUnit->regPool->numCoreTemps; i++) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800606 dvmCompilerResetDef(cUnit, cUnit->regPool->coreTemps[i].reg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700607 }
608 for (i=0; i< cUnit->regPool->numFPTemps; i++) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800609 dvmCompilerResetDef(cUnit, cUnit->regPool->FPTemps[i].reg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700610 }
611}
612
Bill Buzbeec6f10662010-02-09 11:16:15 -0800613extern void dvmCompilerClobberAllRegs(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -0700614{
615 int i;
616 for (i=0; i< cUnit->regPool->numCoreTemps; i++) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800617 dvmCompilerClobber(cUnit, cUnit->regPool->coreTemps[i].reg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700618 }
619 for (i=0; i< cUnit->regPool->numFPTemps; i++) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800620 dvmCompilerClobber(cUnit, cUnit->regPool->FPTemps[i].reg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700621 }
622}
623
624/* To be used when explicitly managing register use */
Bill Buzbeec6f10662010-02-09 11:16:15 -0800625extern void dvmCompilerLockAllTemps(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -0700626{
627 int i;
628 for (i=0; i< cUnit->regPool->numCoreTemps; i++) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800629 dvmCompilerLockTemp(cUnit, cUnit->regPool->coreTemps[i].reg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700630 }
631}
632
633// Make sure nothing is live and dirty
634static void flushAllRegsBody(CompilationUnit *cUnit, RegisterInfo *info,
635 int numRegs)
636{
637 int i;
638 for (i=0; i < numRegs; i++) {
639 if (info[i].live && info[i].dirty) {
640 if (info[i].pair) {
641 flushRegWide(cUnit, info[i].reg, info[i].partner);
642 } else {
643 flushReg(cUnit, info[i].reg);
644 }
645 }
646 }
647}
648
Bill Buzbeec6f10662010-02-09 11:16:15 -0800649extern void dvmCompilerFlushAllRegs(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -0700650{
651 flushAllRegsBody(cUnit, cUnit->regPool->coreTemps,
652 cUnit->regPool->numCoreTemps);
653 flushAllRegsBody(cUnit, cUnit->regPool->FPTemps,
654 cUnit->regPool->numFPTemps);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800655 dvmCompilerClobberAllRegs(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700656}
657
658
659//TUNING: rewrite all of this reg stuff. Probably use an attribute table
660static bool regClassMatches(int regClass, int reg)
661{
662 if (regClass == kAnyReg) {
663 return true;
664 } else if (regClass == kCoreReg) {
665 return !FPREG(reg);
666 } else {
667 return FPREG(reg);
668 }
669}
670
Bill Buzbeec6f10662010-02-09 11:16:15 -0800671extern void dvmCompilerMarkLive(CompilationUnit *cUnit, int reg, int sReg)
Bill Buzbee1465db52009-09-23 17:17:35 -0700672{
673 RegisterInfo *info = getRegInfo(cUnit, reg);
674 if ((info->reg == reg) && (info->sReg == sReg) && info->live) {
675 return; /* already live */
676 } else if (sReg != INVALID_SREG) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800677 dvmCompilerClobberSReg(cUnit, sReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700678 info->live = true;
679 } else {
680 /* Can't be live if no associated sReg */
681 info->live = false;
682 }
683 info->sReg = sReg;
684}
685
Bill Buzbeec6f10662010-02-09 11:16:15 -0800686extern void dvmCompilerMarkPair(CompilationUnit *cUnit, int lowReg, int highReg)
Bill Buzbee1465db52009-09-23 17:17:35 -0700687{
688 RegisterInfo *infoLo = getRegInfo(cUnit, lowReg);
689 RegisterInfo *infoHi = getRegInfo(cUnit, highReg);
690 infoLo->pair = infoHi->pair = true;
691 infoLo->partner = highReg;
692 infoHi->partner = lowReg;
693}
694
Bill Buzbeec6f10662010-02-09 11:16:15 -0800695extern void dvmCompilerMarkClean(CompilationUnit *cUnit, int reg)
Bill Buzbee1465db52009-09-23 17:17:35 -0700696{
697 RegisterInfo *info = getRegInfo(cUnit, reg);
698 info->dirty = false;
699}
700
Bill Buzbeec6f10662010-02-09 11:16:15 -0800701extern void dvmCompilerMarkDirty(CompilationUnit *cUnit, int reg)
Bill Buzbee1465db52009-09-23 17:17:35 -0700702{
703 RegisterInfo *info = getRegInfo(cUnit, reg);
704 info->dirty = true;
705}
706
Elliott Hughes6a555132010-02-25 15:41:42 -0800707extern void dvmCompilerMarkInUse(CompilationUnit *cUnit, int reg)
Bill Buzbee1465db52009-09-23 17:17:35 -0700708{
Ben Cheng5d90c202009-11-22 23:31:11 -0800709 RegisterInfo *info = getRegInfo(cUnit, reg);
710 info->inUse = true;
Bill Buzbee1465db52009-09-23 17:17:35 -0700711}
712
Andy McFadden953a0ed2010-09-17 15:48:38 -0700713static void copyRegInfo(CompilationUnit *cUnit, int newReg, int oldReg)
Bill Buzbee1465db52009-09-23 17:17:35 -0700714{
715 RegisterInfo *newInfo = getRegInfo(cUnit, newReg);
716 RegisterInfo *oldInfo = getRegInfo(cUnit, oldReg);
717 *newInfo = *oldInfo;
718 newInfo->reg = newReg;
719}
720
721/*
722 * Return an updated location record with current in-register status.
723 * If the value lives in live temps, reflect that fact. No code
724 * is generated. The the live value is part of an older pair,
725 * clobber both low and high.
726 * TUNING: clobbering both is a bit heavy-handed, but the alternative
727 * is a bit complex when dealing with FP regs. Examine code to see
728 * if it's worthwhile trying to be more clever here.
729 */
Bill Buzbeec6f10662010-02-09 11:16:15 -0800730extern RegLocation dvmCompilerUpdateLoc(CompilationUnit *cUnit, RegLocation loc)
Bill Buzbee1465db52009-09-23 17:17:35 -0700731{
732 assert(!loc.wide);
733 if (loc.location == kLocDalvikFrame) {
734 RegisterInfo *infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
735 if (infoLo) {
736 if (infoLo->pair) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800737 dvmCompilerClobber(cUnit, infoLo->reg);
738 dvmCompilerClobber(cUnit, infoLo->partner);
Bill Buzbee1465db52009-09-23 17:17:35 -0700739 } else {
740 loc.lowReg = infoLo->reg;
741 loc.location = kLocPhysReg;
742 }
743 }
744 }
745
746 return loc;
747}
748
749/* see comments for updateLoc */
Bill Buzbeec6f10662010-02-09 11:16:15 -0800750extern RegLocation dvmCompilerUpdateLocWide(CompilationUnit *cUnit,
751 RegLocation loc)
Bill Buzbee1465db52009-09-23 17:17:35 -0700752{
753 assert(loc.wide);
754 if (loc.location == kLocDalvikFrame) {
Bill Buzbee80cef862010-03-25 10:38:34 -0700755 // Are the dalvik regs already live in physical registers?
Bill Buzbee1465db52009-09-23 17:17:35 -0700756 RegisterInfo *infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800757 RegisterInfo *infoHi = allocLive(cUnit,
758 dvmCompilerSRegHi(loc.sRegLow), kAnyReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700759 bool match = true;
760 match = match && (infoLo != NULL);
761 match = match && (infoHi != NULL);
Bill Buzbee80cef862010-03-25 10:38:34 -0700762 // Are they both core or both FP?
Bill Buzbee1465db52009-09-23 17:17:35 -0700763 match = match && (FPREG(infoLo->reg) == FPREG(infoHi->reg));
Bill Buzbee80cef862010-03-25 10:38:34 -0700764 // If a pair of floating point singles, are they properly aligned?
Bill Buzbee1465db52009-09-23 17:17:35 -0700765 if (match && FPREG(infoLo->reg)) {
766 match &= ((infoLo->reg & 0x1) == 0);
767 match &= ((infoHi->reg - infoLo->reg) == 1);
768 }
Bill Buzbee80cef862010-03-25 10:38:34 -0700769 // If previously used as a pair, it is the same pair?
770 if (match && (infoLo->pair || infoHi->pair)) {
771 match = (infoLo->pair == infoHi->pair);
772 match &= ((infoLo->reg == infoHi->partner) &&
773 (infoHi->reg == infoLo->partner));
774 }
Bill Buzbee1465db52009-09-23 17:17:35 -0700775 if (match) {
Bill Buzbee80cef862010-03-25 10:38:34 -0700776 // Can reuse - update the register usage info
Bill Buzbee1465db52009-09-23 17:17:35 -0700777 loc.lowReg = infoLo->reg;
778 loc.highReg = infoHi->reg;
779 loc.location = kLocPhysReg;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800780 dvmCompilerMarkPair(cUnit, loc.lowReg, loc.highReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700781 assert(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
782 return loc;
783 }
Bill Buzbee80cef862010-03-25 10:38:34 -0700784 // Can't easily reuse - clobber any overlaps
Bill Buzbee1465db52009-09-23 17:17:35 -0700785 if (infoLo) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800786 dvmCompilerClobber(cUnit, infoLo->reg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700787 if (infoLo->pair)
Bill Buzbeec6f10662010-02-09 11:16:15 -0800788 dvmCompilerClobber(cUnit, infoLo->partner);
Bill Buzbee1465db52009-09-23 17:17:35 -0700789 }
790 if (infoHi) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800791 dvmCompilerClobber(cUnit, infoHi->reg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700792 if (infoHi->pair)
Bill Buzbeec6f10662010-02-09 11:16:15 -0800793 dvmCompilerClobber(cUnit, infoHi->partner);
Bill Buzbee1465db52009-09-23 17:17:35 -0700794 }
795 }
796
797 return loc;
798}
799
800static RegLocation evalLocWide(CompilationUnit *cUnit, RegLocation loc,
801 int regClass, bool update)
802{
803 assert(loc.wide);
804 int newRegs;
805 int lowReg;
806 int highReg;
807
Bill Buzbeec6f10662010-02-09 11:16:15 -0800808 loc = dvmCompilerUpdateLocWide(cUnit, loc);
Bill Buzbee1465db52009-09-23 17:17:35 -0700809
810 /* If already in registers, we can assume proper form. Right reg class? */
811 if (loc.location == kLocPhysReg) {
812 assert(FPREG(loc.lowReg) == FPREG(loc.highReg));
813 assert(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
814 if (!regClassMatches(regClass, loc.lowReg)) {
815 /* Wrong register class. Reallocate and copy */
Ben Cheng5d90c202009-11-22 23:31:11 -0800816 newRegs = dvmCompilerAllocTypedTempPair(cUnit, loc.fp, regClass);
Bill Buzbee1465db52009-09-23 17:17:35 -0700817 lowReg = newRegs & 0xff;
818 highReg = (newRegs >> 8) & 0xff;
Ben Cheng5d90c202009-11-22 23:31:11 -0800819 dvmCompilerRegCopyWide(cUnit, lowReg, highReg, loc.lowReg,
820 loc.highReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700821 copyRegInfo(cUnit, lowReg, loc.lowReg);
822 copyRegInfo(cUnit, highReg, loc.highReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800823 dvmCompilerClobber(cUnit, loc.lowReg);
824 dvmCompilerClobber(cUnit, loc.highReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700825 loc.lowReg = lowReg;
826 loc.highReg = highReg;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800827 dvmCompilerMarkPair(cUnit, loc.lowReg, loc.highReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700828 assert(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
829 }
830 return loc;
831 }
832
833 assert((loc.location != kLocRetval) || (loc.sRegLow == INVALID_SREG));
Ben Cheng5d90c202009-11-22 23:31:11 -0800834 assert((loc.location != kLocRetval) ||
Bill Buzbeec6f10662010-02-09 11:16:15 -0800835 (dvmCompilerSRegHi(loc.sRegLow) == INVALID_SREG));
Bill Buzbee1465db52009-09-23 17:17:35 -0700836
Ben Cheng5d90c202009-11-22 23:31:11 -0800837 newRegs = dvmCompilerAllocTypedTempPair(cUnit, loc.fp, regClass);
Bill Buzbee1465db52009-09-23 17:17:35 -0700838 loc.lowReg = newRegs & 0xff;
839 loc.highReg = (newRegs >> 8) & 0xff;
840
Bill Buzbeec6f10662010-02-09 11:16:15 -0800841 dvmCompilerMarkPair(cUnit, loc.lowReg, loc.highReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700842 if (update) {
843 loc.location = kLocPhysReg;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800844 dvmCompilerMarkLive(cUnit, loc.lowReg, loc.sRegLow);
845 dvmCompilerMarkLive(cUnit, loc.highReg, dvmCompilerSRegHi(loc.sRegLow));
Bill Buzbee1465db52009-09-23 17:17:35 -0700846 }
847 assert(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
848 return loc;
849}
850
Bill Buzbeec6f10662010-02-09 11:16:15 -0800851extern RegLocation dvmCompilerEvalLoc(CompilationUnit *cUnit, RegLocation loc,
852 int regClass, bool update)
Bill Buzbee1465db52009-09-23 17:17:35 -0700853{
Bill Buzbee1465db52009-09-23 17:17:35 -0700854 int newReg;
855 if (loc.wide)
856 return evalLocWide(cUnit, loc, regClass, update);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800857 loc = dvmCompilerUpdateLoc(cUnit, loc);
Bill Buzbee1465db52009-09-23 17:17:35 -0700858
859 if (loc.location == kLocPhysReg) {
860 if (!regClassMatches(regClass, loc.lowReg)) {
861 /* Wrong register class. Realloc, copy and transfer ownership */
Ben Cheng5d90c202009-11-22 23:31:11 -0800862 newReg = dvmCompilerAllocTypedTemp(cUnit, loc.fp, regClass);
863 dvmCompilerRegCopy(cUnit, newReg, loc.lowReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700864 copyRegInfo(cUnit, newReg, loc.lowReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800865 dvmCompilerClobber(cUnit, loc.lowReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700866 loc.lowReg = newReg;
867 }
868 return loc;
869 }
870
871 assert((loc.location != kLocRetval) || (loc.sRegLow == INVALID_SREG));
872
Ben Cheng5d90c202009-11-22 23:31:11 -0800873 newReg = dvmCompilerAllocTypedTemp(cUnit, loc.fp, regClass);
Bill Buzbee1465db52009-09-23 17:17:35 -0700874 loc.lowReg = newReg;
875
876 if (update) {
877 loc.location = kLocPhysReg;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800878 dvmCompilerMarkLive(cUnit, loc.lowReg, loc.sRegLow);
Bill Buzbee1465db52009-09-23 17:17:35 -0700879 }
880 return loc;
881}
882
Bill Buzbee1465db52009-09-23 17:17:35 -0700883static inline int getDestSSAName(MIR *mir, int num)
884{
885 assert(mir->ssaRep->numDefs > num);
886 return mir->ssaRep->defs[num];
887}
888
889// Get the LocRecord associated with an SSA name use.
Bill Buzbeec6f10662010-02-09 11:16:15 -0800890extern RegLocation dvmCompilerGetSrc(CompilationUnit *cUnit, MIR *mir, int num)
Bill Buzbee1465db52009-09-23 17:17:35 -0700891{
Bill Buzbeec6f10662010-02-09 11:16:15 -0800892 RegLocation loc = cUnit->regLocation[
893 SREG(cUnit, dvmCompilerSSASrc(mir, num))];
894 loc.fp = cUnit->regLocation[dvmCompilerSSASrc(mir, num)].fp;
Bill Buzbee1465db52009-09-23 17:17:35 -0700895 loc.wide = false;
896 return loc;
897}
898
899// Get the LocRecord associated with an SSA name def.
Bill Buzbeec6f10662010-02-09 11:16:15 -0800900extern RegLocation dvmCompilerGetDest(CompilationUnit *cUnit, MIR *mir,
901 int num)
Bill Buzbee1465db52009-09-23 17:17:35 -0700902{
903 RegLocation loc = cUnit->regLocation[SREG(cUnit, getDestSSAName(mir, num))];
904 loc.fp = cUnit->regLocation[getDestSSAName(mir, num)].fp;
905 loc.wide = false;
906 return loc;
907}
908
909static RegLocation getLocWide(CompilationUnit *cUnit, MIR *mir,
Bill Buzbeec6f10662010-02-09 11:16:15 -0800910 int low, int high, bool isSrc)
Bill Buzbee1465db52009-09-23 17:17:35 -0700911{
912 RegLocation lowLoc;
913 RegLocation highLoc;
914 /* Copy loc record for low word and patch in data from high word */
915 if (isSrc) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800916 lowLoc = dvmCompilerGetSrc(cUnit, mir, low);
917 highLoc = dvmCompilerGetSrc(cUnit, mir, high);
Bill Buzbee1465db52009-09-23 17:17:35 -0700918 } else {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800919 lowLoc = dvmCompilerGetDest(cUnit, mir, low);
920 highLoc = dvmCompilerGetDest(cUnit, mir, high);
Bill Buzbee1465db52009-09-23 17:17:35 -0700921 }
922 /* Avoid this case by either promoting both or neither. */
923 assert(lowLoc.location == highLoc.location);
924 if (lowLoc.location == kLocPhysReg) {
925 /* This case shouldn't happen if we've named correctly */
926 assert(lowLoc.fp == highLoc.fp);
927 }
928 lowLoc.wide = true;
929 lowLoc.highReg = highLoc.lowReg;
930 return lowLoc;
931}
Ben Cheng5d90c202009-11-22 23:31:11 -0800932
Bill Buzbeec6f10662010-02-09 11:16:15 -0800933extern RegLocation dvmCompilerGetDestWide(CompilationUnit *cUnit, MIR *mir,
934 int low, int high)
Bill Buzbee1465db52009-09-23 17:17:35 -0700935{
936 return getLocWide(cUnit, mir, low, high, false);
937}
938
Bill Buzbeec6f10662010-02-09 11:16:15 -0800939extern RegLocation dvmCompilerGetSrcWide(CompilationUnit *cUnit, MIR *mir,
Bill Buzbee1465db52009-09-23 17:17:35 -0700940 int low, int high)
941{
942 return getLocWide(cUnit, mir, low, high, true);
943}
944
Bill Buzbeec6f10662010-02-09 11:16:15 -0800945extern RegLocation dvmCompilerGetReturnWide(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -0700946{
947 RegLocation res = LOC_C_RETURN_WIDE;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800948 dvmCompilerClobber(cUnit, r0);
949 dvmCompilerClobber(cUnit, r1);
Elliott Hughes6a555132010-02-25 15:41:42 -0800950 dvmCompilerMarkInUse(cUnit, r0);
951 dvmCompilerMarkInUse(cUnit, r1);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800952 dvmCompilerMarkPair(cUnit, res.lowReg, res.highReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700953 return res;
954}
955
Bill Buzbeec6f10662010-02-09 11:16:15 -0800956extern RegLocation dvmCompilerGetReturnWideAlt(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -0700957{
958 RegLocation res = LOC_C_RETURN_WIDE;
959 res.lowReg = r2;
960 res.highReg = r3;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800961 dvmCompilerClobber(cUnit, r2);
962 dvmCompilerClobber(cUnit, r3);
Elliott Hughes6a555132010-02-25 15:41:42 -0800963 dvmCompilerMarkInUse(cUnit, r2);
964 dvmCompilerMarkInUse(cUnit, r3);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800965 dvmCompilerMarkPair(cUnit, res.lowReg, res.highReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700966 return res;
967}
968
Bill Buzbeec6f10662010-02-09 11:16:15 -0800969extern RegLocation dvmCompilerGetReturn(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -0700970{
971 RegLocation res = LOC_C_RETURN;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800972 dvmCompilerClobber(cUnit, r0);
Elliott Hughes6a555132010-02-25 15:41:42 -0800973 dvmCompilerMarkInUse(cUnit, r0);
Bill Buzbee1465db52009-09-23 17:17:35 -0700974 return res;
975}
976
Bill Buzbeec6f10662010-02-09 11:16:15 -0800977extern RegLocation dvmCompilerGetReturnAlt(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -0700978{
979 RegLocation res = LOC_C_RETURN;
980 res.lowReg = r1;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800981 dvmCompilerClobber(cUnit, r1);
Elliott Hughes6a555132010-02-25 15:41:42 -0800982 dvmCompilerMarkInUse(cUnit, r1);
Bill Buzbee1465db52009-09-23 17:17:35 -0700983 return res;
984}
985
986/* Kill the corresponding bit in the null-checked register list */
Bill Buzbeec6f10662010-02-09 11:16:15 -0800987extern void dvmCompilerKillNullCheckedLoc(CompilationUnit *cUnit,
988 RegLocation loc)
Bill Buzbee1465db52009-09-23 17:17:35 -0700989{
990 if (loc.location != kLocRetval) {
991 assert(loc.sRegLow != INVALID_SREG);
992 dvmClearBit(cUnit->regPool->nullCheckedRegs, loc.sRegLow);
993 if (loc.wide) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800994 assert(dvmCompilerSRegHi(loc.sRegLow) != INVALID_SREG);
995 dvmClearBit(cUnit->regPool->nullCheckedRegs,
996 dvmCompilerSRegHi(loc.sRegLow));
Bill Buzbee1465db52009-09-23 17:17:35 -0700997 }
998 }
999}
Ben Cheng5d90c202009-11-22 23:31:11 -08001000
1001extern void dvmCompilerFlushRegWideForV5TEVFP(CompilationUnit *cUnit,
1002 int reg1, int reg2)
1003{
1004 flushRegWide(cUnit, reg1, reg2);
1005}
1006
1007extern void dvmCompilerFlushRegForV5TEVFP(CompilationUnit *cUnit, int reg)
1008{
1009 flushReg(cUnit, reg);
1010}