blob: 7dcb95bd36562b610835a6cdcd4071e52cd85fa5 [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. */
140void oatClobber(CompilationUnit* cUnit, int reg)
141{
buzbee68253262011-10-07 14:02:25 -0700142 RegisterInfo* p = oatGetRegInfo(cUnit, reg);
143 if (p->isTemp) {
144 DCHECK(!(p->live && p->dirty)) << "Live & dirty temp in clobber";
145 p->live = false;
146 p->sReg = INVALID_SREG;
147 p->defStart = NULL;
148 p->defEnd = NULL;
149 if (p->pair) {
150 p->pair = false;
151 oatClobber(cUnit, p->partner);
152 }
buzbee67bf8852011-08-17 17:51:35 -0700153 }
154}
155
buzbeeed3e9302011-09-23 17:34:19 -0700156STATIC void clobberSRegBody(RegisterInfo* p, int numRegs, int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700157{
158 int i;
159 for (i=0; i< numRegs; i++) {
160 if (p[i].sReg == sReg) {
161 if (p[i].isTemp) {
162 p[i].live = false;
163 }
164 p[i].defStart = NULL;
165 p[i].defEnd = NULL;
166 }
167 }
168}
169
170/* Clobber any temp associated with an sReg. Could be in either class */
171extern void oatClobberSReg(CompilationUnit* cUnit, int sReg)
172{
173 clobberSRegBody(cUnit->regPool->coreRegs, cUnit->regPool->numCoreRegs,
174 sReg);
175 clobberSRegBody(cUnit->regPool->FPRegs, cUnit->regPool->numFPRegs,
176 sReg);
177}
178
179/* Reserve a callee-save register. Return -1 if none available */
180extern int oatAllocPreservedCoreReg(CompilationUnit* cUnit, int sReg)
181{
182 int res = -1;
183 RegisterInfo* coreRegs = cUnit->regPool->coreRegs;
184 for (int i = 0; i < cUnit->regPool->numCoreRegs; i++) {
185 if (!coreRegs[i].isTemp && !coreRegs[i].inUse) {
186 res = coreRegs[i].reg;
187 coreRegs[i].inUse = true;
188 cUnit->coreSpillMask |= (1 << res);
buzbeec41e5b52011-09-23 12:46:19 -0700189 cUnit->coreVmapTable.push_back(sReg);
buzbeebbaf8942011-10-02 13:08:29 -0700190 cUnit->numCoreSpills++;
buzbee67bc2362011-10-11 18:08:40 -0700191 // Should be promoting based on initial sReg set
192 DCHECK_EQ(sReg, oatS2VReg(cUnit, sReg));
193 cUnit->promotionMap[sReg].coreLocation = kLocPhysReg;
194 cUnit->promotionMap[sReg].coreReg = res;
buzbee67bf8852011-08-17 17:51:35 -0700195 break;
196 }
197 }
198 return res;
199}
200
201/*
buzbeebbaf8942011-10-02 13:08:29 -0700202 * Mark a callee-save fp register as promoted. Note that
203 * vpush/vpop uses contiguous register lists so we must
204 * include any holes in the mask. Associate holes with
buzbee3ddc0d12011-10-05 10:36:21 -0700205 * Dalvik register INVALID_VREG (0xFFFFU).
buzbeebbaf8942011-10-02 13:08:29 -0700206 */
207STATIC void markPreservedSingle(CompilationUnit* cUnit, int sReg, int reg)
208{
209 DCHECK_GE(reg, FP_REG_MASK + FP_CALLEE_SAVE_BASE);
210 reg = (reg & FP_REG_MASK) - FP_CALLEE_SAVE_BASE;
211 // Ensure fpVmapTable is large enough
212 int tableSize = cUnit->fpVmapTable.size();
213 for (int i = tableSize; i < (reg + 1); i++) {
buzbee3ddc0d12011-10-05 10:36:21 -0700214 cUnit->fpVmapTable.push_back(INVALID_VREG);
buzbeebbaf8942011-10-02 13:08:29 -0700215 }
216 // Add the current mapping
217 cUnit->fpVmapTable[reg] = sReg;
218 // Size of fpVmapTable is high-water mark, use to set mask
219 cUnit->numFPSpills = cUnit->fpVmapTable.size();
220 cUnit->fpSpillMask = ((1 << cUnit->numFPSpills) - 1) << FP_CALLEE_SAVE_BASE;
221}
222
223/*
buzbee67bf8852011-08-17 17:51:35 -0700224 * Reserve a callee-save fp single register. Try to fullfill request for
225 * even/odd allocation, but go ahead and allocate anything if not
226 * available. If nothing's available, return -1.
227 */
buzbeeed3e9302011-09-23 17:34:19 -0700228STATIC int allocPreservedSingle(CompilationUnit* cUnit, int sReg, bool even)
buzbee67bf8852011-08-17 17:51:35 -0700229{
230 int res = -1;
231 RegisterInfo* FPRegs = cUnit->regPool->FPRegs;
232 for (int i = 0; i < cUnit->regPool->numFPRegs; i++) {
233 if (!FPRegs[i].isTemp && !FPRegs[i].inUse &&
234 ((FPRegs[i].reg & 0x1) == 0) == even) {
235 res = FPRegs[i].reg;
236 FPRegs[i].inUse = true;
buzbee67bc2362011-10-11 18:08:40 -0700237 // Should be promoting based on initial sReg set
238 DCHECK_EQ(sReg, oatS2VReg(cUnit, sReg));
buzbeebbaf8942011-10-02 13:08:29 -0700239 markPreservedSingle(cUnit, sReg, res);
buzbee67bc2362011-10-11 18:08:40 -0700240 cUnit->promotionMap[sReg].fpLocation = kLocPhysReg;
241 cUnit->promotionMap[sReg].fpReg = res;
buzbee67bf8852011-08-17 17:51:35 -0700242 break;
243 }
244 }
245 return res;
246}
247
248/*
249 * Somewhat messy code here. We want to allocate a pair of contiguous
250 * physical single-precision floating point registers starting with
251 * an even numbered reg. It is possible that the paired sReg (sReg+1)
252 * has already been allocated - try to fit if possible. Fail to
253 * allocate if we can't meet the requirements for the pair of
254 * sReg<=sX[even] & (sReg+1)<= sX+1.
255 */
buzbeeed3e9302011-09-23 17:34:19 -0700256STATIC int allocPreservedDouble(CompilationUnit* cUnit, int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700257{
258 int res = -1; // Assume failure
buzbee67bc2362011-10-11 18:08:40 -0700259 // Should be promoting based on initial sReg set
260 DCHECK_EQ(sReg, oatS2VReg(cUnit, sReg));
261 if (cUnit->promotionMap[sReg+1].fpLocation == kLocPhysReg) {
buzbee67bf8852011-08-17 17:51:35 -0700262 // Upper reg is already allocated. Can we fit?
buzbee67bc2362011-10-11 18:08:40 -0700263 int highReg = cUnit->promotionMap[sReg+1].fpReg;
buzbee67bf8852011-08-17 17:51:35 -0700264 if ((highReg & 1) == 0) {
265 // High reg is even - fail.
266 return res;
267 }
268 // Is the low reg of the pair free?
buzbee68253262011-10-07 14:02:25 -0700269 RegisterInfo* p = oatGetRegInfo(cUnit, highReg-1);
buzbee67bf8852011-08-17 17:51:35 -0700270 if (p->inUse || p->isTemp) {
271 // Already allocated or not preserved - fail.
272 return res;
273 }
274 // OK - good to go.
275 res = p->reg;
276 p->inUse = true;
buzbeeed3e9302011-09-23 17:34:19 -0700277 DCHECK_EQ((res & 1), 0);
buzbeebbaf8942011-10-02 13:08:29 -0700278 markPreservedSingle(cUnit, sReg, res);
buzbee67bf8852011-08-17 17:51:35 -0700279 } else {
280 RegisterInfo* FPRegs = cUnit->regPool->FPRegs;
281 for (int i = 0; i < cUnit->regPool->numFPRegs; i++) {
282 if (!FPRegs[i].isTemp && !FPRegs[i].inUse &&
283 ((FPRegs[i].reg & 0x1) == 0x0) &&
284 !FPRegs[i+1].isTemp && !FPRegs[i+1].inUse &&
285 ((FPRegs[i+1].reg & 0x1) == 0x1) &&
286 (FPRegs[i].reg + 1) == FPRegs[i+1].reg) {
287 res = FPRegs[i].reg;
288 FPRegs[i].inUse = true;
buzbeebbaf8942011-10-02 13:08:29 -0700289 markPreservedSingle(cUnit, sReg, res);
buzbee67bf8852011-08-17 17:51:35 -0700290 FPRegs[i+1].inUse = true;
buzbeebbaf8942011-10-02 13:08:29 -0700291 DCHECK_EQ(res + 1, FPRegs[i+1].reg);
292 markPreservedSingle(cUnit, sReg+1, res+1);
buzbee67bf8852011-08-17 17:51:35 -0700293 break;
294 }
295 }
296 }
297 if (res != -1) {
buzbee67bc2362011-10-11 18:08:40 -0700298 cUnit->promotionMap[sReg].fpLocation = kLocPhysReg;
299 cUnit->promotionMap[sReg].fpReg = res;
300 cUnit->promotionMap[sReg+1].fpLocation = kLocPhysReg;
301 cUnit->promotionMap[sReg+1].fpReg = res + 1;
buzbee67bf8852011-08-17 17:51:35 -0700302 }
303 return res;
304}
305
306
307/*
308 * Reserve a callee-save fp register. If this register can be used
309 * as the first of a double, attempt to allocate an even pair of fp
310 * single regs (but if can't still attempt to allocate a single, preferring
311 * first to allocate an odd register.
312 */
313extern int oatAllocPreservedFPReg(CompilationUnit* cUnit, int sReg,
314 bool doubleStart)
315{
316 int res = -1;
317 if (doubleStart) {
318 res = allocPreservedDouble(cUnit, sReg);
buzbee67bf8852011-08-17 17:51:35 -0700319 }
320 if (res == -1) {
321 res = allocPreservedSingle(cUnit, sReg, false /* try odd # */);
322 }
323 if (res == -1)
324 res = allocPreservedSingle(cUnit, sReg, true /* try even # */);
325 return res;
326}
327
buzbeeed3e9302011-09-23 17:34:19 -0700328STATIC int allocTempBody(CompilationUnit* cUnit, RegisterInfo* p, int numRegs,
buzbee67bf8852011-08-17 17:51:35 -0700329 int* nextTemp, bool required)
330{
331 int i;
332 int next = *nextTemp;
333 for (i=0; i< numRegs; i++) {
334 if (next >= numRegs)
335 next = 0;
336 if (p[next].isTemp && !p[next].inUse && !p[next].live) {
337 oatClobber(cUnit, p[next].reg);
338 p[next].inUse = true;
339 p[next].pair = false;
340 *nextTemp = next + 1;
341 return p[next].reg;
342 }
343 next++;
344 }
345 next = *nextTemp;
346 for (i=0; i< numRegs; i++) {
347 if (next >= numRegs)
348 next = 0;
349 if (p[next].isTemp && !p[next].inUse) {
350 oatClobber(cUnit, p[next].reg);
351 p[next].inUse = true;
352 p[next].pair = false;
353 *nextTemp = next + 1;
354 return p[next].reg;
355 }
356 next++;
357 }
358 if (required) {
buzbee6181f792011-09-29 11:14:04 -0700359 oatCodegenDump(cUnit);
buzbee67bf8852011-08-17 17:51:35 -0700360 dumpRegPool(cUnit->regPool->coreRegs,
361 cUnit->regPool->numCoreRegs);
362 LOG(FATAL) << "No free temp registers";
363 }
364 return -1; // No register available
365}
366
367//REDO: too many assumptions.
368extern int oatAllocTempDouble(CompilationUnit* cUnit)
369{
370 RegisterInfo* p = cUnit->regPool->FPRegs;
371 int numRegs = cUnit->regPool->numFPRegs;
buzbeea50638b2011-11-02 15:15:06 -0700372 /* Start looking at an even reg */
373 int next = cUnit->regPool->nextFPReg & ~0x1;
buzbee67bf8852011-08-17 17:51:35 -0700374
buzbeea50638b2011-11-02 15:15:06 -0700375 // First try to avoid allocating live registers
376 for (int i=0; i < numRegs; i+=2) {
buzbee67bf8852011-08-17 17:51:35 -0700377 if (next >= numRegs)
378 next = 0;
379 if ((p[next].isTemp && !p[next].inUse && !p[next].live) &&
380 (p[next+1].isTemp && !p[next+1].inUse && !p[next+1].live)) {
381 oatClobber(cUnit, p[next].reg);
382 oatClobber(cUnit, p[next+1].reg);
383 p[next].inUse = true;
384 p[next+1].inUse = true;
buzbeeed3e9302011-09-23 17:34:19 -0700385 DCHECK_EQ((p[next].reg+1), p[next+1].reg);
386 DCHECK_EQ((p[next].reg & 0x1), 0);
buzbeea50638b2011-11-02 15:15:06 -0700387 cUnit->regPool->nextFPReg = next + 2;
388 if (cUnit->regPool->nextFPReg >= numRegs) {
389 cUnit->regPool->nextFPReg = 0;
390 }
buzbee67bf8852011-08-17 17:51:35 -0700391 return p[next].reg;
392 }
393 next += 2;
394 }
buzbeea50638b2011-11-02 15:15:06 -0700395 next = cUnit->regPool->nextFPReg & ~0x1;
396
397 // No choice - find a pair and kill it.
398 for (int i=0; i < numRegs; i+=2) {
buzbee67bf8852011-08-17 17:51:35 -0700399 if (next >= numRegs)
400 next = 0;
401 if (p[next].isTemp && !p[next].inUse && p[next+1].isTemp &&
402 !p[next+1].inUse) {
403 oatClobber(cUnit, p[next].reg);
404 oatClobber(cUnit, p[next+1].reg);
405 p[next].inUse = true;
406 p[next+1].inUse = true;
buzbeeed3e9302011-09-23 17:34:19 -0700407 DCHECK_EQ((p[next].reg+1), p[next+1].reg);
408 DCHECK_EQ((p[next].reg & 0x1), 0);
buzbeea50638b2011-11-02 15:15:06 -0700409 cUnit->regPool->nextFPReg = next + 2;
410 if (cUnit->regPool->nextFPReg >= numRegs) {
411 cUnit->regPool->nextFPReg = 0;
412 }
buzbee67bf8852011-08-17 17:51:35 -0700413 return p[next].reg;
414 }
415 next += 2;
416 }
buzbee6181f792011-09-29 11:14:04 -0700417 LOG(FATAL) << "No free temp registers (pair)";
buzbee67bf8852011-08-17 17:51:35 -0700418 return -1;
419}
420
421/* Return a temp if one is available, -1 otherwise */
422extern int oatAllocFreeTemp(CompilationUnit* cUnit)
423{
424 return allocTempBody(cUnit, cUnit->regPool->coreRegs,
425 cUnit->regPool->numCoreRegs,
426 &cUnit->regPool->nextCoreReg, true);
427}
428
429extern int oatAllocTemp(CompilationUnit* cUnit)
430{
431 return allocTempBody(cUnit, cUnit->regPool->coreRegs,
432 cUnit->regPool->numCoreRegs,
433 &cUnit->regPool->nextCoreReg, true);
434}
435
436extern int oatAllocTempFloat(CompilationUnit* cUnit)
437{
438 return allocTempBody(cUnit, cUnit->regPool->FPRegs,
439 cUnit->regPool->numFPRegs,
440 &cUnit->regPool->nextFPReg, true);
441}
442
buzbeeed3e9302011-09-23 17:34:19 -0700443STATIC RegisterInfo* allocLiveBody(RegisterInfo* p, int numRegs, int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700444{
445 int i;
446 if (sReg == -1)
447 return NULL;
448 for (i=0; i < numRegs; i++) {
449 if (p[i].live && (p[i].sReg == sReg)) {
450 if (p[i].isTemp)
451 p[i].inUse = true;
452 return &p[i];
453 }
454 }
455 return NULL;
456}
457
buzbeeed3e9302011-09-23 17:34:19 -0700458STATIC RegisterInfo* allocLive(CompilationUnit* cUnit, int sReg,
buzbee67bf8852011-08-17 17:51:35 -0700459 int regClass)
460{
461 RegisterInfo* res = NULL;
462 switch(regClass) {
463 case kAnyReg:
464 res = allocLiveBody(cUnit->regPool->FPRegs,
465 cUnit->regPool->numFPRegs, sReg);
466 if (res)
467 break;
468 /* Intentional fallthrough */
469 case kCoreReg:
470 res = allocLiveBody(cUnit->regPool->coreRegs,
471 cUnit->regPool->numCoreRegs, sReg);
472 break;
473 case kFPReg:
474 res = allocLiveBody(cUnit->regPool->FPRegs,
475 cUnit->regPool->numFPRegs, sReg);
476 break;
477 default:
478 LOG(FATAL) << "Invalid register type";
479 }
480 return res;
481}
482
483extern void oatFreeTemp(CompilationUnit* cUnit, int reg)
484{
485 RegisterInfo* p = cUnit->regPool->coreRegs;
486 int numRegs = cUnit->regPool->numCoreRegs;
487 int i;
488 for (i=0; i< numRegs; i++) {
489 if (p[i].reg == reg) {
490 if (p[i].isTemp) {
491 p[i].inUse = false;
492 }
493 p[i].pair = false;
494 return;
495 }
496 }
497 p = cUnit->regPool->FPRegs;
498 numRegs = cUnit->regPool->numFPRegs;
499 for (i=0; i< numRegs; i++) {
500 if (p[i].reg == reg) {
501 if (p[i].isTemp) {
502 p[i].inUse = false;
503 }
504 p[i].pair = false;
505 return;
506 }
507 }
508 LOG(FATAL) << "Tried to free a non-existant temp: r" << reg;
509}
510
511extern RegisterInfo* oatIsLive(CompilationUnit* cUnit, int reg)
512{
513 RegisterInfo* p = cUnit->regPool->coreRegs;
514 int numRegs = cUnit->regPool->numCoreRegs;
515 int i;
516 for (i=0; i< numRegs; i++) {
517 if (p[i].reg == reg) {
518 return p[i].live ? &p[i] : NULL;
519 }
520 }
521 p = cUnit->regPool->FPRegs;
522 numRegs = cUnit->regPool->numFPRegs;
523 for (i=0; i< numRegs; i++) {
524 if (p[i].reg == reg) {
525 return p[i].live ? &p[i] : NULL;
526 }
527 }
528 return NULL;
529}
530
531extern RegisterInfo* oatIsTemp(CompilationUnit* cUnit, int reg)
532{
buzbee68253262011-10-07 14:02:25 -0700533 RegisterInfo* p = oatGetRegInfo(cUnit, reg);
buzbee67bf8852011-08-17 17:51:35 -0700534 return (p->isTemp) ? p : NULL;
535}
536
buzbeeb29e4d12011-09-26 15:05:48 -0700537extern RegisterInfo* oatIsPromoted(CompilationUnit* cUnit, int reg)
538{
buzbee68253262011-10-07 14:02:25 -0700539 RegisterInfo* p = oatGetRegInfo(cUnit, reg);
buzbeeb29e4d12011-09-26 15:05:48 -0700540 return (p->isTemp) ? NULL : p;
541}
542
buzbee67bf8852011-08-17 17:51:35 -0700543extern bool oatIsDirty(CompilationUnit* cUnit, int reg)
544{
buzbee68253262011-10-07 14:02:25 -0700545 RegisterInfo* p = oatGetRegInfo(cUnit, reg);
buzbee67bf8852011-08-17 17:51:35 -0700546 return p->dirty;
547}
548
549/*
550 * Similar to oatAllocTemp(), but forces the allocation of a specific
551 * register. No check is made to see if the register was previously
552 * allocated. Use with caution.
553 */
554extern void oatLockTemp(CompilationUnit* cUnit, int reg)
555{
556 RegisterInfo* p = cUnit->regPool->coreRegs;
557 int numRegs = cUnit->regPool->numCoreRegs;
558 int i;
559 for (i=0; i< numRegs; i++) {
560 if (p[i].reg == reg) {
buzbeeed3e9302011-09-23 17:34:19 -0700561 DCHECK(p[i].isTemp);
buzbee67bf8852011-08-17 17:51:35 -0700562 p[i].inUse = true;
563 p[i].live = false;
564 return;
565 }
566 }
567 p = cUnit->regPool->FPRegs;
568 numRegs = cUnit->regPool->numFPRegs;
569 for (i=0; i< numRegs; i++) {
570 if (p[i].reg == reg) {
buzbeeed3e9302011-09-23 17:34:19 -0700571 DCHECK(p[i].isTemp);
buzbee67bf8852011-08-17 17:51:35 -0700572 p[i].inUse = true;
573 p[i].live = false;
574 return;
575 }
576 }
577 LOG(FATAL) << "Tried to lock a non-existant temp: r" << reg;
578}
579
580extern void oatResetDef(CompilationUnit* cUnit, int reg)
581{
buzbee68253262011-10-07 14:02:25 -0700582 RegisterInfo* p = oatGetRegInfo(cUnit, reg);
buzbee67bf8852011-08-17 17:51:35 -0700583 p->defStart = NULL;
584 p->defEnd = NULL;
585}
586
buzbeeed3e9302011-09-23 17:34:19 -0700587STATIC void nullifyRange(CompilationUnit* cUnit, LIR *start, LIR *finish,
buzbee67bf8852011-08-17 17:51:35 -0700588 int sReg1, int sReg2)
589{
590 if (start && finish) {
591 LIR *p;
buzbeeed3e9302011-09-23 17:34:19 -0700592 DCHECK_EQ(sReg1, sReg2);
buzbee67bf8852011-08-17 17:51:35 -0700593 for (p = start; ;p = p->next) {
594 ((ArmLIR *)p)->flags.isNop = true;
buzbee6181f792011-09-29 11:14:04 -0700595 ((ArmLIR *)p)->flags.squashed = true;
buzbee67bf8852011-08-17 17:51:35 -0700596 if (p == finish)
597 break;
598 }
599 }
600}
601
602/*
603 * Mark the beginning and end LIR of a def sequence. Note that
604 * on entry start points to the LIR prior to the beginning of the
605 * sequence.
606 */
607extern void oatMarkDef(CompilationUnit* cUnit, RegLocation rl,
608 LIR *start, LIR *finish)
609{
buzbeeed3e9302011-09-23 17:34:19 -0700610 DCHECK(!rl.wide);
611 DCHECK(start && start->next);
612 DCHECK(finish);
buzbee68253262011-10-07 14:02:25 -0700613 RegisterInfo* p = oatGetRegInfo(cUnit, rl.lowReg);
buzbee67bf8852011-08-17 17:51:35 -0700614 p->defStart = start->next;
615 p->defEnd = finish;
616}
617
618/*
619 * Mark the beginning and end LIR of a def sequence. Note that
620 * on entry start points to the LIR prior to the beginning of the
621 * sequence.
622 */
623extern void oatMarkDefWide(CompilationUnit* cUnit, RegLocation rl,
624 LIR *start, LIR *finish)
625{
buzbeeed3e9302011-09-23 17:34:19 -0700626 DCHECK(rl.wide);
627 DCHECK(start && start->next);
628 DCHECK(finish);
buzbee68253262011-10-07 14:02:25 -0700629 RegisterInfo* p = oatGetRegInfo(cUnit, rl.lowReg);
buzbee67bf8852011-08-17 17:51:35 -0700630 oatResetDef(cUnit, rl.highReg); // Only track low of pair
631 p->defStart = start->next;
632 p->defEnd = finish;
633}
634
635extern RegLocation oatWideToNarrow(CompilationUnit* cUnit,
636 RegLocation rl)
637{
buzbeeed3e9302011-09-23 17:34:19 -0700638 DCHECK(rl.wide);
buzbee67bf8852011-08-17 17:51:35 -0700639 if (rl.location == kLocPhysReg) {
buzbee68253262011-10-07 14:02:25 -0700640 RegisterInfo* infoLo = oatGetRegInfo(cUnit, rl.lowReg);
641 RegisterInfo* infoHi = oatGetRegInfo(cUnit, rl.highReg);
buzbee0c7f26d2011-09-07 12:28:51 -0700642 if (infoLo->isTemp) {
643 infoLo->pair = false;
644 infoLo->defStart = NULL;
645 infoLo->defEnd = NULL;
buzbee67bf8852011-08-17 17:51:35 -0700646 }
buzbee0c7f26d2011-09-07 12:28:51 -0700647 if (infoHi->isTemp) {
648 infoHi->pair = false;
649 infoHi->defStart = NULL;
650 infoHi->defEnd = NULL;
buzbee67bf8852011-08-17 17:51:35 -0700651 }
buzbee67bf8852011-08-17 17:51:35 -0700652 }
653 rl.wide = false;
654 return rl;
655}
656
657extern void oatResetDefLoc(CompilationUnit* cUnit, RegLocation rl)
658{
buzbeeed3e9302011-09-23 17:34:19 -0700659 DCHECK(!rl.wide);
buzbee6181f792011-09-29 11:14:04 -0700660 RegisterInfo* p = oatIsTemp(cUnit, rl.lowReg);
661 if (p && !(cUnit->disableOpt & (1 << kSuppressLoads))) {
buzbeeed3e9302011-09-23 17:34:19 -0700662 DCHECK(!p->pair);
buzbee67bf8852011-08-17 17:51:35 -0700663 nullifyRange(cUnit, p->defStart, p->defEnd,
664 p->sReg, rl.sRegLow);
665 }
666 oatResetDef(cUnit, rl.lowReg);
667}
668
669extern void oatResetDefLocWide(CompilationUnit* cUnit, RegLocation rl)
670{
buzbeeed3e9302011-09-23 17:34:19 -0700671 DCHECK(rl.wide);
buzbee6181f792011-09-29 11:14:04 -0700672 RegisterInfo* pLow = oatIsTemp(cUnit, rl.lowReg);
673 RegisterInfo* pHigh = oatIsTemp(cUnit, rl.highReg);
674 if (pLow && !(cUnit->disableOpt & (1 << kSuppressLoads))) {
675 DCHECK(pLow->pair);
676 nullifyRange(cUnit, pLow->defStart, pLow->defEnd,
677 pLow->sReg, rl.sRegLow);
678 }
679 if (pHigh && !(cUnit->disableOpt & (1 << kSuppressLoads))) {
680 DCHECK(pHigh->pair);
buzbee67bf8852011-08-17 17:51:35 -0700681 }
682 oatResetDef(cUnit, rl.lowReg);
683 oatResetDef(cUnit, rl.highReg);
684}
685
686extern void oatResetDefTracking(CompilationUnit* cUnit)
687{
688 int i;
689 for (i=0; i< cUnit->regPool->numCoreRegs; i++) {
690 oatResetDef(cUnit, cUnit->regPool->coreRegs[i].reg);
691 }
692 for (i=0; i< cUnit->regPool->numFPRegs; i++) {
693 oatResetDef(cUnit, cUnit->regPool->FPRegs[i].reg);
694 }
695}
696
697extern void oatClobberAllRegs(CompilationUnit* cUnit)
698{
699 int i;
700 for (i=0; i< cUnit->regPool->numCoreRegs; i++) {
701 oatClobber(cUnit, cUnit->regPool->coreRegs[i].reg);
702 }
703 for (i=0; i< cUnit->regPool->numFPRegs; i++) {
704 oatClobber(cUnit, cUnit->regPool->FPRegs[i].reg);
705 }
706}
707
708/* To be used when explicitly managing register use */
buzbee2e748f32011-08-29 21:02:19 -0700709extern void oatLockCallTemps(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700710{
buzbee2e748f32011-08-29 21:02:19 -0700711 //TODO: Arm specific - move to target dependent code
712 oatLockTemp(cUnit, r0);
713 oatLockTemp(cUnit, r1);
714 oatLockTemp(cUnit, r2);
715 oatLockTemp(cUnit, r3);
buzbee67bf8852011-08-17 17:51:35 -0700716}
717
buzbee0d966cf2011-09-08 17:34:58 -0700718/* To be used when explicitly managing register use */
719extern void oatFreeCallTemps(CompilationUnit* cUnit)
720{
721 //TODO: Arm specific - move to target dependent code
722 oatFreeTemp(cUnit, r0);
723 oatFreeTemp(cUnit, r1);
724 oatFreeTemp(cUnit, r2);
725 oatFreeTemp(cUnit, r3);
726}
727
buzbee67bf8852011-08-17 17:51:35 -0700728// Make sure nothing is live and dirty
buzbeeed3e9302011-09-23 17:34:19 -0700729STATIC void flushAllRegsBody(CompilationUnit* cUnit, RegisterInfo* info,
buzbee67bf8852011-08-17 17:51:35 -0700730 int numRegs)
731{
732 int i;
733 for (i=0; i < numRegs; i++) {
734 if (info[i].live && info[i].dirty) {
735 if (info[i].pair) {
736 oatFlushRegWide(cUnit, info[i].reg, info[i].partner);
737 } else {
738 oatFlushReg(cUnit, info[i].reg);
739 }
740 }
741 }
742}
743
744extern void oatFlushAllRegs(CompilationUnit* cUnit)
745{
746 flushAllRegsBody(cUnit, cUnit->regPool->coreRegs,
747 cUnit->regPool->numCoreRegs);
748 flushAllRegsBody(cUnit, cUnit->regPool->FPRegs,
749 cUnit->regPool->numFPRegs);
750 oatClobberAllRegs(cUnit);
751}
752
753
754//TUNING: rewrite all of this reg stuff. Probably use an attribute table
buzbeeed3e9302011-09-23 17:34:19 -0700755STATIC bool regClassMatches(int regClass, int reg)
buzbee67bf8852011-08-17 17:51:35 -0700756{
757 if (regClass == kAnyReg) {
758 return true;
759 } else if (regClass == kCoreReg) {
760 return !FPREG(reg);
761 } else {
762 return FPREG(reg);
763 }
764}
765
766extern void oatMarkLive(CompilationUnit* cUnit, int reg, int sReg)
767{
buzbee68253262011-10-07 14:02:25 -0700768 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
buzbee67bf8852011-08-17 17:51:35 -0700769 if ((info->reg == reg) && (info->sReg == sReg) && info->live) {
770 return; /* already live */
771 } else if (sReg != INVALID_SREG) {
772 oatClobberSReg(cUnit, sReg);
773 if (info->isTemp) {
774 info->live = true;
775 }
776 } else {
777 /* Can't be live if no associated sReg */
buzbeeed3e9302011-09-23 17:34:19 -0700778 DCHECK(info->isTemp);
buzbee67bf8852011-08-17 17:51:35 -0700779 info->live = false;
780 }
781 info->sReg = sReg;
782}
783
784extern void oatMarkTemp(CompilationUnit* cUnit, int reg)
785{
buzbee68253262011-10-07 14:02:25 -0700786 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
buzbee67bf8852011-08-17 17:51:35 -0700787 info->isTemp = true;
788}
789
buzbee9e0f9b02011-08-24 15:32:46 -0700790extern void oatUnmarkTemp(CompilationUnit* cUnit, int reg)
791{
buzbee68253262011-10-07 14:02:25 -0700792 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
buzbee9e0f9b02011-08-24 15:32:46 -0700793 info->isTemp = false;
794}
795
buzbee67bf8852011-08-17 17:51:35 -0700796extern void oatMarkPair(CompilationUnit* cUnit, int lowReg, int highReg)
797{
buzbee68253262011-10-07 14:02:25 -0700798 RegisterInfo* infoLo = oatGetRegInfo(cUnit, lowReg);
799 RegisterInfo* infoHi = oatGetRegInfo(cUnit, highReg);
buzbee67bf8852011-08-17 17:51:35 -0700800 infoLo->pair = infoHi->pair = true;
801 infoLo->partner = highReg;
802 infoHi->partner = lowReg;
803}
804
805extern void oatMarkClean(CompilationUnit* cUnit, RegLocation loc)
806{
buzbee68253262011-10-07 14:02:25 -0700807 RegisterInfo* info = oatGetRegInfo(cUnit, loc.lowReg);
buzbee67bf8852011-08-17 17:51:35 -0700808 info->dirty = false;
809 if (loc.wide) {
buzbee68253262011-10-07 14:02:25 -0700810 info = oatGetRegInfo(cUnit, loc.highReg);
buzbee67bf8852011-08-17 17:51:35 -0700811 info->dirty = false;
812 }
813}
814
815extern void oatMarkDirty(CompilationUnit* cUnit, RegLocation loc)
816{
817 if (loc.home) {
818 // If already home, can't be dirty
819 return;
820 }
buzbee68253262011-10-07 14:02:25 -0700821 RegisterInfo* info = oatGetRegInfo(cUnit, loc.lowReg);
buzbee67bf8852011-08-17 17:51:35 -0700822 info->dirty = true;
823 if (loc.wide) {
buzbee68253262011-10-07 14:02:25 -0700824 info = oatGetRegInfo(cUnit, loc.highReg);
buzbee67bf8852011-08-17 17:51:35 -0700825 info->dirty = true;
826 }
827}
828
829extern void oatMarkInUse(CompilationUnit* cUnit, int reg)
830{
buzbee68253262011-10-07 14:02:25 -0700831 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
buzbee67bf8852011-08-17 17:51:35 -0700832 info->inUse = true;
833}
834
buzbeeed3e9302011-09-23 17:34:19 -0700835STATIC void copyRegInfo(CompilationUnit* cUnit, int newReg, int oldReg)
buzbee67bf8852011-08-17 17:51:35 -0700836{
buzbee68253262011-10-07 14:02:25 -0700837 RegisterInfo* newInfo = oatGetRegInfo(cUnit, newReg);
838 RegisterInfo* oldInfo = oatGetRegInfo(cUnit, oldReg);
buzbeeec5adf32011-09-11 15:25:43 -0700839 // Target temp status must not change
840 bool isTemp = newInfo->isTemp;
buzbee67bf8852011-08-17 17:51:35 -0700841 *newInfo = *oldInfo;
buzbeeec5adf32011-09-11 15:25:43 -0700842 // Restore target's temp status
843 newInfo->isTemp = isTemp;
buzbee67bf8852011-08-17 17:51:35 -0700844 newInfo->reg = newReg;
845}
846
847/*
848 * Return an updated location record with current in-register status.
849 * If the value lives in live temps, reflect that fact. No code
buzbeeb29e4d12011-09-26 15:05:48 -0700850 * is generated. If the live value is part of an older pair,
buzbee67bf8852011-08-17 17:51:35 -0700851 * clobber both low and high.
852 * TUNING: clobbering both is a bit heavy-handed, but the alternative
853 * is a bit complex when dealing with FP regs. Examine code to see
854 * if it's worthwhile trying to be more clever here.
855 */
856
857extern RegLocation oatUpdateLoc(CompilationUnit* cUnit, RegLocation loc)
858{
buzbeeed3e9302011-09-23 17:34:19 -0700859 DCHECK(!loc.wide);
buzbee6181f792011-09-29 11:14:04 -0700860 DCHECK(oatCheckCorePoolSanity(cUnit));
buzbee67bf8852011-08-17 17:51:35 -0700861 if (loc.location == kLocDalvikFrame) {
862 RegisterInfo* infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
863 if (infoLo) {
864 if (infoLo->pair) {
865 oatClobber(cUnit, infoLo->reg);
866 oatClobber(cUnit, infoLo->partner);
buzbee58f92742011-10-01 11:22:17 -0700867 oatFreeTemp(cUnit, infoLo->reg);
buzbee67bf8852011-08-17 17:51:35 -0700868 } else {
869 loc.lowReg = infoLo->reg;
870 loc.location = kLocPhysReg;
871 }
872 }
873 }
874
875 return loc;
876}
877
buzbee6181f792011-09-29 11:14:04 -0700878bool oatCheckCorePoolSanity(CompilationUnit* cUnit)
879{
880 for (static int i = 0; i < cUnit->regPool->numCoreRegs; i++) {
881 if (cUnit->regPool->coreRegs[i].pair) {
882 static int myReg = cUnit->regPool->coreRegs[i].reg;
883 static int mySreg = cUnit->regPool->coreRegs[i].sReg;
884 static int partnerReg = cUnit->regPool->coreRegs[i].partner;
buzbee68253262011-10-07 14:02:25 -0700885 static RegisterInfo* partner = oatGetRegInfo(cUnit, partnerReg);
buzbee6181f792011-09-29 11:14:04 -0700886 DCHECK(partner != NULL);
887 DCHECK(partner->pair);
888 DCHECK_EQ(myReg, partner->partner);
889 static int partnerSreg = partner->sReg;
890 if (mySreg == INVALID_SREG) {
891 DCHECK_EQ(partnerSreg, INVALID_SREG);
892 } else {
893 int diff = mySreg - partnerSreg;
894 DCHECK((diff == -1) || (diff == 1));
895 }
896 }
897 if (!cUnit->regPool->coreRegs[i].live) {
898 DCHECK(cUnit->regPool->coreRegs[i].defStart == NULL);
899 DCHECK(cUnit->regPool->coreRegs[i].defEnd == NULL);
900 }
901 }
902 return true;
903}
904
buzbee67bf8852011-08-17 17:51:35 -0700905/* see comments for updateLoc */
906extern RegLocation oatUpdateLocWide(CompilationUnit* cUnit,
907 RegLocation loc)
908{
buzbeeed3e9302011-09-23 17:34:19 -0700909 DCHECK(loc.wide);
buzbee6181f792011-09-29 11:14:04 -0700910 DCHECK(oatCheckCorePoolSanity(cUnit));
buzbee67bf8852011-08-17 17:51:35 -0700911 if (loc.location == kLocDalvikFrame) {
912 // Are the dalvik regs already live in physical registers?
913 RegisterInfo* infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
914 RegisterInfo* infoHi = allocLive(cUnit,
915 oatSRegHi(loc.sRegLow), kAnyReg);
916 bool match = true;
917 match = match && (infoLo != NULL);
918 match = match && (infoHi != NULL);
919 // Are they both core or both FP?
920 match = match && (FPREG(infoLo->reg) == FPREG(infoHi->reg));
921 // If a pair of floating point singles, are they properly aligned?
922 if (match && FPREG(infoLo->reg)) {
923 match &= ((infoLo->reg & 0x1) == 0);
924 match &= ((infoHi->reg - infoLo->reg) == 1);
925 }
926 // If previously used as a pair, it is the same pair?
927 if (match && (infoLo->pair || infoHi->pair)) {
928 match = (infoLo->pair == infoHi->pair);
929 match &= ((infoLo->reg == infoHi->partner) &&
930 (infoHi->reg == infoLo->partner));
931 }
932 if (match) {
933 // Can reuse - update the register usage info
934 loc.lowReg = infoLo->reg;
935 loc.highReg = infoHi->reg;
936 loc.location = kLocPhysReg;
937 oatMarkPair(cUnit, loc.lowReg, loc.highReg);
buzbeeed3e9302011-09-23 17:34:19 -0700938 DCHECK(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
buzbee67bf8852011-08-17 17:51:35 -0700939 return loc;
940 }
buzbee58f92742011-10-01 11:22:17 -0700941 // Can't easily reuse - clobber and free any overlaps
buzbee67bf8852011-08-17 17:51:35 -0700942 if (infoLo) {
943 oatClobber(cUnit, infoLo->reg);
buzbee58f92742011-10-01 11:22:17 -0700944 oatFreeTemp(cUnit, infoLo->reg);
buzbee67bf8852011-08-17 17:51:35 -0700945 if (infoLo->pair)
946 oatClobber(cUnit, infoLo->partner);
947 }
948 if (infoHi) {
949 oatClobber(cUnit, infoHi->reg);
buzbee58f92742011-10-01 11:22:17 -0700950 oatFreeTemp(cUnit, infoHi->reg);
buzbee67bf8852011-08-17 17:51:35 -0700951 if (infoHi->pair)
952 oatClobber(cUnit, infoHi->partner);
953 }
954 }
955 return loc;
956}
957
buzbeeed3e9302011-09-23 17:34:19 -0700958
959/* For use in cases we don't know (or care) width */
960extern RegLocation oatUpdateRawLoc(CompilationUnit* cUnit,
961 RegLocation loc)
962{
963 if (loc.wide)
964 return oatUpdateLocWide(cUnit, loc);
965 else
966 return oatUpdateLoc(cUnit, loc);
967}
968
969STATIC RegLocation evalLocWide(CompilationUnit* cUnit, RegLocation loc,
buzbee67bf8852011-08-17 17:51:35 -0700970 int regClass, bool update)
971{
buzbeeed3e9302011-09-23 17:34:19 -0700972 DCHECK(loc.wide);
buzbee67bf8852011-08-17 17:51:35 -0700973 int newRegs;
974 int lowReg;
975 int highReg;
976
977 loc = oatUpdateLocWide(cUnit, loc);
978
979 /* If already in registers, we can assume proper form. Right reg class? */
980 if (loc.location == kLocPhysReg) {
buzbeeed3e9302011-09-23 17:34:19 -0700981 DCHECK_EQ(FPREG(loc.lowReg), FPREG(loc.highReg));
982 DCHECK(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
buzbee67bf8852011-08-17 17:51:35 -0700983 if (!regClassMatches(regClass, loc.lowReg)) {
984 /* Wrong register class. Reallocate and copy */
985 newRegs = oatAllocTypedTempPair(cUnit, loc.fp, regClass);
986 lowReg = newRegs & 0xff;
987 highReg = (newRegs >> 8) & 0xff;
988 oatRegCopyWide(cUnit, lowReg, highReg, loc.lowReg,
989 loc.highReg);
990 copyRegInfo(cUnit, lowReg, loc.lowReg);
991 copyRegInfo(cUnit, highReg, loc.highReg);
992 oatClobber(cUnit, loc.lowReg);
993 oatClobber(cUnit, loc.highReg);
994 loc.lowReg = lowReg;
995 loc.highReg = highReg;
996 oatMarkPair(cUnit, loc.lowReg, loc.highReg);
buzbeeed3e9302011-09-23 17:34:19 -0700997 DCHECK(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
buzbee67bf8852011-08-17 17:51:35 -0700998 }
999 return loc;
1000 }
1001
buzbeeed3e9302011-09-23 17:34:19 -07001002 DCHECK_NE(loc.sRegLow, INVALID_SREG);
1003 DCHECK_NE(oatSRegHi(loc.sRegLow), INVALID_SREG);
buzbee67bf8852011-08-17 17:51:35 -07001004
1005 newRegs = oatAllocTypedTempPair(cUnit, loc.fp, regClass);
1006 loc.lowReg = newRegs & 0xff;
1007 loc.highReg = (newRegs >> 8) & 0xff;
1008
1009 oatMarkPair(cUnit, loc.lowReg, loc.highReg);
1010 if (update) {
1011 loc.location = kLocPhysReg;
1012 oatMarkLive(cUnit, loc.lowReg, loc.sRegLow);
1013 oatMarkLive(cUnit, loc.highReg, oatSRegHi(loc.sRegLow));
1014 }
buzbeeed3e9302011-09-23 17:34:19 -07001015 DCHECK(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
buzbee67bf8852011-08-17 17:51:35 -07001016 return loc;
1017}
1018
1019extern RegLocation oatEvalLoc(CompilationUnit* cUnit, RegLocation loc,
1020 int regClass, bool update)
1021{
1022 int newReg;
1023
1024 if (loc.wide)
1025 return evalLocWide(cUnit, loc, regClass, update);
1026
1027 loc = oatUpdateLoc(cUnit, loc);
1028
1029 if (loc.location == kLocPhysReg) {
1030 if (!regClassMatches(regClass, loc.lowReg)) {
1031 /* Wrong register class. Realloc, copy and transfer ownership */
1032 newReg = oatAllocTypedTemp(cUnit, loc.fp, regClass);
1033 oatRegCopy(cUnit, newReg, loc.lowReg);
1034 copyRegInfo(cUnit, newReg, loc.lowReg);
1035 oatClobber(cUnit, loc.lowReg);
1036 loc.lowReg = newReg;
1037 }
1038 return loc;
1039 }
1040
buzbeeed3e9302011-09-23 17:34:19 -07001041 DCHECK_NE(loc.sRegLow, INVALID_SREG);
buzbee67bf8852011-08-17 17:51:35 -07001042
1043 newReg = oatAllocTypedTemp(cUnit, loc.fp, regClass);
1044 loc.lowReg = newReg;
1045
1046 if (update) {
1047 loc.location = kLocPhysReg;
1048 oatMarkLive(cUnit, loc.lowReg, loc.sRegLow);
1049 }
1050 return loc;
1051}
1052
1053extern RegLocation oatGetDest(CompilationUnit* cUnit, MIR* mir, int num)
1054{
buzbeee9a72f62011-09-04 17:59:07 -07001055 RegLocation res = cUnit->regLocation[mir->ssaRep->defs[num]];
buzbeeed3e9302011-09-23 17:34:19 -07001056 DCHECK(!res.wide);
buzbeee9a72f62011-09-04 17:59:07 -07001057 return res;
buzbee67bf8852011-08-17 17:51:35 -07001058}
1059extern RegLocation oatGetSrc(CompilationUnit* cUnit, MIR* mir, int num)
1060{
buzbeee9a72f62011-09-04 17:59:07 -07001061 RegLocation res = cUnit->regLocation[mir->ssaRep->uses[num]];
buzbeeed3e9302011-09-23 17:34:19 -07001062 DCHECK(!res.wide);
buzbeee9a72f62011-09-04 17:59:07 -07001063 return res;
1064}
1065extern RegLocation oatGetRawSrc(CompilationUnit* cUnit, MIR* mir, int num)
1066{
1067 RegLocation res = cUnit->regLocation[mir->ssaRep->uses[num]];
1068 return res;
buzbee67bf8852011-08-17 17:51:35 -07001069}
1070extern RegLocation oatGetDestWide(CompilationUnit* cUnit, MIR* mir,
1071 int low, int high)
1072{
buzbeee9a72f62011-09-04 17:59:07 -07001073 RegLocation res = cUnit->regLocation[mir->ssaRep->defs[low]];
buzbeeed3e9302011-09-23 17:34:19 -07001074 DCHECK(res.wide);
buzbeee9a72f62011-09-04 17:59:07 -07001075 return res;
buzbee67bf8852011-08-17 17:51:35 -07001076}
1077
1078extern RegLocation oatGetSrcWide(CompilationUnit* cUnit, MIR* mir,
1079 int low, int high)
1080{
buzbeee9a72f62011-09-04 17:59:07 -07001081 RegLocation res = cUnit->regLocation[mir->ssaRep->uses[low]];
buzbeeed3e9302011-09-23 17:34:19 -07001082 DCHECK(res.wide);
buzbeee9a72f62011-09-04 17:59:07 -07001083 return res;
buzbee67bf8852011-08-17 17:51:35 -07001084}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -08001085
1086} // namespace art