blob: 2a4fe59864e7e6ad0fd9e7f2e2520b25ae2f6459 [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
Elliott Hughes11d1b0c2012-01-23 16:57:47 -080030namespace art {
31
buzbee67bf8852011-08-17 17:51:35 -070032#define SREG(c, s) ((c)->regLocation[(s)].sRegLow)
33/*
34 * Get the "real" sreg number associated with an sReg slot. In general,
35 * sReg values passed through codegen are the SSA names created by
36 * dataflow analysis and refer to slot numbers in the cUnit->regLocation
37 * array. However, renaming is accomplished by simply replacing RegLocation
38 * entries in the cUnit->reglocation[] array. Therefore, when location
39 * records for operands are first created, we need to ask the locRecord
40 * identified by the dataflow pass what it's new name is.
41 */
42
43/*
44 * Free all allocated temps in the temp pools. Note that this does
45 * not affect the "liveness" of a temp register, which will stay
46 * live until it is either explicitly killed or reallocated.
47 */
48extern void oatResetRegPool(CompilationUnit* cUnit)
49{
50 int i;
51 for (i=0; i < cUnit->regPool->numCoreRegs; i++) {
52 if (cUnit->regPool->coreRegs[i].isTemp)
53 cUnit->regPool->coreRegs[i].inUse = false;
54 }
55 for (i=0; i < cUnit->regPool->numFPRegs; i++) {
56 if (cUnit->regPool->FPRegs[i].isTemp)
57 cUnit->regPool->FPRegs[i].inUse = false;
58 }
59}
60
61 /* Set up temp & preserved register pools specialized by target */
62extern void oatInitPool(RegisterInfo* regs, int* regNums, int num)
63{
64 int i;
65 for (i=0; i < num; i++) {
66 regs[i].reg = regNums[i];
67 regs[i].inUse = false;
68 regs[i].isTemp = false;
69 regs[i].pair = false;
70 regs[i].live = false;
71 regs[i].dirty = false;
72 regs[i].sReg = INVALID_SREG;
73 }
74}
75
buzbeeed3e9302011-09-23 17:34:19 -070076STATIC void dumpRegPool(RegisterInfo* p, int numRegs)
buzbee67bf8852011-08-17 17:51:35 -070077{
78 int i;
79 LOG(INFO) << "================================================";
80 for (i=0; i < numRegs; i++ ){
81 char buf[100];
82 snprintf(buf, 100,
83 "R[%d]: T:%d, U:%d, P:%d, p:%d, LV:%d, D:%d, SR:%d, ST:%x, EN:%x",
84 p[i].reg, p[i].isTemp, p[i].inUse, p[i].pair, p[i].partner,
85 p[i].live, p[i].dirty, p[i].sReg,(int)p[i].defStart,
86 (int)p[i].defEnd);
87 LOG(INFO) << buf;
88 }
89 LOG(INFO) << "================================================";
90}
91
buzbee6181f792011-09-29 11:14:04 -070092void oatDumpCoreRegPool(CompilationUnit* cUnit)
93{
94 dumpRegPool(cUnit->regPool->coreRegs, cUnit->regPool->numCoreRegs);
95}
96
97void oatDumpFpRegPool(CompilationUnit* cUnit)
98{
99 dumpRegPool(cUnit->regPool->FPRegs, cUnit->regPool->numFPRegs);
100}
101
buzbee67bf8852011-08-17 17:51:35 -0700102void oatFlushRegWide(CompilationUnit* cUnit, int reg1, int reg2)
103{
buzbee68253262011-10-07 14:02:25 -0700104 RegisterInfo* info1 = oatGetRegInfo(cUnit, reg1);
105 RegisterInfo* info2 = oatGetRegInfo(cUnit, reg2);
buzbeeed3e9302011-09-23 17:34:19 -0700106 DCHECK(info1 && info2 && info1->pair && info2->pair &&
buzbee67bf8852011-08-17 17:51:35 -0700107 (info1->partner == info2->reg) &&
108 (info2->partner == info1->reg));
109 if ((info1->live && info1->dirty) || (info2->live && info2->dirty)) {
110 if (!(info1->isTemp && info2->isTemp)) {
111 /* Should not happen. If it does, there's a problem in evalLoc */
112 LOG(FATAL) << "Long half-temp, half-promoted";
113 }
114
115 info1->dirty = false;
116 info2->dirty = false;
117 if (oatS2VReg(cUnit, info2->sReg) <
118 oatS2VReg(cUnit, info1->sReg))
119 info1 = info2;
120 int vReg = oatS2VReg(cUnit, info1->sReg);
121 oatFlushRegWideImpl(cUnit, rSP,
122 oatVRegOffset(cUnit, vReg),
123 info1->reg, info1->partner);
124 }
125}
126
127void oatFlushReg(CompilationUnit* cUnit, int reg)
128{
buzbee68253262011-10-07 14:02:25 -0700129 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
buzbee67bf8852011-08-17 17:51:35 -0700130 if (info->live && info->dirty) {
131 info->dirty = false;
132 int vReg = oatS2VReg(cUnit, info->sReg);
133 oatFlushRegImpl(cUnit, rSP,
134 oatVRegOffset(cUnit, vReg),
135 reg, kWord);
136 }
137}
138
buzbee67bf8852011-08-17 17:51:35 -0700139/* Mark a temp register as dead. Does not affect allocation state. */
buzbee5abfa3e2012-01-31 17:01:43 -0800140static inline void clobberBody(CompilationUnit *cUnit, RegisterInfo* p)
buzbee67bf8852011-08-17 17:51:35 -0700141{
buzbee68253262011-10-07 14:02:25 -0700142 if (p->isTemp) {
143 DCHECK(!(p->live && p->dirty)) << "Live & dirty temp in clobber";
144 p->live = false;
145 p->sReg = INVALID_SREG;
146 p->defStart = NULL;
147 p->defEnd = NULL;
148 if (p->pair) {
149 p->pair = false;
150 oatClobber(cUnit, p->partner);
151 }
buzbee67bf8852011-08-17 17:51:35 -0700152 }
153}
154
buzbee5abfa3e2012-01-31 17:01:43 -0800155/* Mark a temp register as dead. Does not affect allocation state. */
156void oatClobber(CompilationUnit* cUnit, int reg)
157{
158 clobberBody(cUnit, oatGetRegInfo(cUnit, reg));
159}
160
buzbeeed3e9302011-09-23 17:34:19 -0700161STATIC void clobberSRegBody(RegisterInfo* p, int numRegs, int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700162{
163 int i;
164 for (i=0; i< numRegs; i++) {
165 if (p[i].sReg == sReg) {
166 if (p[i].isTemp) {
167 p[i].live = false;
168 }
169 p[i].defStart = NULL;
170 p[i].defEnd = NULL;
171 }
172 }
173}
174
175/* Clobber any temp associated with an sReg. Could be in either class */
176extern void oatClobberSReg(CompilationUnit* cUnit, int sReg)
177{
178 clobberSRegBody(cUnit->regPool->coreRegs, cUnit->regPool->numCoreRegs,
179 sReg);
180 clobberSRegBody(cUnit->regPool->FPRegs, cUnit->regPool->numFPRegs,
181 sReg);
182}
183
184/* Reserve a callee-save register. Return -1 if none available */
185extern int oatAllocPreservedCoreReg(CompilationUnit* cUnit, int sReg)
186{
187 int res = -1;
188 RegisterInfo* coreRegs = cUnit->regPool->coreRegs;
189 for (int i = 0; i < cUnit->regPool->numCoreRegs; i++) {
190 if (!coreRegs[i].isTemp && !coreRegs[i].inUse) {
191 res = coreRegs[i].reg;
192 coreRegs[i].inUse = true;
193 cUnit->coreSpillMask |= (1 << res);
buzbeec41e5b52011-09-23 12:46:19 -0700194 cUnit->coreVmapTable.push_back(sReg);
buzbeebbaf8942011-10-02 13:08:29 -0700195 cUnit->numCoreSpills++;
buzbee67bc2362011-10-11 18:08:40 -0700196 // Should be promoting based on initial sReg set
197 DCHECK_EQ(sReg, oatS2VReg(cUnit, sReg));
198 cUnit->promotionMap[sReg].coreLocation = kLocPhysReg;
199 cUnit->promotionMap[sReg].coreReg = res;
buzbee67bf8852011-08-17 17:51:35 -0700200 break;
201 }
202 }
203 return res;
204}
205
206/*
buzbeebbaf8942011-10-02 13:08:29 -0700207 * Mark a callee-save fp register as promoted. Note that
208 * vpush/vpop uses contiguous register lists so we must
209 * include any holes in the mask. Associate holes with
buzbee3ddc0d12011-10-05 10:36:21 -0700210 * Dalvik register INVALID_VREG (0xFFFFU).
buzbeebbaf8942011-10-02 13:08:29 -0700211 */
212STATIC void markPreservedSingle(CompilationUnit* cUnit, int sReg, int reg)
213{
214 DCHECK_GE(reg, FP_REG_MASK + FP_CALLEE_SAVE_BASE);
215 reg = (reg & FP_REG_MASK) - FP_CALLEE_SAVE_BASE;
216 // Ensure fpVmapTable is large enough
217 int tableSize = cUnit->fpVmapTable.size();
218 for (int i = tableSize; i < (reg + 1); i++) {
buzbee3ddc0d12011-10-05 10:36:21 -0700219 cUnit->fpVmapTable.push_back(INVALID_VREG);
buzbeebbaf8942011-10-02 13:08:29 -0700220 }
221 // Add the current mapping
222 cUnit->fpVmapTable[reg] = sReg;
223 // Size of fpVmapTable is high-water mark, use to set mask
224 cUnit->numFPSpills = cUnit->fpVmapTable.size();
225 cUnit->fpSpillMask = ((1 << cUnit->numFPSpills) - 1) << FP_CALLEE_SAVE_BASE;
226}
227
228/*
buzbee67bf8852011-08-17 17:51:35 -0700229 * Reserve a callee-save fp single register. Try to fullfill request for
230 * even/odd allocation, but go ahead and allocate anything if not
231 * available. If nothing's available, return -1.
232 */
buzbeeed3e9302011-09-23 17:34:19 -0700233STATIC int allocPreservedSingle(CompilationUnit* cUnit, int sReg, bool even)
buzbee67bf8852011-08-17 17:51:35 -0700234{
235 int res = -1;
236 RegisterInfo* FPRegs = cUnit->regPool->FPRegs;
237 for (int i = 0; i < cUnit->regPool->numFPRegs; i++) {
238 if (!FPRegs[i].isTemp && !FPRegs[i].inUse &&
239 ((FPRegs[i].reg & 0x1) == 0) == even) {
240 res = FPRegs[i].reg;
241 FPRegs[i].inUse = true;
buzbee67bc2362011-10-11 18:08:40 -0700242 // Should be promoting based on initial sReg set
243 DCHECK_EQ(sReg, oatS2VReg(cUnit, sReg));
buzbeebbaf8942011-10-02 13:08:29 -0700244 markPreservedSingle(cUnit, sReg, res);
buzbee67bc2362011-10-11 18:08:40 -0700245 cUnit->promotionMap[sReg].fpLocation = kLocPhysReg;
246 cUnit->promotionMap[sReg].fpReg = res;
buzbee67bf8852011-08-17 17:51:35 -0700247 break;
248 }
249 }
250 return res;
251}
252
253/*
254 * Somewhat messy code here. We want to allocate a pair of contiguous
255 * physical single-precision floating point registers starting with
256 * an even numbered reg. It is possible that the paired sReg (sReg+1)
257 * has already been allocated - try to fit if possible. Fail to
258 * allocate if we can't meet the requirements for the pair of
259 * sReg<=sX[even] & (sReg+1)<= sX+1.
260 */
buzbeeed3e9302011-09-23 17:34:19 -0700261STATIC int allocPreservedDouble(CompilationUnit* cUnit, int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700262{
263 int res = -1; // Assume failure
buzbee67bc2362011-10-11 18:08:40 -0700264 // Should be promoting based on initial sReg set
265 DCHECK_EQ(sReg, oatS2VReg(cUnit, sReg));
266 if (cUnit->promotionMap[sReg+1].fpLocation == kLocPhysReg) {
buzbee67bf8852011-08-17 17:51:35 -0700267 // Upper reg is already allocated. Can we fit?
buzbee67bc2362011-10-11 18:08:40 -0700268 int highReg = cUnit->promotionMap[sReg+1].fpReg;
buzbee67bf8852011-08-17 17:51:35 -0700269 if ((highReg & 1) == 0) {
270 // High reg is even - fail.
271 return res;
272 }
273 // Is the low reg of the pair free?
buzbee68253262011-10-07 14:02:25 -0700274 RegisterInfo* p = oatGetRegInfo(cUnit, highReg-1);
buzbee67bf8852011-08-17 17:51:35 -0700275 if (p->inUse || p->isTemp) {
276 // Already allocated or not preserved - fail.
277 return res;
278 }
279 // OK - good to go.
280 res = p->reg;
281 p->inUse = true;
buzbeeed3e9302011-09-23 17:34:19 -0700282 DCHECK_EQ((res & 1), 0);
buzbeebbaf8942011-10-02 13:08:29 -0700283 markPreservedSingle(cUnit, sReg, res);
buzbee67bf8852011-08-17 17:51:35 -0700284 } else {
285 RegisterInfo* FPRegs = cUnit->regPool->FPRegs;
286 for (int i = 0; i < cUnit->regPool->numFPRegs; i++) {
287 if (!FPRegs[i].isTemp && !FPRegs[i].inUse &&
288 ((FPRegs[i].reg & 0x1) == 0x0) &&
289 !FPRegs[i+1].isTemp && !FPRegs[i+1].inUse &&
290 ((FPRegs[i+1].reg & 0x1) == 0x1) &&
291 (FPRegs[i].reg + 1) == FPRegs[i+1].reg) {
292 res = FPRegs[i].reg;
293 FPRegs[i].inUse = true;
buzbeebbaf8942011-10-02 13:08:29 -0700294 markPreservedSingle(cUnit, sReg, res);
buzbee67bf8852011-08-17 17:51:35 -0700295 FPRegs[i+1].inUse = true;
buzbeebbaf8942011-10-02 13:08:29 -0700296 DCHECK_EQ(res + 1, FPRegs[i+1].reg);
297 markPreservedSingle(cUnit, sReg+1, res+1);
buzbee67bf8852011-08-17 17:51:35 -0700298 break;
299 }
300 }
301 }
302 if (res != -1) {
buzbee67bc2362011-10-11 18:08:40 -0700303 cUnit->promotionMap[sReg].fpLocation = kLocPhysReg;
304 cUnit->promotionMap[sReg].fpReg = res;
305 cUnit->promotionMap[sReg+1].fpLocation = kLocPhysReg;
306 cUnit->promotionMap[sReg+1].fpReg = res + 1;
buzbee67bf8852011-08-17 17:51:35 -0700307 }
308 return res;
309}
310
311
312/*
313 * Reserve a callee-save fp register. If this register can be used
314 * as the first of a double, attempt to allocate an even pair of fp
315 * single regs (but if can't still attempt to allocate a single, preferring
316 * first to allocate an odd register.
317 */
318extern int oatAllocPreservedFPReg(CompilationUnit* cUnit, int sReg,
319 bool doubleStart)
320{
321 int res = -1;
322 if (doubleStart) {
323 res = allocPreservedDouble(cUnit, sReg);
buzbee67bf8852011-08-17 17:51:35 -0700324 }
325 if (res == -1) {
326 res = allocPreservedSingle(cUnit, sReg, false /* try odd # */);
327 }
328 if (res == -1)
329 res = allocPreservedSingle(cUnit, sReg, true /* try even # */);
330 return res;
331}
332
buzbeeed3e9302011-09-23 17:34:19 -0700333STATIC int allocTempBody(CompilationUnit* cUnit, RegisterInfo* p, int numRegs,
buzbee67bf8852011-08-17 17:51:35 -0700334 int* nextTemp, bool required)
335{
336 int i;
337 int next = *nextTemp;
338 for (i=0; i< numRegs; i++) {
339 if (next >= numRegs)
340 next = 0;
341 if (p[next].isTemp && !p[next].inUse && !p[next].live) {
342 oatClobber(cUnit, p[next].reg);
343 p[next].inUse = true;
344 p[next].pair = false;
345 *nextTemp = next + 1;
346 return p[next].reg;
347 }
348 next++;
349 }
350 next = *nextTemp;
351 for (i=0; i< numRegs; i++) {
352 if (next >= numRegs)
353 next = 0;
354 if (p[next].isTemp && !p[next].inUse) {
355 oatClobber(cUnit, p[next].reg);
356 p[next].inUse = true;
357 p[next].pair = false;
358 *nextTemp = next + 1;
359 return p[next].reg;
360 }
361 next++;
362 }
363 if (required) {
buzbee6181f792011-09-29 11:14:04 -0700364 oatCodegenDump(cUnit);
buzbee67bf8852011-08-17 17:51:35 -0700365 dumpRegPool(cUnit->regPool->coreRegs,
366 cUnit->regPool->numCoreRegs);
367 LOG(FATAL) << "No free temp registers";
368 }
369 return -1; // No register available
370}
371
372//REDO: too many assumptions.
373extern int oatAllocTempDouble(CompilationUnit* cUnit)
374{
375 RegisterInfo* p = cUnit->regPool->FPRegs;
376 int numRegs = cUnit->regPool->numFPRegs;
buzbeea50638b2011-11-02 15:15:06 -0700377 /* Start looking at an even reg */
378 int next = cUnit->regPool->nextFPReg & ~0x1;
buzbee67bf8852011-08-17 17:51:35 -0700379
buzbeea50638b2011-11-02 15:15:06 -0700380 // First try to avoid allocating live registers
381 for (int i=0; i < numRegs; i+=2) {
buzbee67bf8852011-08-17 17:51:35 -0700382 if (next >= numRegs)
383 next = 0;
384 if ((p[next].isTemp && !p[next].inUse && !p[next].live) &&
385 (p[next+1].isTemp && !p[next+1].inUse && !p[next+1].live)) {
386 oatClobber(cUnit, p[next].reg);
387 oatClobber(cUnit, p[next+1].reg);
388 p[next].inUse = true;
389 p[next+1].inUse = true;
buzbeeed3e9302011-09-23 17:34:19 -0700390 DCHECK_EQ((p[next].reg+1), p[next+1].reg);
391 DCHECK_EQ((p[next].reg & 0x1), 0);
buzbeea50638b2011-11-02 15:15:06 -0700392 cUnit->regPool->nextFPReg = next + 2;
393 if (cUnit->regPool->nextFPReg >= numRegs) {
394 cUnit->regPool->nextFPReg = 0;
395 }
buzbee67bf8852011-08-17 17:51:35 -0700396 return p[next].reg;
397 }
398 next += 2;
399 }
buzbeea50638b2011-11-02 15:15:06 -0700400 next = cUnit->regPool->nextFPReg & ~0x1;
401
402 // No choice - find a pair and kill it.
403 for (int i=0; i < numRegs; i+=2) {
buzbee67bf8852011-08-17 17:51:35 -0700404 if (next >= numRegs)
405 next = 0;
406 if (p[next].isTemp && !p[next].inUse && p[next+1].isTemp &&
407 !p[next+1].inUse) {
408 oatClobber(cUnit, p[next].reg);
409 oatClobber(cUnit, p[next+1].reg);
410 p[next].inUse = true;
411 p[next+1].inUse = true;
buzbeeed3e9302011-09-23 17:34:19 -0700412 DCHECK_EQ((p[next].reg+1), p[next+1].reg);
413 DCHECK_EQ((p[next].reg & 0x1), 0);
buzbeea50638b2011-11-02 15:15:06 -0700414 cUnit->regPool->nextFPReg = next + 2;
415 if (cUnit->regPool->nextFPReg >= numRegs) {
416 cUnit->regPool->nextFPReg = 0;
417 }
buzbee67bf8852011-08-17 17:51:35 -0700418 return p[next].reg;
419 }
420 next += 2;
421 }
buzbee6181f792011-09-29 11:14:04 -0700422 LOG(FATAL) << "No free temp registers (pair)";
buzbee67bf8852011-08-17 17:51:35 -0700423 return -1;
424}
425
426/* Return a temp if one is available, -1 otherwise */
427extern int oatAllocFreeTemp(CompilationUnit* cUnit)
428{
429 return allocTempBody(cUnit, cUnit->regPool->coreRegs,
430 cUnit->regPool->numCoreRegs,
431 &cUnit->regPool->nextCoreReg, true);
432}
433
434extern int oatAllocTemp(CompilationUnit* cUnit)
435{
436 return allocTempBody(cUnit, cUnit->regPool->coreRegs,
437 cUnit->regPool->numCoreRegs,
438 &cUnit->regPool->nextCoreReg, true);
439}
440
441extern int oatAllocTempFloat(CompilationUnit* cUnit)
442{
443 return allocTempBody(cUnit, cUnit->regPool->FPRegs,
444 cUnit->regPool->numFPRegs,
445 &cUnit->regPool->nextFPReg, true);
446}
447
buzbeeed3e9302011-09-23 17:34:19 -0700448STATIC RegisterInfo* allocLiveBody(RegisterInfo* p, int numRegs, int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700449{
450 int i;
451 if (sReg == -1)
452 return NULL;
453 for (i=0; i < numRegs; i++) {
454 if (p[i].live && (p[i].sReg == sReg)) {
455 if (p[i].isTemp)
456 p[i].inUse = true;
457 return &p[i];
458 }
459 }
460 return NULL;
461}
462
buzbeeed3e9302011-09-23 17:34:19 -0700463STATIC RegisterInfo* allocLive(CompilationUnit* cUnit, int sReg,
buzbee67bf8852011-08-17 17:51:35 -0700464 int regClass)
465{
466 RegisterInfo* res = NULL;
467 switch(regClass) {
468 case kAnyReg:
469 res = allocLiveBody(cUnit->regPool->FPRegs,
470 cUnit->regPool->numFPRegs, sReg);
471 if (res)
472 break;
473 /* Intentional fallthrough */
474 case kCoreReg:
475 res = allocLiveBody(cUnit->regPool->coreRegs,
476 cUnit->regPool->numCoreRegs, sReg);
477 break;
478 case kFPReg:
479 res = allocLiveBody(cUnit->regPool->FPRegs,
480 cUnit->regPool->numFPRegs, sReg);
481 break;
482 default:
483 LOG(FATAL) << "Invalid register type";
484 }
485 return res;
486}
487
488extern void oatFreeTemp(CompilationUnit* cUnit, int reg)
489{
490 RegisterInfo* p = cUnit->regPool->coreRegs;
491 int numRegs = cUnit->regPool->numCoreRegs;
492 int i;
493 for (i=0; i< numRegs; i++) {
494 if (p[i].reg == reg) {
495 if (p[i].isTemp) {
496 p[i].inUse = false;
497 }
498 p[i].pair = false;
499 return;
500 }
501 }
502 p = cUnit->regPool->FPRegs;
503 numRegs = cUnit->regPool->numFPRegs;
504 for (i=0; i< numRegs; i++) {
505 if (p[i].reg == reg) {
506 if (p[i].isTemp) {
507 p[i].inUse = false;
508 }
509 p[i].pair = false;
510 return;
511 }
512 }
513 LOG(FATAL) << "Tried to free a non-existant temp: r" << reg;
514}
515
516extern RegisterInfo* oatIsLive(CompilationUnit* cUnit, int reg)
517{
518 RegisterInfo* p = cUnit->regPool->coreRegs;
519 int numRegs = cUnit->regPool->numCoreRegs;
520 int i;
521 for (i=0; i< numRegs; i++) {
522 if (p[i].reg == reg) {
523 return p[i].live ? &p[i] : NULL;
524 }
525 }
526 p = cUnit->regPool->FPRegs;
527 numRegs = cUnit->regPool->numFPRegs;
528 for (i=0; i< numRegs; i++) {
529 if (p[i].reg == reg) {
530 return p[i].live ? &p[i] : NULL;
531 }
532 }
533 return NULL;
534}
535
536extern RegisterInfo* oatIsTemp(CompilationUnit* cUnit, int reg)
537{
buzbee68253262011-10-07 14:02:25 -0700538 RegisterInfo* p = oatGetRegInfo(cUnit, reg);
buzbee67bf8852011-08-17 17:51:35 -0700539 return (p->isTemp) ? p : NULL;
540}
541
buzbeeb29e4d12011-09-26 15:05:48 -0700542extern RegisterInfo* oatIsPromoted(CompilationUnit* cUnit, int reg)
543{
buzbee68253262011-10-07 14:02:25 -0700544 RegisterInfo* p = oatGetRegInfo(cUnit, reg);
buzbeeb29e4d12011-09-26 15:05:48 -0700545 return (p->isTemp) ? NULL : p;
546}
547
buzbee67bf8852011-08-17 17:51:35 -0700548extern bool oatIsDirty(CompilationUnit* cUnit, int reg)
549{
buzbee68253262011-10-07 14:02:25 -0700550 RegisterInfo* p = oatGetRegInfo(cUnit, reg);
buzbee67bf8852011-08-17 17:51:35 -0700551 return p->dirty;
552}
553
554/*
555 * Similar to oatAllocTemp(), but forces the allocation of a specific
556 * register. No check is made to see if the register was previously
557 * allocated. Use with caution.
558 */
559extern void oatLockTemp(CompilationUnit* cUnit, int reg)
560{
561 RegisterInfo* p = cUnit->regPool->coreRegs;
562 int numRegs = cUnit->regPool->numCoreRegs;
563 int i;
564 for (i=0; i< numRegs; i++) {
565 if (p[i].reg == reg) {
buzbeeed3e9302011-09-23 17:34:19 -0700566 DCHECK(p[i].isTemp);
buzbee67bf8852011-08-17 17:51:35 -0700567 p[i].inUse = true;
568 p[i].live = false;
569 return;
570 }
571 }
572 p = cUnit->regPool->FPRegs;
573 numRegs = cUnit->regPool->numFPRegs;
574 for (i=0; i< numRegs; i++) {
575 if (p[i].reg == reg) {
buzbeeed3e9302011-09-23 17:34:19 -0700576 DCHECK(p[i].isTemp);
buzbee67bf8852011-08-17 17:51:35 -0700577 p[i].inUse = true;
578 p[i].live = false;
579 return;
580 }
581 }
582 LOG(FATAL) << "Tried to lock a non-existant temp: r" << reg;
583}
584
buzbee5abfa3e2012-01-31 17:01:43 -0800585static inline void resetDefBody(RegisterInfo* p)
buzbee67bf8852011-08-17 17:51:35 -0700586{
buzbee67bf8852011-08-17 17:51:35 -0700587 p->defStart = NULL;
588 p->defEnd = NULL;
589}
590
buzbee5abfa3e2012-01-31 17:01:43 -0800591extern void oatResetDef(CompilationUnit* cUnit, int reg)
592{
593 resetDefBody(oatGetRegInfo(cUnit, reg));
594}
595
buzbeeed3e9302011-09-23 17:34:19 -0700596STATIC void nullifyRange(CompilationUnit* cUnit, LIR *start, LIR *finish,
buzbee67bf8852011-08-17 17:51:35 -0700597 int sReg1, int sReg2)
598{
599 if (start && finish) {
600 LIR *p;
buzbeeed3e9302011-09-23 17:34:19 -0700601 DCHECK_EQ(sReg1, sReg2);
buzbee67bf8852011-08-17 17:51:35 -0700602 for (p = start; ;p = p->next) {
603 ((ArmLIR *)p)->flags.isNop = true;
buzbee6181f792011-09-29 11:14:04 -0700604 ((ArmLIR *)p)->flags.squashed = true;
buzbee67bf8852011-08-17 17:51:35 -0700605 if (p == finish)
606 break;
607 }
608 }
609}
610
611/*
612 * Mark the beginning and end LIR of a def sequence. Note that
613 * on entry start points to the LIR prior to the beginning of the
614 * sequence.
615 */
616extern void oatMarkDef(CompilationUnit* cUnit, RegLocation rl,
617 LIR *start, LIR *finish)
618{
buzbeeed3e9302011-09-23 17:34:19 -0700619 DCHECK(!rl.wide);
620 DCHECK(start && start->next);
621 DCHECK(finish);
buzbee68253262011-10-07 14:02:25 -0700622 RegisterInfo* p = oatGetRegInfo(cUnit, rl.lowReg);
buzbee67bf8852011-08-17 17:51:35 -0700623 p->defStart = start->next;
624 p->defEnd = finish;
625}
626
627/*
628 * Mark the beginning and end LIR of a def sequence. Note that
629 * on entry start points to the LIR prior to the beginning of the
630 * sequence.
631 */
632extern void oatMarkDefWide(CompilationUnit* cUnit, RegLocation rl,
633 LIR *start, LIR *finish)
634{
buzbeeed3e9302011-09-23 17:34:19 -0700635 DCHECK(rl.wide);
636 DCHECK(start && start->next);
637 DCHECK(finish);
buzbee68253262011-10-07 14:02:25 -0700638 RegisterInfo* p = oatGetRegInfo(cUnit, rl.lowReg);
buzbee67bf8852011-08-17 17:51:35 -0700639 oatResetDef(cUnit, rl.highReg); // Only track low of pair
640 p->defStart = start->next;
641 p->defEnd = finish;
642}
643
644extern RegLocation oatWideToNarrow(CompilationUnit* cUnit,
645 RegLocation rl)
646{
buzbeeed3e9302011-09-23 17:34:19 -0700647 DCHECK(rl.wide);
buzbee67bf8852011-08-17 17:51:35 -0700648 if (rl.location == kLocPhysReg) {
buzbee68253262011-10-07 14:02:25 -0700649 RegisterInfo* infoLo = oatGetRegInfo(cUnit, rl.lowReg);
650 RegisterInfo* infoHi = oatGetRegInfo(cUnit, rl.highReg);
buzbee0c7f26d2011-09-07 12:28:51 -0700651 if (infoLo->isTemp) {
652 infoLo->pair = false;
653 infoLo->defStart = NULL;
654 infoLo->defEnd = NULL;
buzbee67bf8852011-08-17 17:51:35 -0700655 }
buzbee0c7f26d2011-09-07 12:28:51 -0700656 if (infoHi->isTemp) {
657 infoHi->pair = false;
658 infoHi->defStart = NULL;
659 infoHi->defEnd = NULL;
buzbee67bf8852011-08-17 17:51:35 -0700660 }
buzbee67bf8852011-08-17 17:51:35 -0700661 }
662 rl.wide = false;
663 return rl;
664}
665
666extern void oatResetDefLoc(CompilationUnit* cUnit, RegLocation rl)
667{
buzbeeed3e9302011-09-23 17:34:19 -0700668 DCHECK(!rl.wide);
buzbee6181f792011-09-29 11:14:04 -0700669 RegisterInfo* p = oatIsTemp(cUnit, rl.lowReg);
670 if (p && !(cUnit->disableOpt & (1 << kSuppressLoads))) {
buzbeeed3e9302011-09-23 17:34:19 -0700671 DCHECK(!p->pair);
buzbee67bf8852011-08-17 17:51:35 -0700672 nullifyRange(cUnit, p->defStart, p->defEnd,
673 p->sReg, rl.sRegLow);
674 }
675 oatResetDef(cUnit, rl.lowReg);
676}
677
678extern void oatResetDefLocWide(CompilationUnit* cUnit, RegLocation rl)
679{
buzbeeed3e9302011-09-23 17:34:19 -0700680 DCHECK(rl.wide);
buzbee6181f792011-09-29 11:14:04 -0700681 RegisterInfo* pLow = oatIsTemp(cUnit, rl.lowReg);
682 RegisterInfo* pHigh = oatIsTemp(cUnit, rl.highReg);
683 if (pLow && !(cUnit->disableOpt & (1 << kSuppressLoads))) {
684 DCHECK(pLow->pair);
685 nullifyRange(cUnit, pLow->defStart, pLow->defEnd,
686 pLow->sReg, rl.sRegLow);
687 }
688 if (pHigh && !(cUnit->disableOpt & (1 << kSuppressLoads))) {
689 DCHECK(pHigh->pair);
buzbee67bf8852011-08-17 17:51:35 -0700690 }
691 oatResetDef(cUnit, rl.lowReg);
692 oatResetDef(cUnit, rl.highReg);
693}
694
695extern void oatResetDefTracking(CompilationUnit* cUnit)
696{
697 int i;
698 for (i=0; i< cUnit->regPool->numCoreRegs; i++) {
buzbee5abfa3e2012-01-31 17:01:43 -0800699 resetDefBody(&cUnit->regPool->coreRegs[i]);
buzbee67bf8852011-08-17 17:51:35 -0700700 }
701 for (i=0; i< cUnit->regPool->numFPRegs; i++) {
buzbee5abfa3e2012-01-31 17:01:43 -0800702 resetDefBody(&cUnit->regPool->FPRegs[i]);
buzbee67bf8852011-08-17 17:51:35 -0700703 }
704}
705
706extern void oatClobberAllRegs(CompilationUnit* cUnit)
707{
708 int i;
709 for (i=0; i< cUnit->regPool->numCoreRegs; i++) {
buzbee5abfa3e2012-01-31 17:01:43 -0800710 clobberBody(cUnit, &cUnit->regPool->coreRegs[i]);
buzbee67bf8852011-08-17 17:51:35 -0700711 }
712 for (i=0; i< cUnit->regPool->numFPRegs; i++) {
buzbee5abfa3e2012-01-31 17:01:43 -0800713 clobberBody(cUnit, &cUnit->regPool->FPRegs[i]);
buzbee67bf8852011-08-17 17:51:35 -0700714 }
715}
716
717/* To be used when explicitly managing register use */
buzbee2e748f32011-08-29 21:02:19 -0700718extern void oatLockCallTemps(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700719{
buzbee2e748f32011-08-29 21:02:19 -0700720 //TODO: Arm specific - move to target dependent code
721 oatLockTemp(cUnit, r0);
722 oatLockTemp(cUnit, r1);
723 oatLockTemp(cUnit, r2);
724 oatLockTemp(cUnit, r3);
buzbee67bf8852011-08-17 17:51:35 -0700725}
726
buzbee0d966cf2011-09-08 17:34:58 -0700727/* To be used when explicitly managing register use */
728extern void oatFreeCallTemps(CompilationUnit* cUnit)
729{
730 //TODO: Arm specific - move to target dependent code
731 oatFreeTemp(cUnit, r0);
732 oatFreeTemp(cUnit, r1);
733 oatFreeTemp(cUnit, r2);
734 oatFreeTemp(cUnit, r3);
735}
736
buzbee67bf8852011-08-17 17:51:35 -0700737// Make sure nothing is live and dirty
buzbeeed3e9302011-09-23 17:34:19 -0700738STATIC void flushAllRegsBody(CompilationUnit* cUnit, RegisterInfo* info,
buzbee67bf8852011-08-17 17:51:35 -0700739 int numRegs)
740{
741 int i;
742 for (i=0; i < numRegs; i++) {
743 if (info[i].live && info[i].dirty) {
744 if (info[i].pair) {
745 oatFlushRegWide(cUnit, info[i].reg, info[i].partner);
746 } else {
747 oatFlushReg(cUnit, info[i].reg);
748 }
749 }
750 }
751}
752
753extern void oatFlushAllRegs(CompilationUnit* cUnit)
754{
755 flushAllRegsBody(cUnit, cUnit->regPool->coreRegs,
756 cUnit->regPool->numCoreRegs);
757 flushAllRegsBody(cUnit, cUnit->regPool->FPRegs,
758 cUnit->regPool->numFPRegs);
759 oatClobberAllRegs(cUnit);
760}
761
762
763//TUNING: rewrite all of this reg stuff. Probably use an attribute table
buzbeeed3e9302011-09-23 17:34:19 -0700764STATIC bool regClassMatches(int regClass, int reg)
buzbee67bf8852011-08-17 17:51:35 -0700765{
766 if (regClass == kAnyReg) {
767 return true;
768 } else if (regClass == kCoreReg) {
769 return !FPREG(reg);
770 } else {
771 return FPREG(reg);
772 }
773}
774
775extern void oatMarkLive(CompilationUnit* cUnit, int reg, int sReg)
776{
buzbee68253262011-10-07 14:02:25 -0700777 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
buzbee67bf8852011-08-17 17:51:35 -0700778 if ((info->reg == reg) && (info->sReg == sReg) && info->live) {
779 return; /* already live */
780 } else if (sReg != INVALID_SREG) {
781 oatClobberSReg(cUnit, sReg);
782 if (info->isTemp) {
783 info->live = true;
784 }
785 } else {
786 /* Can't be live if no associated sReg */
buzbeeed3e9302011-09-23 17:34:19 -0700787 DCHECK(info->isTemp);
buzbee67bf8852011-08-17 17:51:35 -0700788 info->live = false;
789 }
790 info->sReg = sReg;
791}
792
793extern void oatMarkTemp(CompilationUnit* cUnit, int reg)
794{
buzbee68253262011-10-07 14:02:25 -0700795 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
buzbee67bf8852011-08-17 17:51:35 -0700796 info->isTemp = true;
797}
798
buzbee9e0f9b02011-08-24 15:32:46 -0700799extern void oatUnmarkTemp(CompilationUnit* cUnit, int reg)
800{
buzbee68253262011-10-07 14:02:25 -0700801 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
buzbee9e0f9b02011-08-24 15:32:46 -0700802 info->isTemp = false;
803}
804
buzbee67bf8852011-08-17 17:51:35 -0700805extern void oatMarkPair(CompilationUnit* cUnit, int lowReg, int highReg)
806{
buzbee68253262011-10-07 14:02:25 -0700807 RegisterInfo* infoLo = oatGetRegInfo(cUnit, lowReg);
808 RegisterInfo* infoHi = oatGetRegInfo(cUnit, highReg);
buzbee67bf8852011-08-17 17:51:35 -0700809 infoLo->pair = infoHi->pair = true;
810 infoLo->partner = highReg;
811 infoHi->partner = lowReg;
812}
813
814extern void oatMarkClean(CompilationUnit* cUnit, RegLocation loc)
815{
buzbee68253262011-10-07 14:02:25 -0700816 RegisterInfo* info = oatGetRegInfo(cUnit, loc.lowReg);
buzbee67bf8852011-08-17 17:51:35 -0700817 info->dirty = false;
818 if (loc.wide) {
buzbee68253262011-10-07 14:02:25 -0700819 info = oatGetRegInfo(cUnit, loc.highReg);
buzbee67bf8852011-08-17 17:51:35 -0700820 info->dirty = false;
821 }
822}
823
824extern void oatMarkDirty(CompilationUnit* cUnit, RegLocation loc)
825{
826 if (loc.home) {
827 // If already home, can't be dirty
828 return;
829 }
buzbee68253262011-10-07 14:02:25 -0700830 RegisterInfo* info = oatGetRegInfo(cUnit, loc.lowReg);
buzbee67bf8852011-08-17 17:51:35 -0700831 info->dirty = true;
832 if (loc.wide) {
buzbee68253262011-10-07 14:02:25 -0700833 info = oatGetRegInfo(cUnit, loc.highReg);
buzbee67bf8852011-08-17 17:51:35 -0700834 info->dirty = true;
835 }
836}
837
838extern void oatMarkInUse(CompilationUnit* cUnit, int reg)
839{
buzbee68253262011-10-07 14:02:25 -0700840 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
buzbee67bf8852011-08-17 17:51:35 -0700841 info->inUse = true;
842}
843
buzbeeed3e9302011-09-23 17:34:19 -0700844STATIC void copyRegInfo(CompilationUnit* cUnit, int newReg, int oldReg)
buzbee67bf8852011-08-17 17:51:35 -0700845{
buzbee68253262011-10-07 14:02:25 -0700846 RegisterInfo* newInfo = oatGetRegInfo(cUnit, newReg);
847 RegisterInfo* oldInfo = oatGetRegInfo(cUnit, oldReg);
buzbeeec5adf32011-09-11 15:25:43 -0700848 // Target temp status must not change
849 bool isTemp = newInfo->isTemp;
buzbee67bf8852011-08-17 17:51:35 -0700850 *newInfo = *oldInfo;
buzbeeec5adf32011-09-11 15:25:43 -0700851 // Restore target's temp status
852 newInfo->isTemp = isTemp;
buzbee67bf8852011-08-17 17:51:35 -0700853 newInfo->reg = newReg;
854}
855
856/*
857 * Return an updated location record with current in-register status.
858 * If the value lives in live temps, reflect that fact. No code
buzbeeb29e4d12011-09-26 15:05:48 -0700859 * is generated. If the live value is part of an older pair,
buzbee67bf8852011-08-17 17:51:35 -0700860 * clobber both low and high.
861 * TUNING: clobbering both is a bit heavy-handed, but the alternative
862 * is a bit complex when dealing with FP regs. Examine code to see
863 * if it's worthwhile trying to be more clever here.
864 */
865
866extern RegLocation oatUpdateLoc(CompilationUnit* cUnit, RegLocation loc)
867{
buzbeeed3e9302011-09-23 17:34:19 -0700868 DCHECK(!loc.wide);
buzbee6181f792011-09-29 11:14:04 -0700869 DCHECK(oatCheckCorePoolSanity(cUnit));
buzbee67bf8852011-08-17 17:51:35 -0700870 if (loc.location == kLocDalvikFrame) {
871 RegisterInfo* infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
872 if (infoLo) {
873 if (infoLo->pair) {
874 oatClobber(cUnit, infoLo->reg);
875 oatClobber(cUnit, infoLo->partner);
buzbee58f92742011-10-01 11:22:17 -0700876 oatFreeTemp(cUnit, infoLo->reg);
buzbee67bf8852011-08-17 17:51:35 -0700877 } else {
878 loc.lowReg = infoLo->reg;
879 loc.location = kLocPhysReg;
880 }
881 }
882 }
883
884 return loc;
885}
886
buzbee6181f792011-09-29 11:14:04 -0700887bool oatCheckCorePoolSanity(CompilationUnit* cUnit)
888{
889 for (static int i = 0; i < cUnit->regPool->numCoreRegs; i++) {
890 if (cUnit->regPool->coreRegs[i].pair) {
891 static int myReg = cUnit->regPool->coreRegs[i].reg;
892 static int mySreg = cUnit->regPool->coreRegs[i].sReg;
893 static int partnerReg = cUnit->regPool->coreRegs[i].partner;
buzbee68253262011-10-07 14:02:25 -0700894 static RegisterInfo* partner = oatGetRegInfo(cUnit, partnerReg);
buzbee6181f792011-09-29 11:14:04 -0700895 DCHECK(partner != NULL);
896 DCHECK(partner->pair);
897 DCHECK_EQ(myReg, partner->partner);
898 static int partnerSreg = partner->sReg;
899 if (mySreg == INVALID_SREG) {
900 DCHECK_EQ(partnerSreg, INVALID_SREG);
901 } else {
902 int diff = mySreg - partnerSreg;
903 DCHECK((diff == -1) || (diff == 1));
904 }
905 }
906 if (!cUnit->regPool->coreRegs[i].live) {
907 DCHECK(cUnit->regPool->coreRegs[i].defStart == NULL);
908 DCHECK(cUnit->regPool->coreRegs[i].defEnd == NULL);
909 }
910 }
911 return true;
912}
913
buzbee67bf8852011-08-17 17:51:35 -0700914/* see comments for updateLoc */
915extern RegLocation oatUpdateLocWide(CompilationUnit* cUnit,
916 RegLocation loc)
917{
buzbeeed3e9302011-09-23 17:34:19 -0700918 DCHECK(loc.wide);
buzbee6181f792011-09-29 11:14:04 -0700919 DCHECK(oatCheckCorePoolSanity(cUnit));
buzbee67bf8852011-08-17 17:51:35 -0700920 if (loc.location == kLocDalvikFrame) {
921 // Are the dalvik regs already live in physical registers?
922 RegisterInfo* infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
923 RegisterInfo* infoHi = allocLive(cUnit,
924 oatSRegHi(loc.sRegLow), kAnyReg);
925 bool match = true;
926 match = match && (infoLo != NULL);
927 match = match && (infoHi != NULL);
928 // Are they both core or both FP?
929 match = match && (FPREG(infoLo->reg) == FPREG(infoHi->reg));
930 // If a pair of floating point singles, are they properly aligned?
931 if (match && FPREG(infoLo->reg)) {
932 match &= ((infoLo->reg & 0x1) == 0);
933 match &= ((infoHi->reg - infoLo->reg) == 1);
934 }
935 // If previously used as a pair, it is the same pair?
936 if (match && (infoLo->pair || infoHi->pair)) {
937 match = (infoLo->pair == infoHi->pair);
938 match &= ((infoLo->reg == infoHi->partner) &&
939 (infoHi->reg == infoLo->partner));
940 }
941 if (match) {
942 // Can reuse - update the register usage info
943 loc.lowReg = infoLo->reg;
944 loc.highReg = infoHi->reg;
945 loc.location = kLocPhysReg;
946 oatMarkPair(cUnit, loc.lowReg, loc.highReg);
buzbeeed3e9302011-09-23 17:34:19 -0700947 DCHECK(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
buzbee67bf8852011-08-17 17:51:35 -0700948 return loc;
949 }
buzbee58f92742011-10-01 11:22:17 -0700950 // Can't easily reuse - clobber and free any overlaps
buzbee67bf8852011-08-17 17:51:35 -0700951 if (infoLo) {
952 oatClobber(cUnit, infoLo->reg);
buzbee58f92742011-10-01 11:22:17 -0700953 oatFreeTemp(cUnit, infoLo->reg);
buzbee67bf8852011-08-17 17:51:35 -0700954 if (infoLo->pair)
955 oatClobber(cUnit, infoLo->partner);
956 }
957 if (infoHi) {
958 oatClobber(cUnit, infoHi->reg);
buzbee58f92742011-10-01 11:22:17 -0700959 oatFreeTemp(cUnit, infoHi->reg);
buzbee67bf8852011-08-17 17:51:35 -0700960 if (infoHi->pair)
961 oatClobber(cUnit, infoHi->partner);
962 }
963 }
964 return loc;
965}
966
buzbeeed3e9302011-09-23 17:34:19 -0700967
968/* For use in cases we don't know (or care) width */
969extern RegLocation oatUpdateRawLoc(CompilationUnit* cUnit,
970 RegLocation loc)
971{
972 if (loc.wide)
973 return oatUpdateLocWide(cUnit, loc);
974 else
975 return oatUpdateLoc(cUnit, loc);
976}
977
978STATIC RegLocation evalLocWide(CompilationUnit* cUnit, RegLocation loc,
buzbee67bf8852011-08-17 17:51:35 -0700979 int regClass, bool update)
980{
buzbeeed3e9302011-09-23 17:34:19 -0700981 DCHECK(loc.wide);
buzbee67bf8852011-08-17 17:51:35 -0700982 int newRegs;
983 int lowReg;
984 int highReg;
985
986 loc = oatUpdateLocWide(cUnit, loc);
987
988 /* If already in registers, we can assume proper form. Right reg class? */
989 if (loc.location == kLocPhysReg) {
buzbeeed3e9302011-09-23 17:34:19 -0700990 DCHECK_EQ(FPREG(loc.lowReg), FPREG(loc.highReg));
991 DCHECK(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
buzbee67bf8852011-08-17 17:51:35 -0700992 if (!regClassMatches(regClass, loc.lowReg)) {
993 /* Wrong register class. Reallocate and copy */
994 newRegs = oatAllocTypedTempPair(cUnit, loc.fp, regClass);
995 lowReg = newRegs & 0xff;
996 highReg = (newRegs >> 8) & 0xff;
997 oatRegCopyWide(cUnit, lowReg, highReg, loc.lowReg,
998 loc.highReg);
999 copyRegInfo(cUnit, lowReg, loc.lowReg);
1000 copyRegInfo(cUnit, highReg, loc.highReg);
1001 oatClobber(cUnit, loc.lowReg);
1002 oatClobber(cUnit, loc.highReg);
1003 loc.lowReg = lowReg;
1004 loc.highReg = highReg;
1005 oatMarkPair(cUnit, loc.lowReg, loc.highReg);
buzbeeed3e9302011-09-23 17:34:19 -07001006 DCHECK(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
buzbee67bf8852011-08-17 17:51:35 -07001007 }
1008 return loc;
1009 }
1010
buzbeeed3e9302011-09-23 17:34:19 -07001011 DCHECK_NE(loc.sRegLow, INVALID_SREG);
1012 DCHECK_NE(oatSRegHi(loc.sRegLow), INVALID_SREG);
buzbee67bf8852011-08-17 17:51:35 -07001013
1014 newRegs = oatAllocTypedTempPair(cUnit, loc.fp, regClass);
1015 loc.lowReg = newRegs & 0xff;
1016 loc.highReg = (newRegs >> 8) & 0xff;
1017
1018 oatMarkPair(cUnit, loc.lowReg, loc.highReg);
1019 if (update) {
1020 loc.location = kLocPhysReg;
1021 oatMarkLive(cUnit, loc.lowReg, loc.sRegLow);
1022 oatMarkLive(cUnit, loc.highReg, oatSRegHi(loc.sRegLow));
1023 }
buzbeeed3e9302011-09-23 17:34:19 -07001024 DCHECK(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
buzbee67bf8852011-08-17 17:51:35 -07001025 return loc;
1026}
1027
1028extern RegLocation oatEvalLoc(CompilationUnit* cUnit, RegLocation loc,
1029 int regClass, bool update)
1030{
1031 int newReg;
1032
1033 if (loc.wide)
1034 return evalLocWide(cUnit, loc, regClass, update);
1035
1036 loc = oatUpdateLoc(cUnit, loc);
1037
1038 if (loc.location == kLocPhysReg) {
1039 if (!regClassMatches(regClass, loc.lowReg)) {
1040 /* Wrong register class. Realloc, copy and transfer ownership */
1041 newReg = oatAllocTypedTemp(cUnit, loc.fp, regClass);
1042 oatRegCopy(cUnit, newReg, loc.lowReg);
1043 copyRegInfo(cUnit, newReg, loc.lowReg);
1044 oatClobber(cUnit, loc.lowReg);
1045 loc.lowReg = newReg;
1046 }
1047 return loc;
1048 }
1049
buzbeeed3e9302011-09-23 17:34:19 -07001050 DCHECK_NE(loc.sRegLow, INVALID_SREG);
buzbee67bf8852011-08-17 17:51:35 -07001051
1052 newReg = oatAllocTypedTemp(cUnit, loc.fp, regClass);
1053 loc.lowReg = newReg;
1054
1055 if (update) {
1056 loc.location = kLocPhysReg;
1057 oatMarkLive(cUnit, loc.lowReg, loc.sRegLow);
1058 }
1059 return loc;
1060}
1061
1062extern RegLocation oatGetDest(CompilationUnit* cUnit, MIR* mir, int num)
1063{
buzbeee9a72f62011-09-04 17:59:07 -07001064 RegLocation res = cUnit->regLocation[mir->ssaRep->defs[num]];
buzbeeed3e9302011-09-23 17:34:19 -07001065 DCHECK(!res.wide);
buzbeee9a72f62011-09-04 17:59:07 -07001066 return res;
buzbee67bf8852011-08-17 17:51:35 -07001067}
1068extern RegLocation oatGetSrc(CompilationUnit* cUnit, MIR* mir, int num)
1069{
buzbeee9a72f62011-09-04 17:59:07 -07001070 RegLocation res = cUnit->regLocation[mir->ssaRep->uses[num]];
buzbeeed3e9302011-09-23 17:34:19 -07001071 DCHECK(!res.wide);
buzbeee9a72f62011-09-04 17:59:07 -07001072 return res;
1073}
1074extern RegLocation oatGetRawSrc(CompilationUnit* cUnit, MIR* mir, int num)
1075{
1076 RegLocation res = cUnit->regLocation[mir->ssaRep->uses[num]];
1077 return res;
buzbee67bf8852011-08-17 17:51:35 -07001078}
1079extern RegLocation oatGetDestWide(CompilationUnit* cUnit, MIR* mir,
1080 int low, int high)
1081{
buzbeee9a72f62011-09-04 17:59:07 -07001082 RegLocation res = cUnit->regLocation[mir->ssaRep->defs[low]];
buzbeeed3e9302011-09-23 17:34:19 -07001083 DCHECK(res.wide);
buzbeee9a72f62011-09-04 17:59:07 -07001084 return res;
buzbee67bf8852011-08-17 17:51:35 -07001085}
1086
1087extern RegLocation oatGetSrcWide(CompilationUnit* cUnit, MIR* mir,
1088 int low, int high)
1089{
buzbeee9a72f62011-09-04 17:59:07 -07001090 RegLocation res = cUnit->regLocation[mir->ssaRep->uses[low]];
buzbeeed3e9302011-09-23 17:34:19 -07001091 DCHECK(res.wide);
buzbeee9a72f62011-09-04 17:59:07 -07001092 return res;
buzbee67bf8852011-08-17 17:51:35 -07001093}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -08001094
1095} // namespace art