blob: 3fe3b3ad5f4fc1ad31de4993fbd7c58f07c59c7b [file] [log] [blame]
buzbee67bf8852011-08-17 17:51:35 -07001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/*
18 * This file contains register alloction support and is intended to be
19 * included by:
20 *
21 * Codegen-$(TARGET_ARCH_VARIANT).c
22 *
23 */
24
25#include "../CompilerUtility.h"
26#include "../CompilerIR.h"
27#include "../Dataflow.h"
28#include "Ralloc.h"
29
30#define SREG(c, s) ((c)->regLocation[(s)].sRegLow)
31/*
32 * Get the "real" sreg number associated with an sReg slot. In general,
33 * sReg values passed through codegen are the SSA names created by
34 * dataflow analysis and refer to slot numbers in the cUnit->regLocation
35 * array. However, renaming is accomplished by simply replacing RegLocation
36 * entries in the cUnit->reglocation[] array. Therefore, when location
37 * records for operands are first created, we need to ask the locRecord
38 * identified by the dataflow pass what it's new name is.
39 */
40
41/*
42 * Free all allocated temps in the temp pools. Note that this does
43 * not affect the "liveness" of a temp register, which will stay
44 * live until it is either explicitly killed or reallocated.
45 */
46extern void oatResetRegPool(CompilationUnit* cUnit)
47{
48 int i;
49 for (i=0; i < cUnit->regPool->numCoreRegs; i++) {
50 if (cUnit->regPool->coreRegs[i].isTemp)
51 cUnit->regPool->coreRegs[i].inUse = false;
52 }
53 for (i=0; i < cUnit->regPool->numFPRegs; i++) {
54 if (cUnit->regPool->FPRegs[i].isTemp)
55 cUnit->regPool->FPRegs[i].inUse = false;
56 }
57}
58
59 /* Set up temp & preserved register pools specialized by target */
60extern void oatInitPool(RegisterInfo* regs, int* regNums, int num)
61{
62 int i;
63 for (i=0; i < num; i++) {
64 regs[i].reg = regNums[i];
65 regs[i].inUse = false;
66 regs[i].isTemp = false;
67 regs[i].pair = false;
68 regs[i].live = false;
69 regs[i].dirty = false;
70 regs[i].sReg = INVALID_SREG;
71 }
72}
73
buzbeeed3e9302011-09-23 17:34:19 -070074STATIC void dumpRegPool(RegisterInfo* p, int numRegs)
buzbee67bf8852011-08-17 17:51:35 -070075{
76 int i;
77 LOG(INFO) << "================================================";
78 for (i=0; i < numRegs; i++ ){
79 char buf[100];
80 snprintf(buf, 100,
81 "R[%d]: T:%d, U:%d, P:%d, p:%d, LV:%d, D:%d, SR:%d, ST:%x, EN:%x",
82 p[i].reg, p[i].isTemp, p[i].inUse, p[i].pair, p[i].partner,
83 p[i].live, p[i].dirty, p[i].sReg,(int)p[i].defStart,
84 (int)p[i].defEnd);
85 LOG(INFO) << buf;
86 }
87 LOG(INFO) << "================================================";
88}
89
buzbee6181f792011-09-29 11:14:04 -070090void oatDumpCoreRegPool(CompilationUnit* cUnit)
91{
92 dumpRegPool(cUnit->regPool->coreRegs, cUnit->regPool->numCoreRegs);
93}
94
95void oatDumpFpRegPool(CompilationUnit* cUnit)
96{
97 dumpRegPool(cUnit->regPool->FPRegs, cUnit->regPool->numFPRegs);
98}
99
buzbee67bf8852011-08-17 17:51:35 -0700100void oatFlushRegWide(CompilationUnit* cUnit, int reg1, int reg2)
101{
buzbee68253262011-10-07 14:02:25 -0700102 RegisterInfo* info1 = oatGetRegInfo(cUnit, reg1);
103 RegisterInfo* info2 = oatGetRegInfo(cUnit, reg2);
buzbeeed3e9302011-09-23 17:34:19 -0700104 DCHECK(info1 && info2 && info1->pair && info2->pair &&
buzbee67bf8852011-08-17 17:51:35 -0700105 (info1->partner == info2->reg) &&
106 (info2->partner == info1->reg));
107 if ((info1->live && info1->dirty) || (info2->live && info2->dirty)) {
108 if (!(info1->isTemp && info2->isTemp)) {
109 /* Should not happen. If it does, there's a problem in evalLoc */
110 LOG(FATAL) << "Long half-temp, half-promoted";
111 }
112
113 info1->dirty = false;
114 info2->dirty = false;
115 if (oatS2VReg(cUnit, info2->sReg) <
116 oatS2VReg(cUnit, info1->sReg))
117 info1 = info2;
118 int vReg = oatS2VReg(cUnit, info1->sReg);
119 oatFlushRegWideImpl(cUnit, rSP,
120 oatVRegOffset(cUnit, vReg),
121 info1->reg, info1->partner);
122 }
123}
124
125void oatFlushReg(CompilationUnit* cUnit, int reg)
126{
buzbee68253262011-10-07 14:02:25 -0700127 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
buzbee67bf8852011-08-17 17:51:35 -0700128 if (info->live && info->dirty) {
129 info->dirty = false;
130 int vReg = oatS2VReg(cUnit, info->sReg);
131 oatFlushRegImpl(cUnit, rSP,
132 oatVRegOffset(cUnit, vReg),
133 reg, kWord);
134 }
135}
136
buzbee67bf8852011-08-17 17:51:35 -0700137/* Mark a temp register as dead. Does not affect allocation state. */
138void oatClobber(CompilationUnit* cUnit, int reg)
139{
buzbee68253262011-10-07 14:02:25 -0700140 RegisterInfo* p = oatGetRegInfo(cUnit, reg);
141 if (p->isTemp) {
142 DCHECK(!(p->live && p->dirty)) << "Live & dirty temp in clobber";
143 p->live = false;
144 p->sReg = INVALID_SREG;
145 p->defStart = NULL;
146 p->defEnd = NULL;
147 if (p->pair) {
148 p->pair = false;
149 oatClobber(cUnit, p->partner);
150 }
buzbee67bf8852011-08-17 17:51:35 -0700151 }
152}
153
buzbeeed3e9302011-09-23 17:34:19 -0700154STATIC void clobberSRegBody(RegisterInfo* p, int numRegs, int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700155{
156 int i;
157 for (i=0; i< numRegs; i++) {
158 if (p[i].sReg == sReg) {
159 if (p[i].isTemp) {
160 p[i].live = false;
161 }
162 p[i].defStart = NULL;
163 p[i].defEnd = NULL;
164 }
165 }
166}
167
168/* Clobber any temp associated with an sReg. Could be in either class */
169extern void oatClobberSReg(CompilationUnit* cUnit, int sReg)
170{
171 clobberSRegBody(cUnit->regPool->coreRegs, cUnit->regPool->numCoreRegs,
172 sReg);
173 clobberSRegBody(cUnit->regPool->FPRegs, cUnit->regPool->numFPRegs,
174 sReg);
175}
176
177/* Reserve a callee-save register. Return -1 if none available */
178extern int oatAllocPreservedCoreReg(CompilationUnit* cUnit, int sReg)
179{
180 int res = -1;
181 RegisterInfo* coreRegs = cUnit->regPool->coreRegs;
182 for (int i = 0; i < cUnit->regPool->numCoreRegs; i++) {
183 if (!coreRegs[i].isTemp && !coreRegs[i].inUse) {
184 res = coreRegs[i].reg;
185 coreRegs[i].inUse = true;
186 cUnit->coreSpillMask |= (1 << res);
buzbeec41e5b52011-09-23 12:46:19 -0700187 cUnit->coreVmapTable.push_back(sReg);
buzbeebbaf8942011-10-02 13:08:29 -0700188 cUnit->numCoreSpills++;
buzbee67bc2362011-10-11 18:08:40 -0700189 // Should be promoting based on initial sReg set
190 DCHECK_EQ(sReg, oatS2VReg(cUnit, sReg));
191 cUnit->promotionMap[sReg].coreLocation = kLocPhysReg;
192 cUnit->promotionMap[sReg].coreReg = res;
buzbee67bf8852011-08-17 17:51:35 -0700193 break;
194 }
195 }
196 return res;
197}
198
199/*
buzbeebbaf8942011-10-02 13:08:29 -0700200 * Mark a callee-save fp register as promoted. Note that
201 * vpush/vpop uses contiguous register lists so we must
202 * include any holes in the mask. Associate holes with
buzbee3ddc0d12011-10-05 10:36:21 -0700203 * Dalvik register INVALID_VREG (0xFFFFU).
buzbeebbaf8942011-10-02 13:08:29 -0700204 */
205STATIC void markPreservedSingle(CompilationUnit* cUnit, int sReg, int reg)
206{
207 DCHECK_GE(reg, FP_REG_MASK + FP_CALLEE_SAVE_BASE);
208 reg = (reg & FP_REG_MASK) - FP_CALLEE_SAVE_BASE;
209 // Ensure fpVmapTable is large enough
210 int tableSize = cUnit->fpVmapTable.size();
211 for (int i = tableSize; i < (reg + 1); i++) {
buzbee3ddc0d12011-10-05 10:36:21 -0700212 cUnit->fpVmapTable.push_back(INVALID_VREG);
buzbeebbaf8942011-10-02 13:08:29 -0700213 }
214 // Add the current mapping
215 cUnit->fpVmapTable[reg] = sReg;
216 // Size of fpVmapTable is high-water mark, use to set mask
217 cUnit->numFPSpills = cUnit->fpVmapTable.size();
218 cUnit->fpSpillMask = ((1 << cUnit->numFPSpills) - 1) << FP_CALLEE_SAVE_BASE;
219}
220
221/*
buzbee67bf8852011-08-17 17:51:35 -0700222 * Reserve a callee-save fp single register. Try to fullfill request for
223 * even/odd allocation, but go ahead and allocate anything if not
224 * available. If nothing's available, return -1.
225 */
buzbeeed3e9302011-09-23 17:34:19 -0700226STATIC int allocPreservedSingle(CompilationUnit* cUnit, int sReg, bool even)
buzbee67bf8852011-08-17 17:51:35 -0700227{
228 int res = -1;
229 RegisterInfo* FPRegs = cUnit->regPool->FPRegs;
230 for (int i = 0; i < cUnit->regPool->numFPRegs; i++) {
231 if (!FPRegs[i].isTemp && !FPRegs[i].inUse &&
232 ((FPRegs[i].reg & 0x1) == 0) == even) {
233 res = FPRegs[i].reg;
234 FPRegs[i].inUse = true;
buzbee67bc2362011-10-11 18:08:40 -0700235 // Should be promoting based on initial sReg set
236 DCHECK_EQ(sReg, oatS2VReg(cUnit, sReg));
buzbeebbaf8942011-10-02 13:08:29 -0700237 markPreservedSingle(cUnit, sReg, res);
buzbee67bc2362011-10-11 18:08:40 -0700238 cUnit->promotionMap[sReg].fpLocation = kLocPhysReg;
239 cUnit->promotionMap[sReg].fpReg = res;
buzbee67bf8852011-08-17 17:51:35 -0700240 break;
241 }
242 }
243 return res;
244}
245
246/*
247 * Somewhat messy code here. We want to allocate a pair of contiguous
248 * physical single-precision floating point registers starting with
249 * an even numbered reg. It is possible that the paired sReg (sReg+1)
250 * has already been allocated - try to fit if possible. Fail to
251 * allocate if we can't meet the requirements for the pair of
252 * sReg<=sX[even] & (sReg+1)<= sX+1.
253 */
buzbeeed3e9302011-09-23 17:34:19 -0700254STATIC int allocPreservedDouble(CompilationUnit* cUnit, int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700255{
256 int res = -1; // Assume failure
buzbee67bc2362011-10-11 18:08:40 -0700257 // Should be promoting based on initial sReg set
258 DCHECK_EQ(sReg, oatS2VReg(cUnit, sReg));
259 if (cUnit->promotionMap[sReg+1].fpLocation == kLocPhysReg) {
buzbee67bf8852011-08-17 17:51:35 -0700260 // Upper reg is already allocated. Can we fit?
buzbee67bc2362011-10-11 18:08:40 -0700261 int highReg = cUnit->promotionMap[sReg+1].fpReg;
buzbee67bf8852011-08-17 17:51:35 -0700262 if ((highReg & 1) == 0) {
263 // High reg is even - fail.
264 return res;
265 }
266 // Is the low reg of the pair free?
buzbee68253262011-10-07 14:02:25 -0700267 RegisterInfo* p = oatGetRegInfo(cUnit, highReg-1);
buzbee67bf8852011-08-17 17:51:35 -0700268 if (p->inUse || p->isTemp) {
269 // Already allocated or not preserved - fail.
270 return res;
271 }
272 // OK - good to go.
273 res = p->reg;
274 p->inUse = true;
buzbeeed3e9302011-09-23 17:34:19 -0700275 DCHECK_EQ((res & 1), 0);
buzbeebbaf8942011-10-02 13:08:29 -0700276 markPreservedSingle(cUnit, sReg, res);
buzbee67bf8852011-08-17 17:51:35 -0700277 } else {
278 RegisterInfo* FPRegs = cUnit->regPool->FPRegs;
279 for (int i = 0; i < cUnit->regPool->numFPRegs; i++) {
280 if (!FPRegs[i].isTemp && !FPRegs[i].inUse &&
281 ((FPRegs[i].reg & 0x1) == 0x0) &&
282 !FPRegs[i+1].isTemp && !FPRegs[i+1].inUse &&
283 ((FPRegs[i+1].reg & 0x1) == 0x1) &&
284 (FPRegs[i].reg + 1) == FPRegs[i+1].reg) {
285 res = FPRegs[i].reg;
286 FPRegs[i].inUse = true;
buzbeebbaf8942011-10-02 13:08:29 -0700287 markPreservedSingle(cUnit, sReg, res);
buzbee67bf8852011-08-17 17:51:35 -0700288 FPRegs[i+1].inUse = true;
buzbeebbaf8942011-10-02 13:08:29 -0700289 DCHECK_EQ(res + 1, FPRegs[i+1].reg);
290 markPreservedSingle(cUnit, sReg+1, res+1);
buzbee67bf8852011-08-17 17:51:35 -0700291 break;
292 }
293 }
294 }
295 if (res != -1) {
buzbee67bc2362011-10-11 18:08:40 -0700296 cUnit->promotionMap[sReg].fpLocation = kLocPhysReg;
297 cUnit->promotionMap[sReg].fpReg = res;
298 cUnit->promotionMap[sReg+1].fpLocation = kLocPhysReg;
299 cUnit->promotionMap[sReg+1].fpReg = res + 1;
buzbee67bf8852011-08-17 17:51:35 -0700300 }
301 return res;
302}
303
304
305/*
306 * Reserve a callee-save fp register. If this register can be used
307 * as the first of a double, attempt to allocate an even pair of fp
308 * single regs (but if can't still attempt to allocate a single, preferring
309 * first to allocate an odd register.
310 */
311extern int oatAllocPreservedFPReg(CompilationUnit* cUnit, int sReg,
312 bool doubleStart)
313{
314 int res = -1;
315 if (doubleStart) {
316 res = allocPreservedDouble(cUnit, sReg);
buzbee67bf8852011-08-17 17:51:35 -0700317 }
318 if (res == -1) {
319 res = allocPreservedSingle(cUnit, sReg, false /* try odd # */);
320 }
321 if (res == -1)
322 res = allocPreservedSingle(cUnit, sReg, true /* try even # */);
323 return res;
324}
325
buzbeeed3e9302011-09-23 17:34:19 -0700326STATIC int allocTempBody(CompilationUnit* cUnit, RegisterInfo* p, int numRegs,
buzbee67bf8852011-08-17 17:51:35 -0700327 int* nextTemp, bool required)
328{
329 int i;
330 int next = *nextTemp;
331 for (i=0; i< numRegs; i++) {
332 if (next >= numRegs)
333 next = 0;
334 if (p[next].isTemp && !p[next].inUse && !p[next].live) {
335 oatClobber(cUnit, p[next].reg);
336 p[next].inUse = true;
337 p[next].pair = false;
338 *nextTemp = next + 1;
339 return p[next].reg;
340 }
341 next++;
342 }
343 next = *nextTemp;
344 for (i=0; i< numRegs; i++) {
345 if (next >= numRegs)
346 next = 0;
347 if (p[next].isTemp && !p[next].inUse) {
348 oatClobber(cUnit, p[next].reg);
349 p[next].inUse = true;
350 p[next].pair = false;
351 *nextTemp = next + 1;
352 return p[next].reg;
353 }
354 next++;
355 }
356 if (required) {
buzbee6181f792011-09-29 11:14:04 -0700357 oatCodegenDump(cUnit);
buzbee67bf8852011-08-17 17:51:35 -0700358 dumpRegPool(cUnit->regPool->coreRegs,
359 cUnit->regPool->numCoreRegs);
360 LOG(FATAL) << "No free temp registers";
361 }
362 return -1; // No register available
363}
364
365//REDO: too many assumptions.
366extern int oatAllocTempDouble(CompilationUnit* cUnit)
367{
368 RegisterInfo* p = cUnit->regPool->FPRegs;
369 int numRegs = cUnit->regPool->numFPRegs;
buzbeea50638b2011-11-02 15:15:06 -0700370 /* Start looking at an even reg */
371 int next = cUnit->regPool->nextFPReg & ~0x1;
buzbee67bf8852011-08-17 17:51:35 -0700372
buzbeea50638b2011-11-02 15:15:06 -0700373 // First try to avoid allocating live registers
374 for (int i=0; i < numRegs; i+=2) {
buzbee67bf8852011-08-17 17:51:35 -0700375 if (next >= numRegs)
376 next = 0;
377 if ((p[next].isTemp && !p[next].inUse && !p[next].live) &&
378 (p[next+1].isTemp && !p[next+1].inUse && !p[next+1].live)) {
379 oatClobber(cUnit, p[next].reg);
380 oatClobber(cUnit, p[next+1].reg);
381 p[next].inUse = true;
382 p[next+1].inUse = true;
buzbeeed3e9302011-09-23 17:34:19 -0700383 DCHECK_EQ((p[next].reg+1), p[next+1].reg);
384 DCHECK_EQ((p[next].reg & 0x1), 0);
buzbeea50638b2011-11-02 15:15:06 -0700385 cUnit->regPool->nextFPReg = next + 2;
386 if (cUnit->regPool->nextFPReg >= numRegs) {
387 cUnit->regPool->nextFPReg = 0;
388 }
buzbee67bf8852011-08-17 17:51:35 -0700389 return p[next].reg;
390 }
391 next += 2;
392 }
buzbeea50638b2011-11-02 15:15:06 -0700393 next = cUnit->regPool->nextFPReg & ~0x1;
394
395 // No choice - find a pair and kill it.
396 for (int i=0; i < numRegs; i+=2) {
buzbee67bf8852011-08-17 17:51:35 -0700397 if (next >= numRegs)
398 next = 0;
399 if (p[next].isTemp && !p[next].inUse && p[next+1].isTemp &&
400 !p[next+1].inUse) {
401 oatClobber(cUnit, p[next].reg);
402 oatClobber(cUnit, p[next+1].reg);
403 p[next].inUse = true;
404 p[next+1].inUse = true;
buzbeeed3e9302011-09-23 17:34:19 -0700405 DCHECK_EQ((p[next].reg+1), p[next+1].reg);
406 DCHECK_EQ((p[next].reg & 0x1), 0);
buzbeea50638b2011-11-02 15:15:06 -0700407 cUnit->regPool->nextFPReg = next + 2;
408 if (cUnit->regPool->nextFPReg >= numRegs) {
409 cUnit->regPool->nextFPReg = 0;
410 }
buzbee67bf8852011-08-17 17:51:35 -0700411 return p[next].reg;
412 }
413 next += 2;
414 }
buzbee6181f792011-09-29 11:14:04 -0700415 LOG(FATAL) << "No free temp registers (pair)";
buzbee67bf8852011-08-17 17:51:35 -0700416 return -1;
417}
418
419/* Return a temp if one is available, -1 otherwise */
420extern int oatAllocFreeTemp(CompilationUnit* cUnit)
421{
422 return allocTempBody(cUnit, cUnit->regPool->coreRegs,
423 cUnit->regPool->numCoreRegs,
424 &cUnit->regPool->nextCoreReg, true);
425}
426
427extern int oatAllocTemp(CompilationUnit* cUnit)
428{
429 return allocTempBody(cUnit, cUnit->regPool->coreRegs,
430 cUnit->regPool->numCoreRegs,
431 &cUnit->regPool->nextCoreReg, true);
432}
433
434extern int oatAllocTempFloat(CompilationUnit* cUnit)
435{
436 return allocTempBody(cUnit, cUnit->regPool->FPRegs,
437 cUnit->regPool->numFPRegs,
438 &cUnit->regPool->nextFPReg, true);
439}
440
buzbeeed3e9302011-09-23 17:34:19 -0700441STATIC RegisterInfo* allocLiveBody(RegisterInfo* p, int numRegs, int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700442{
443 int i;
444 if (sReg == -1)
445 return NULL;
446 for (i=0; i < numRegs; i++) {
447 if (p[i].live && (p[i].sReg == sReg)) {
448 if (p[i].isTemp)
449 p[i].inUse = true;
450 return &p[i];
451 }
452 }
453 return NULL;
454}
455
buzbeeed3e9302011-09-23 17:34:19 -0700456STATIC RegisterInfo* allocLive(CompilationUnit* cUnit, int sReg,
buzbee67bf8852011-08-17 17:51:35 -0700457 int regClass)
458{
459 RegisterInfo* res = NULL;
460 switch(regClass) {
461 case kAnyReg:
462 res = allocLiveBody(cUnit->regPool->FPRegs,
463 cUnit->regPool->numFPRegs, sReg);
464 if (res)
465 break;
466 /* Intentional fallthrough */
467 case kCoreReg:
468 res = allocLiveBody(cUnit->regPool->coreRegs,
469 cUnit->regPool->numCoreRegs, sReg);
470 break;
471 case kFPReg:
472 res = allocLiveBody(cUnit->regPool->FPRegs,
473 cUnit->regPool->numFPRegs, sReg);
474 break;
475 default:
476 LOG(FATAL) << "Invalid register type";
477 }
478 return res;
479}
480
481extern void oatFreeTemp(CompilationUnit* cUnit, int reg)
482{
483 RegisterInfo* p = cUnit->regPool->coreRegs;
484 int numRegs = cUnit->regPool->numCoreRegs;
485 int i;
486 for (i=0; i< numRegs; i++) {
487 if (p[i].reg == reg) {
488 if (p[i].isTemp) {
489 p[i].inUse = false;
490 }
491 p[i].pair = false;
492 return;
493 }
494 }
495 p = cUnit->regPool->FPRegs;
496 numRegs = cUnit->regPool->numFPRegs;
497 for (i=0; i< numRegs; i++) {
498 if (p[i].reg == reg) {
499 if (p[i].isTemp) {
500 p[i].inUse = false;
501 }
502 p[i].pair = false;
503 return;
504 }
505 }
506 LOG(FATAL) << "Tried to free a non-existant temp: r" << reg;
507}
508
509extern RegisterInfo* oatIsLive(CompilationUnit* cUnit, int reg)
510{
511 RegisterInfo* p = cUnit->regPool->coreRegs;
512 int numRegs = cUnit->regPool->numCoreRegs;
513 int i;
514 for (i=0; i< numRegs; i++) {
515 if (p[i].reg == reg) {
516 return p[i].live ? &p[i] : NULL;
517 }
518 }
519 p = cUnit->regPool->FPRegs;
520 numRegs = cUnit->regPool->numFPRegs;
521 for (i=0; i< numRegs; i++) {
522 if (p[i].reg == reg) {
523 return p[i].live ? &p[i] : NULL;
524 }
525 }
526 return NULL;
527}
528
529extern RegisterInfo* oatIsTemp(CompilationUnit* cUnit, int reg)
530{
buzbee68253262011-10-07 14:02:25 -0700531 RegisterInfo* p = oatGetRegInfo(cUnit, reg);
buzbee67bf8852011-08-17 17:51:35 -0700532 return (p->isTemp) ? p : NULL;
533}
534
buzbeeb29e4d12011-09-26 15:05:48 -0700535extern RegisterInfo* oatIsPromoted(CompilationUnit* cUnit, int reg)
536{
buzbee68253262011-10-07 14:02:25 -0700537 RegisterInfo* p = oatGetRegInfo(cUnit, reg);
buzbeeb29e4d12011-09-26 15:05:48 -0700538 return (p->isTemp) ? NULL : p;
539}
540
buzbee67bf8852011-08-17 17:51:35 -0700541extern bool oatIsDirty(CompilationUnit* cUnit, int reg)
542{
buzbee68253262011-10-07 14:02:25 -0700543 RegisterInfo* p = oatGetRegInfo(cUnit, reg);
buzbee67bf8852011-08-17 17:51:35 -0700544 return p->dirty;
545}
546
547/*
548 * Similar to oatAllocTemp(), but forces the allocation of a specific
549 * register. No check is made to see if the register was previously
550 * allocated. Use with caution.
551 */
552extern void oatLockTemp(CompilationUnit* cUnit, int reg)
553{
554 RegisterInfo* p = cUnit->regPool->coreRegs;
555 int numRegs = cUnit->regPool->numCoreRegs;
556 int i;
557 for (i=0; i< numRegs; i++) {
558 if (p[i].reg == reg) {
buzbeeed3e9302011-09-23 17:34:19 -0700559 DCHECK(p[i].isTemp);
buzbee67bf8852011-08-17 17:51:35 -0700560 p[i].inUse = true;
561 p[i].live = false;
562 return;
563 }
564 }
565 p = cUnit->regPool->FPRegs;
566 numRegs = cUnit->regPool->numFPRegs;
567 for (i=0; i< numRegs; i++) {
568 if (p[i].reg == reg) {
buzbeeed3e9302011-09-23 17:34:19 -0700569 DCHECK(p[i].isTemp);
buzbee67bf8852011-08-17 17:51:35 -0700570 p[i].inUse = true;
571 p[i].live = false;
572 return;
573 }
574 }
575 LOG(FATAL) << "Tried to lock a non-existant temp: r" << reg;
576}
577
578extern void oatResetDef(CompilationUnit* cUnit, int reg)
579{
buzbee68253262011-10-07 14:02:25 -0700580 RegisterInfo* p = oatGetRegInfo(cUnit, reg);
buzbee67bf8852011-08-17 17:51:35 -0700581 p->defStart = NULL;
582 p->defEnd = NULL;
583}
584
buzbeeed3e9302011-09-23 17:34:19 -0700585STATIC void nullifyRange(CompilationUnit* cUnit, LIR *start, LIR *finish,
buzbee67bf8852011-08-17 17:51:35 -0700586 int sReg1, int sReg2)
587{
588 if (start && finish) {
589 LIR *p;
buzbeeed3e9302011-09-23 17:34:19 -0700590 DCHECK_EQ(sReg1, sReg2);
buzbee67bf8852011-08-17 17:51:35 -0700591 for (p = start; ;p = p->next) {
592 ((ArmLIR *)p)->flags.isNop = true;
buzbee6181f792011-09-29 11:14:04 -0700593 ((ArmLIR *)p)->flags.squashed = true;
buzbee67bf8852011-08-17 17:51:35 -0700594 if (p == finish)
595 break;
596 }
597 }
598}
599
600/*
601 * Mark the beginning and end LIR of a def sequence. Note that
602 * on entry start points to the LIR prior to the beginning of the
603 * sequence.
604 */
605extern void oatMarkDef(CompilationUnit* cUnit, RegLocation rl,
606 LIR *start, LIR *finish)
607{
buzbeeed3e9302011-09-23 17:34:19 -0700608 DCHECK(!rl.wide);
609 DCHECK(start && start->next);
610 DCHECK(finish);
buzbee68253262011-10-07 14:02:25 -0700611 RegisterInfo* p = oatGetRegInfo(cUnit, rl.lowReg);
buzbee67bf8852011-08-17 17:51:35 -0700612 p->defStart = start->next;
613 p->defEnd = finish;
614}
615
616/*
617 * Mark the beginning and end LIR of a def sequence. Note that
618 * on entry start points to the LIR prior to the beginning of the
619 * sequence.
620 */
621extern void oatMarkDefWide(CompilationUnit* cUnit, RegLocation rl,
622 LIR *start, LIR *finish)
623{
buzbeeed3e9302011-09-23 17:34:19 -0700624 DCHECK(rl.wide);
625 DCHECK(start && start->next);
626 DCHECK(finish);
buzbee68253262011-10-07 14:02:25 -0700627 RegisterInfo* p = oatGetRegInfo(cUnit, rl.lowReg);
buzbee67bf8852011-08-17 17:51:35 -0700628 oatResetDef(cUnit, rl.highReg); // Only track low of pair
629 p->defStart = start->next;
630 p->defEnd = finish;
631}
632
633extern RegLocation oatWideToNarrow(CompilationUnit* cUnit,
634 RegLocation rl)
635{
buzbeeed3e9302011-09-23 17:34:19 -0700636 DCHECK(rl.wide);
buzbee67bf8852011-08-17 17:51:35 -0700637 if (rl.location == kLocPhysReg) {
buzbee68253262011-10-07 14:02:25 -0700638 RegisterInfo* infoLo = oatGetRegInfo(cUnit, rl.lowReg);
639 RegisterInfo* infoHi = oatGetRegInfo(cUnit, rl.highReg);
buzbee0c7f26d2011-09-07 12:28:51 -0700640 if (infoLo->isTemp) {
641 infoLo->pair = false;
642 infoLo->defStart = NULL;
643 infoLo->defEnd = NULL;
buzbee67bf8852011-08-17 17:51:35 -0700644 }
buzbee0c7f26d2011-09-07 12:28:51 -0700645 if (infoHi->isTemp) {
646 infoHi->pair = false;
647 infoHi->defStart = NULL;
648 infoHi->defEnd = NULL;
buzbee67bf8852011-08-17 17:51:35 -0700649 }
buzbee67bf8852011-08-17 17:51:35 -0700650 }
651 rl.wide = false;
652 return rl;
653}
654
655extern void oatResetDefLoc(CompilationUnit* cUnit, RegLocation rl)
656{
buzbeeed3e9302011-09-23 17:34:19 -0700657 DCHECK(!rl.wide);
buzbee6181f792011-09-29 11:14:04 -0700658 RegisterInfo* p = oatIsTemp(cUnit, rl.lowReg);
659 if (p && !(cUnit->disableOpt & (1 << kSuppressLoads))) {
buzbeeed3e9302011-09-23 17:34:19 -0700660 DCHECK(!p->pair);
buzbee67bf8852011-08-17 17:51:35 -0700661 nullifyRange(cUnit, p->defStart, p->defEnd,
662 p->sReg, rl.sRegLow);
663 }
664 oatResetDef(cUnit, rl.lowReg);
665}
666
667extern void oatResetDefLocWide(CompilationUnit* cUnit, RegLocation rl)
668{
buzbeeed3e9302011-09-23 17:34:19 -0700669 DCHECK(rl.wide);
buzbee6181f792011-09-29 11:14:04 -0700670 RegisterInfo* pLow = oatIsTemp(cUnit, rl.lowReg);
671 RegisterInfo* pHigh = oatIsTemp(cUnit, rl.highReg);
672 if (pLow && !(cUnit->disableOpt & (1 << kSuppressLoads))) {
673 DCHECK(pLow->pair);
674 nullifyRange(cUnit, pLow->defStart, pLow->defEnd,
675 pLow->sReg, rl.sRegLow);
676 }
677 if (pHigh && !(cUnit->disableOpt & (1 << kSuppressLoads))) {
678 DCHECK(pHigh->pair);
buzbee67bf8852011-08-17 17:51:35 -0700679 }
680 oatResetDef(cUnit, rl.lowReg);
681 oatResetDef(cUnit, rl.highReg);
682}
683
684extern void oatResetDefTracking(CompilationUnit* cUnit)
685{
686 int i;
687 for (i=0; i< cUnit->regPool->numCoreRegs; i++) {
688 oatResetDef(cUnit, cUnit->regPool->coreRegs[i].reg);
689 }
690 for (i=0; i< cUnit->regPool->numFPRegs; i++) {
691 oatResetDef(cUnit, cUnit->regPool->FPRegs[i].reg);
692 }
693}
694
695extern void oatClobberAllRegs(CompilationUnit* cUnit)
696{
697 int i;
698 for (i=0; i< cUnit->regPool->numCoreRegs; i++) {
699 oatClobber(cUnit, cUnit->regPool->coreRegs[i].reg);
700 }
701 for (i=0; i< cUnit->regPool->numFPRegs; i++) {
702 oatClobber(cUnit, cUnit->regPool->FPRegs[i].reg);
703 }
704}
705
706/* To be used when explicitly managing register use */
buzbee2e748f32011-08-29 21:02:19 -0700707extern void oatLockCallTemps(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700708{
buzbee2e748f32011-08-29 21:02:19 -0700709 //TODO: Arm specific - move to target dependent code
710 oatLockTemp(cUnit, r0);
711 oatLockTemp(cUnit, r1);
712 oatLockTemp(cUnit, r2);
713 oatLockTemp(cUnit, r3);
buzbee67bf8852011-08-17 17:51:35 -0700714}
715
buzbee0d966cf2011-09-08 17:34:58 -0700716/* To be used when explicitly managing register use */
717extern void oatFreeCallTemps(CompilationUnit* cUnit)
718{
719 //TODO: Arm specific - move to target dependent code
720 oatFreeTemp(cUnit, r0);
721 oatFreeTemp(cUnit, r1);
722 oatFreeTemp(cUnit, r2);
723 oatFreeTemp(cUnit, r3);
724}
725
buzbee67bf8852011-08-17 17:51:35 -0700726// Make sure nothing is live and dirty
buzbeeed3e9302011-09-23 17:34:19 -0700727STATIC void flushAllRegsBody(CompilationUnit* cUnit, RegisterInfo* info,
buzbee67bf8852011-08-17 17:51:35 -0700728 int numRegs)
729{
730 int i;
731 for (i=0; i < numRegs; i++) {
732 if (info[i].live && info[i].dirty) {
733 if (info[i].pair) {
734 oatFlushRegWide(cUnit, info[i].reg, info[i].partner);
735 } else {
736 oatFlushReg(cUnit, info[i].reg);
737 }
738 }
739 }
740}
741
742extern void oatFlushAllRegs(CompilationUnit* cUnit)
743{
744 flushAllRegsBody(cUnit, cUnit->regPool->coreRegs,
745 cUnit->regPool->numCoreRegs);
746 flushAllRegsBody(cUnit, cUnit->regPool->FPRegs,
747 cUnit->regPool->numFPRegs);
748 oatClobberAllRegs(cUnit);
749}
750
751
752//TUNING: rewrite all of this reg stuff. Probably use an attribute table
buzbeeed3e9302011-09-23 17:34:19 -0700753STATIC bool regClassMatches(int regClass, int reg)
buzbee67bf8852011-08-17 17:51:35 -0700754{
755 if (regClass == kAnyReg) {
756 return true;
757 } else if (regClass == kCoreReg) {
758 return !FPREG(reg);
759 } else {
760 return FPREG(reg);
761 }
762}
763
764extern void oatMarkLive(CompilationUnit* cUnit, int reg, int sReg)
765{
buzbee68253262011-10-07 14:02:25 -0700766 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
buzbee67bf8852011-08-17 17:51:35 -0700767 if ((info->reg == reg) && (info->sReg == sReg) && info->live) {
768 return; /* already live */
769 } else if (sReg != INVALID_SREG) {
770 oatClobberSReg(cUnit, sReg);
771 if (info->isTemp) {
772 info->live = true;
773 }
774 } else {
775 /* Can't be live if no associated sReg */
buzbeeed3e9302011-09-23 17:34:19 -0700776 DCHECK(info->isTemp);
buzbee67bf8852011-08-17 17:51:35 -0700777 info->live = false;
778 }
779 info->sReg = sReg;
780}
781
782extern void oatMarkTemp(CompilationUnit* cUnit, int reg)
783{
buzbee68253262011-10-07 14:02:25 -0700784 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
buzbee67bf8852011-08-17 17:51:35 -0700785 info->isTemp = true;
786}
787
buzbee9e0f9b02011-08-24 15:32:46 -0700788extern void oatUnmarkTemp(CompilationUnit* cUnit, int reg)
789{
buzbee68253262011-10-07 14:02:25 -0700790 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
buzbee9e0f9b02011-08-24 15:32:46 -0700791 info->isTemp = false;
792}
793
buzbee67bf8852011-08-17 17:51:35 -0700794extern void oatMarkPair(CompilationUnit* cUnit, int lowReg, int highReg)
795{
buzbee68253262011-10-07 14:02:25 -0700796 RegisterInfo* infoLo = oatGetRegInfo(cUnit, lowReg);
797 RegisterInfo* infoHi = oatGetRegInfo(cUnit, highReg);
buzbee67bf8852011-08-17 17:51:35 -0700798 infoLo->pair = infoHi->pair = true;
799 infoLo->partner = highReg;
800 infoHi->partner = lowReg;
801}
802
803extern void oatMarkClean(CompilationUnit* cUnit, RegLocation loc)
804{
buzbee68253262011-10-07 14:02:25 -0700805 RegisterInfo* info = oatGetRegInfo(cUnit, loc.lowReg);
buzbee67bf8852011-08-17 17:51:35 -0700806 info->dirty = false;
807 if (loc.wide) {
buzbee68253262011-10-07 14:02:25 -0700808 info = oatGetRegInfo(cUnit, loc.highReg);
buzbee67bf8852011-08-17 17:51:35 -0700809 info->dirty = false;
810 }
811}
812
813extern void oatMarkDirty(CompilationUnit* cUnit, RegLocation loc)
814{
815 if (loc.home) {
816 // If already home, can't be dirty
817 return;
818 }
buzbee68253262011-10-07 14:02:25 -0700819 RegisterInfo* info = oatGetRegInfo(cUnit, loc.lowReg);
buzbee67bf8852011-08-17 17:51:35 -0700820 info->dirty = true;
821 if (loc.wide) {
buzbee68253262011-10-07 14:02:25 -0700822 info = oatGetRegInfo(cUnit, loc.highReg);
buzbee67bf8852011-08-17 17:51:35 -0700823 info->dirty = true;
824 }
825}
826
827extern void oatMarkInUse(CompilationUnit* cUnit, int reg)
828{
buzbee68253262011-10-07 14:02:25 -0700829 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
buzbee67bf8852011-08-17 17:51:35 -0700830 info->inUse = true;
831}
832
buzbeeed3e9302011-09-23 17:34:19 -0700833STATIC void copyRegInfo(CompilationUnit* cUnit, int newReg, int oldReg)
buzbee67bf8852011-08-17 17:51:35 -0700834{
buzbee68253262011-10-07 14:02:25 -0700835 RegisterInfo* newInfo = oatGetRegInfo(cUnit, newReg);
836 RegisterInfo* oldInfo = oatGetRegInfo(cUnit, oldReg);
buzbeeec5adf32011-09-11 15:25:43 -0700837 // Target temp status must not change
838 bool isTemp = newInfo->isTemp;
buzbee67bf8852011-08-17 17:51:35 -0700839 *newInfo = *oldInfo;
buzbeeec5adf32011-09-11 15:25:43 -0700840 // Restore target's temp status
841 newInfo->isTemp = isTemp;
buzbee67bf8852011-08-17 17:51:35 -0700842 newInfo->reg = newReg;
843}
844
845/*
846 * Return an updated location record with current in-register status.
847 * If the value lives in live temps, reflect that fact. No code
buzbeeb29e4d12011-09-26 15:05:48 -0700848 * is generated. If the live value is part of an older pair,
buzbee67bf8852011-08-17 17:51:35 -0700849 * clobber both low and high.
850 * TUNING: clobbering both is a bit heavy-handed, but the alternative
851 * is a bit complex when dealing with FP regs. Examine code to see
852 * if it's worthwhile trying to be more clever here.
853 */
854
855extern RegLocation oatUpdateLoc(CompilationUnit* cUnit, RegLocation loc)
856{
buzbeeed3e9302011-09-23 17:34:19 -0700857 DCHECK(!loc.wide);
buzbee6181f792011-09-29 11:14:04 -0700858 DCHECK(oatCheckCorePoolSanity(cUnit));
buzbee67bf8852011-08-17 17:51:35 -0700859 if (loc.location == kLocDalvikFrame) {
860 RegisterInfo* infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
861 if (infoLo) {
862 if (infoLo->pair) {
863 oatClobber(cUnit, infoLo->reg);
864 oatClobber(cUnit, infoLo->partner);
buzbee58f92742011-10-01 11:22:17 -0700865 oatFreeTemp(cUnit, infoLo->reg);
buzbee67bf8852011-08-17 17:51:35 -0700866 } else {
867 loc.lowReg = infoLo->reg;
868 loc.location = kLocPhysReg;
869 }
870 }
871 }
872
873 return loc;
874}
875
buzbee6181f792011-09-29 11:14:04 -0700876bool oatCheckCorePoolSanity(CompilationUnit* cUnit)
877{
878 for (static int i = 0; i < cUnit->regPool->numCoreRegs; i++) {
879 if (cUnit->regPool->coreRegs[i].pair) {
880 static int myReg = cUnit->regPool->coreRegs[i].reg;
881 static int mySreg = cUnit->regPool->coreRegs[i].sReg;
882 static int partnerReg = cUnit->regPool->coreRegs[i].partner;
buzbee68253262011-10-07 14:02:25 -0700883 static RegisterInfo* partner = oatGetRegInfo(cUnit, partnerReg);
buzbee6181f792011-09-29 11:14:04 -0700884 DCHECK(partner != NULL);
885 DCHECK(partner->pair);
886 DCHECK_EQ(myReg, partner->partner);
887 static int partnerSreg = partner->sReg;
888 if (mySreg == INVALID_SREG) {
889 DCHECK_EQ(partnerSreg, INVALID_SREG);
890 } else {
891 int diff = mySreg - partnerSreg;
892 DCHECK((diff == -1) || (diff == 1));
893 }
894 }
895 if (!cUnit->regPool->coreRegs[i].live) {
896 DCHECK(cUnit->regPool->coreRegs[i].defStart == NULL);
897 DCHECK(cUnit->regPool->coreRegs[i].defEnd == NULL);
898 }
899 }
900 return true;
901}
902
buzbee67bf8852011-08-17 17:51:35 -0700903/* see comments for updateLoc */
904extern RegLocation oatUpdateLocWide(CompilationUnit* cUnit,
905 RegLocation loc)
906{
buzbeeed3e9302011-09-23 17:34:19 -0700907 DCHECK(loc.wide);
buzbee6181f792011-09-29 11:14:04 -0700908 DCHECK(oatCheckCorePoolSanity(cUnit));
buzbee67bf8852011-08-17 17:51:35 -0700909 if (loc.location == kLocDalvikFrame) {
910 // Are the dalvik regs already live in physical registers?
911 RegisterInfo* infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
912 RegisterInfo* infoHi = allocLive(cUnit,
913 oatSRegHi(loc.sRegLow), kAnyReg);
914 bool match = true;
915 match = match && (infoLo != NULL);
916 match = match && (infoHi != NULL);
917 // Are they both core or both FP?
918 match = match && (FPREG(infoLo->reg) == FPREG(infoHi->reg));
919 // If a pair of floating point singles, are they properly aligned?
920 if (match && FPREG(infoLo->reg)) {
921 match &= ((infoLo->reg & 0x1) == 0);
922 match &= ((infoHi->reg - infoLo->reg) == 1);
923 }
924 // If previously used as a pair, it is the same pair?
925 if (match && (infoLo->pair || infoHi->pair)) {
926 match = (infoLo->pair == infoHi->pair);
927 match &= ((infoLo->reg == infoHi->partner) &&
928 (infoHi->reg == infoLo->partner));
929 }
930 if (match) {
931 // Can reuse - update the register usage info
932 loc.lowReg = infoLo->reg;
933 loc.highReg = infoHi->reg;
934 loc.location = kLocPhysReg;
935 oatMarkPair(cUnit, loc.lowReg, loc.highReg);
buzbeeed3e9302011-09-23 17:34:19 -0700936 DCHECK(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
buzbee67bf8852011-08-17 17:51:35 -0700937 return loc;
938 }
buzbee58f92742011-10-01 11:22:17 -0700939 // Can't easily reuse - clobber and free any overlaps
buzbee67bf8852011-08-17 17:51:35 -0700940 if (infoLo) {
941 oatClobber(cUnit, infoLo->reg);
buzbee58f92742011-10-01 11:22:17 -0700942 oatFreeTemp(cUnit, infoLo->reg);
buzbee67bf8852011-08-17 17:51:35 -0700943 if (infoLo->pair)
944 oatClobber(cUnit, infoLo->partner);
945 }
946 if (infoHi) {
947 oatClobber(cUnit, infoHi->reg);
buzbee58f92742011-10-01 11:22:17 -0700948 oatFreeTemp(cUnit, infoHi->reg);
buzbee67bf8852011-08-17 17:51:35 -0700949 if (infoHi->pair)
950 oatClobber(cUnit, infoHi->partner);
951 }
952 }
953 return loc;
954}
955
buzbeeed3e9302011-09-23 17:34:19 -0700956
957/* For use in cases we don't know (or care) width */
958extern RegLocation oatUpdateRawLoc(CompilationUnit* cUnit,
959 RegLocation loc)
960{
961 if (loc.wide)
962 return oatUpdateLocWide(cUnit, loc);
963 else
964 return oatUpdateLoc(cUnit, loc);
965}
966
967STATIC RegLocation evalLocWide(CompilationUnit* cUnit, RegLocation loc,
buzbee67bf8852011-08-17 17:51:35 -0700968 int regClass, bool update)
969{
buzbeeed3e9302011-09-23 17:34:19 -0700970 DCHECK(loc.wide);
buzbee67bf8852011-08-17 17:51:35 -0700971 int newRegs;
972 int lowReg;
973 int highReg;
974
975 loc = oatUpdateLocWide(cUnit, loc);
976
977 /* If already in registers, we can assume proper form. Right reg class? */
978 if (loc.location == kLocPhysReg) {
buzbeeed3e9302011-09-23 17:34:19 -0700979 DCHECK_EQ(FPREG(loc.lowReg), FPREG(loc.highReg));
980 DCHECK(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
buzbee67bf8852011-08-17 17:51:35 -0700981 if (!regClassMatches(regClass, loc.lowReg)) {
982 /* Wrong register class. Reallocate and copy */
983 newRegs = oatAllocTypedTempPair(cUnit, loc.fp, regClass);
984 lowReg = newRegs & 0xff;
985 highReg = (newRegs >> 8) & 0xff;
986 oatRegCopyWide(cUnit, lowReg, highReg, loc.lowReg,
987 loc.highReg);
988 copyRegInfo(cUnit, lowReg, loc.lowReg);
989 copyRegInfo(cUnit, highReg, loc.highReg);
990 oatClobber(cUnit, loc.lowReg);
991 oatClobber(cUnit, loc.highReg);
992 loc.lowReg = lowReg;
993 loc.highReg = highReg;
994 oatMarkPair(cUnit, loc.lowReg, loc.highReg);
buzbeeed3e9302011-09-23 17:34:19 -0700995 DCHECK(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
buzbee67bf8852011-08-17 17:51:35 -0700996 }
997 return loc;
998 }
999
buzbeeed3e9302011-09-23 17:34:19 -07001000 DCHECK_NE(loc.sRegLow, INVALID_SREG);
1001 DCHECK_NE(oatSRegHi(loc.sRegLow), INVALID_SREG);
buzbee67bf8852011-08-17 17:51:35 -07001002
1003 newRegs = oatAllocTypedTempPair(cUnit, loc.fp, regClass);
1004 loc.lowReg = newRegs & 0xff;
1005 loc.highReg = (newRegs >> 8) & 0xff;
1006
1007 oatMarkPair(cUnit, loc.lowReg, loc.highReg);
1008 if (update) {
1009 loc.location = kLocPhysReg;
1010 oatMarkLive(cUnit, loc.lowReg, loc.sRegLow);
1011 oatMarkLive(cUnit, loc.highReg, oatSRegHi(loc.sRegLow));
1012 }
buzbeeed3e9302011-09-23 17:34:19 -07001013 DCHECK(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
buzbee67bf8852011-08-17 17:51:35 -07001014 return loc;
1015}
1016
1017extern RegLocation oatEvalLoc(CompilationUnit* cUnit, RegLocation loc,
1018 int regClass, bool update)
1019{
1020 int newReg;
1021
1022 if (loc.wide)
1023 return evalLocWide(cUnit, loc, regClass, update);
1024
1025 loc = oatUpdateLoc(cUnit, loc);
1026
1027 if (loc.location == kLocPhysReg) {
1028 if (!regClassMatches(regClass, loc.lowReg)) {
1029 /* Wrong register class. Realloc, copy and transfer ownership */
1030 newReg = oatAllocTypedTemp(cUnit, loc.fp, regClass);
1031 oatRegCopy(cUnit, newReg, loc.lowReg);
1032 copyRegInfo(cUnit, newReg, loc.lowReg);
1033 oatClobber(cUnit, loc.lowReg);
1034 loc.lowReg = newReg;
1035 }
1036 return loc;
1037 }
1038
buzbeeed3e9302011-09-23 17:34:19 -07001039 DCHECK_NE(loc.sRegLow, INVALID_SREG);
buzbee67bf8852011-08-17 17:51:35 -07001040
1041 newReg = oatAllocTypedTemp(cUnit, loc.fp, regClass);
1042 loc.lowReg = newReg;
1043
1044 if (update) {
1045 loc.location = kLocPhysReg;
1046 oatMarkLive(cUnit, loc.lowReg, loc.sRegLow);
1047 }
1048 return loc;
1049}
1050
1051extern RegLocation oatGetDest(CompilationUnit* cUnit, MIR* mir, int num)
1052{
buzbeee9a72f62011-09-04 17:59:07 -07001053 RegLocation res = cUnit->regLocation[mir->ssaRep->defs[num]];
buzbeeed3e9302011-09-23 17:34:19 -07001054 DCHECK(!res.wide);
buzbeee9a72f62011-09-04 17:59:07 -07001055 return res;
buzbee67bf8852011-08-17 17:51:35 -07001056}
1057extern RegLocation oatGetSrc(CompilationUnit* cUnit, MIR* mir, int num)
1058{
buzbeee9a72f62011-09-04 17:59:07 -07001059 RegLocation res = cUnit->regLocation[mir->ssaRep->uses[num]];
buzbeeed3e9302011-09-23 17:34:19 -07001060 DCHECK(!res.wide);
buzbeee9a72f62011-09-04 17:59:07 -07001061 return res;
1062}
1063extern RegLocation oatGetRawSrc(CompilationUnit* cUnit, MIR* mir, int num)
1064{
1065 RegLocation res = cUnit->regLocation[mir->ssaRep->uses[num]];
1066 return res;
buzbee67bf8852011-08-17 17:51:35 -07001067}
1068extern RegLocation oatGetDestWide(CompilationUnit* cUnit, MIR* mir,
1069 int low, int high)
1070{
buzbeee9a72f62011-09-04 17:59:07 -07001071 RegLocation res = cUnit->regLocation[mir->ssaRep->defs[low]];
buzbeeed3e9302011-09-23 17:34:19 -07001072 DCHECK(res.wide);
buzbeee9a72f62011-09-04 17:59:07 -07001073 return res;
buzbee67bf8852011-08-17 17:51:35 -07001074}
1075
1076extern RegLocation oatGetSrcWide(CompilationUnit* cUnit, MIR* mir,
1077 int low, int high)
1078{
buzbeee9a72f62011-09-04 17:59:07 -07001079 RegLocation res = cUnit->regLocation[mir->ssaRep->uses[low]];
buzbeeed3e9302011-09-23 17:34:19 -07001080 DCHECK(res.wide);
buzbeee9a72f62011-09-04 17:59:07 -07001081 return res;
buzbee67bf8852011-08-17 17:51:35 -07001082}