blob: 1b0fb90e35ca302cadfcfa39f5b6413cf3ea9bd8 [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;
370 int next = cUnit->regPool->nextFPReg;
371 int i;
372
373 for (i=0; i < numRegs; i+=2) {
374 /* Cleanup - not all targets need aligned regs */
375 if (next & 1)
376 next++;
377 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);
buzbee67bf8852011-08-17 17:51:35 -0700387 cUnit->regPool->nextFPReg += 2;
388 return p[next].reg;
389 }
390 next += 2;
391 }
392 next = cUnit->regPool->nextFPReg;
393 for (i=0; i < numRegs; i+=2) {
394 if (next >= numRegs)
395 next = 0;
396 if (p[next].isTemp && !p[next].inUse && p[next+1].isTemp &&
397 !p[next+1].inUse) {
398 oatClobber(cUnit, p[next].reg);
399 oatClobber(cUnit, p[next+1].reg);
400 p[next].inUse = true;
401 p[next+1].inUse = true;
buzbeeed3e9302011-09-23 17:34:19 -0700402 DCHECK_EQ((p[next].reg+1), p[next+1].reg);
403 DCHECK_EQ((p[next].reg & 0x1), 0);
buzbee67bf8852011-08-17 17:51:35 -0700404 cUnit->regPool->nextFPReg += 2;
405 return p[next].reg;
406 }
407 next += 2;
408 }
buzbee6181f792011-09-29 11:14:04 -0700409 LOG(FATAL) << "No free temp registers (pair)";
buzbee67bf8852011-08-17 17:51:35 -0700410 return -1;
411}
412
413/* Return a temp if one is available, -1 otherwise */
414extern int oatAllocFreeTemp(CompilationUnit* cUnit)
415{
416 return allocTempBody(cUnit, cUnit->regPool->coreRegs,
417 cUnit->regPool->numCoreRegs,
418 &cUnit->regPool->nextCoreReg, true);
419}
420
421extern int oatAllocTemp(CompilationUnit* cUnit)
422{
423 return allocTempBody(cUnit, cUnit->regPool->coreRegs,
424 cUnit->regPool->numCoreRegs,
425 &cUnit->regPool->nextCoreReg, true);
426}
427
428extern int oatAllocTempFloat(CompilationUnit* cUnit)
429{
430 return allocTempBody(cUnit, cUnit->regPool->FPRegs,
431 cUnit->regPool->numFPRegs,
432 &cUnit->regPool->nextFPReg, true);
433}
434
buzbeeed3e9302011-09-23 17:34:19 -0700435STATIC RegisterInfo* allocLiveBody(RegisterInfo* p, int numRegs, int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700436{
437 int i;
438 if (sReg == -1)
439 return NULL;
440 for (i=0; i < numRegs; i++) {
441 if (p[i].live && (p[i].sReg == sReg)) {
442 if (p[i].isTemp)
443 p[i].inUse = true;
444 return &p[i];
445 }
446 }
447 return NULL;
448}
449
buzbeeed3e9302011-09-23 17:34:19 -0700450STATIC RegisterInfo* allocLive(CompilationUnit* cUnit, int sReg,
buzbee67bf8852011-08-17 17:51:35 -0700451 int regClass)
452{
453 RegisterInfo* res = NULL;
454 switch(regClass) {
455 case kAnyReg:
456 res = allocLiveBody(cUnit->regPool->FPRegs,
457 cUnit->regPool->numFPRegs, sReg);
458 if (res)
459 break;
460 /* Intentional fallthrough */
461 case kCoreReg:
462 res = allocLiveBody(cUnit->regPool->coreRegs,
463 cUnit->regPool->numCoreRegs, sReg);
464 break;
465 case kFPReg:
466 res = allocLiveBody(cUnit->regPool->FPRegs,
467 cUnit->regPool->numFPRegs, sReg);
468 break;
469 default:
470 LOG(FATAL) << "Invalid register type";
471 }
472 return res;
473}
474
475extern void oatFreeTemp(CompilationUnit* cUnit, int reg)
476{
477 RegisterInfo* p = cUnit->regPool->coreRegs;
478 int numRegs = cUnit->regPool->numCoreRegs;
479 int i;
480 for (i=0; i< numRegs; i++) {
481 if (p[i].reg == reg) {
482 if (p[i].isTemp) {
483 p[i].inUse = false;
484 }
485 p[i].pair = false;
486 return;
487 }
488 }
489 p = cUnit->regPool->FPRegs;
490 numRegs = cUnit->regPool->numFPRegs;
491 for (i=0; i< numRegs; i++) {
492 if (p[i].reg == reg) {
493 if (p[i].isTemp) {
494 p[i].inUse = false;
495 }
496 p[i].pair = false;
497 return;
498 }
499 }
500 LOG(FATAL) << "Tried to free a non-existant temp: r" << reg;
501}
502
503extern RegisterInfo* oatIsLive(CompilationUnit* cUnit, int reg)
504{
505 RegisterInfo* p = cUnit->regPool->coreRegs;
506 int numRegs = cUnit->regPool->numCoreRegs;
507 int i;
508 for (i=0; i< numRegs; i++) {
509 if (p[i].reg == reg) {
510 return p[i].live ? &p[i] : NULL;
511 }
512 }
513 p = cUnit->regPool->FPRegs;
514 numRegs = cUnit->regPool->numFPRegs;
515 for (i=0; i< numRegs; i++) {
516 if (p[i].reg == reg) {
517 return p[i].live ? &p[i] : NULL;
518 }
519 }
520 return NULL;
521}
522
523extern RegisterInfo* oatIsTemp(CompilationUnit* cUnit, int reg)
524{
buzbee68253262011-10-07 14:02:25 -0700525 RegisterInfo* p = oatGetRegInfo(cUnit, reg);
buzbee67bf8852011-08-17 17:51:35 -0700526 return (p->isTemp) ? p : NULL;
527}
528
buzbeeb29e4d12011-09-26 15:05:48 -0700529extern RegisterInfo* oatIsPromoted(CompilationUnit* cUnit, int reg)
530{
buzbee68253262011-10-07 14:02:25 -0700531 RegisterInfo* p = oatGetRegInfo(cUnit, reg);
buzbeeb29e4d12011-09-26 15:05:48 -0700532 return (p->isTemp) ? NULL : p;
533}
534
buzbee67bf8852011-08-17 17:51:35 -0700535extern bool oatIsDirty(CompilationUnit* cUnit, int reg)
536{
buzbee68253262011-10-07 14:02:25 -0700537 RegisterInfo* p = oatGetRegInfo(cUnit, reg);
buzbee67bf8852011-08-17 17:51:35 -0700538 return p->dirty;
539}
540
541/*
542 * Similar to oatAllocTemp(), but forces the allocation of a specific
543 * register. No check is made to see if the register was previously
544 * allocated. Use with caution.
545 */
546extern void oatLockTemp(CompilationUnit* cUnit, int reg)
547{
548 RegisterInfo* p = cUnit->regPool->coreRegs;
549 int numRegs = cUnit->regPool->numCoreRegs;
550 int i;
551 for (i=0; i< numRegs; i++) {
552 if (p[i].reg == reg) {
buzbeeed3e9302011-09-23 17:34:19 -0700553 DCHECK(p[i].isTemp);
buzbee67bf8852011-08-17 17:51:35 -0700554 p[i].inUse = true;
555 p[i].live = false;
556 return;
557 }
558 }
559 p = cUnit->regPool->FPRegs;
560 numRegs = cUnit->regPool->numFPRegs;
561 for (i=0; i< numRegs; i++) {
562 if (p[i].reg == reg) {
buzbeeed3e9302011-09-23 17:34:19 -0700563 DCHECK(p[i].isTemp);
buzbee67bf8852011-08-17 17:51:35 -0700564 p[i].inUse = true;
565 p[i].live = false;
566 return;
567 }
568 }
569 LOG(FATAL) << "Tried to lock a non-existant temp: r" << reg;
570}
571
572extern void oatResetDef(CompilationUnit* cUnit, int reg)
573{
buzbee68253262011-10-07 14:02:25 -0700574 RegisterInfo* p = oatGetRegInfo(cUnit, reg);
buzbee67bf8852011-08-17 17:51:35 -0700575 p->defStart = NULL;
576 p->defEnd = NULL;
577}
578
buzbeeed3e9302011-09-23 17:34:19 -0700579STATIC void nullifyRange(CompilationUnit* cUnit, LIR *start, LIR *finish,
buzbee67bf8852011-08-17 17:51:35 -0700580 int sReg1, int sReg2)
581{
582 if (start && finish) {
583 LIR *p;
buzbeeed3e9302011-09-23 17:34:19 -0700584 DCHECK_EQ(sReg1, sReg2);
buzbee67bf8852011-08-17 17:51:35 -0700585 for (p = start; ;p = p->next) {
586 ((ArmLIR *)p)->flags.isNop = true;
buzbee6181f792011-09-29 11:14:04 -0700587 ((ArmLIR *)p)->flags.squashed = true;
buzbee67bf8852011-08-17 17:51:35 -0700588 if (p == finish)
589 break;
590 }
591 }
592}
593
594/*
595 * Mark the beginning and end LIR of a def sequence. Note that
596 * on entry start points to the LIR prior to the beginning of the
597 * sequence.
598 */
599extern void oatMarkDef(CompilationUnit* cUnit, RegLocation rl,
600 LIR *start, LIR *finish)
601{
buzbeeed3e9302011-09-23 17:34:19 -0700602 DCHECK(!rl.wide);
603 DCHECK(start && start->next);
604 DCHECK(finish);
buzbee68253262011-10-07 14:02:25 -0700605 RegisterInfo* p = oatGetRegInfo(cUnit, rl.lowReg);
buzbee67bf8852011-08-17 17:51:35 -0700606 p->defStart = start->next;
607 p->defEnd = finish;
608}
609
610/*
611 * Mark the beginning and end LIR of a def sequence. Note that
612 * on entry start points to the LIR prior to the beginning of the
613 * sequence.
614 */
615extern void oatMarkDefWide(CompilationUnit* cUnit, RegLocation rl,
616 LIR *start, LIR *finish)
617{
buzbeeed3e9302011-09-23 17:34:19 -0700618 DCHECK(rl.wide);
619 DCHECK(start && start->next);
620 DCHECK(finish);
buzbee68253262011-10-07 14:02:25 -0700621 RegisterInfo* p = oatGetRegInfo(cUnit, rl.lowReg);
buzbee67bf8852011-08-17 17:51:35 -0700622 oatResetDef(cUnit, rl.highReg); // Only track low of pair
623 p->defStart = start->next;
624 p->defEnd = finish;
625}
626
627extern RegLocation oatWideToNarrow(CompilationUnit* cUnit,
628 RegLocation rl)
629{
buzbeeed3e9302011-09-23 17:34:19 -0700630 DCHECK(rl.wide);
buzbee67bf8852011-08-17 17:51:35 -0700631 if (rl.location == kLocPhysReg) {
buzbee68253262011-10-07 14:02:25 -0700632 RegisterInfo* infoLo = oatGetRegInfo(cUnit, rl.lowReg);
633 RegisterInfo* infoHi = oatGetRegInfo(cUnit, rl.highReg);
buzbee0c7f26d2011-09-07 12:28:51 -0700634 if (infoLo->isTemp) {
635 infoLo->pair = false;
636 infoLo->defStart = NULL;
637 infoLo->defEnd = NULL;
buzbee67bf8852011-08-17 17:51:35 -0700638 }
buzbee0c7f26d2011-09-07 12:28:51 -0700639 if (infoHi->isTemp) {
640 infoHi->pair = false;
641 infoHi->defStart = NULL;
642 infoHi->defEnd = NULL;
buzbee67bf8852011-08-17 17:51:35 -0700643 }
buzbee67bf8852011-08-17 17:51:35 -0700644 }
645 rl.wide = false;
646 return rl;
647}
648
649extern void oatResetDefLoc(CompilationUnit* cUnit, RegLocation rl)
650{
buzbeeed3e9302011-09-23 17:34:19 -0700651 DCHECK(!rl.wide);
buzbee6181f792011-09-29 11:14:04 -0700652 RegisterInfo* p = oatIsTemp(cUnit, rl.lowReg);
653 if (p && !(cUnit->disableOpt & (1 << kSuppressLoads))) {
buzbeeed3e9302011-09-23 17:34:19 -0700654 DCHECK(!p->pair);
buzbee67bf8852011-08-17 17:51:35 -0700655 nullifyRange(cUnit, p->defStart, p->defEnd,
656 p->sReg, rl.sRegLow);
657 }
658 oatResetDef(cUnit, rl.lowReg);
659}
660
661extern void oatResetDefLocWide(CompilationUnit* cUnit, RegLocation rl)
662{
buzbeeed3e9302011-09-23 17:34:19 -0700663 DCHECK(rl.wide);
buzbee6181f792011-09-29 11:14:04 -0700664 RegisterInfo* pLow = oatIsTemp(cUnit, rl.lowReg);
665 RegisterInfo* pHigh = oatIsTemp(cUnit, rl.highReg);
666 if (pLow && !(cUnit->disableOpt & (1 << kSuppressLoads))) {
667 DCHECK(pLow->pair);
668 nullifyRange(cUnit, pLow->defStart, pLow->defEnd,
669 pLow->sReg, rl.sRegLow);
670 }
671 if (pHigh && !(cUnit->disableOpt & (1 << kSuppressLoads))) {
672 DCHECK(pHigh->pair);
buzbee67bf8852011-08-17 17:51:35 -0700673 }
674 oatResetDef(cUnit, rl.lowReg);
675 oatResetDef(cUnit, rl.highReg);
676}
677
678extern void oatResetDefTracking(CompilationUnit* cUnit)
679{
680 int i;
681 for (i=0; i< cUnit->regPool->numCoreRegs; i++) {
682 oatResetDef(cUnit, cUnit->regPool->coreRegs[i].reg);
683 }
684 for (i=0; i< cUnit->regPool->numFPRegs; i++) {
685 oatResetDef(cUnit, cUnit->regPool->FPRegs[i].reg);
686 }
687}
688
689extern void oatClobberAllRegs(CompilationUnit* cUnit)
690{
691 int i;
692 for (i=0; i< cUnit->regPool->numCoreRegs; i++) {
693 oatClobber(cUnit, cUnit->regPool->coreRegs[i].reg);
694 }
695 for (i=0; i< cUnit->regPool->numFPRegs; i++) {
696 oatClobber(cUnit, cUnit->regPool->FPRegs[i].reg);
697 }
698}
699
700/* To be used when explicitly managing register use */
buzbee2e748f32011-08-29 21:02:19 -0700701extern void oatLockCallTemps(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700702{
buzbee2e748f32011-08-29 21:02:19 -0700703 //TODO: Arm specific - move to target dependent code
704 oatLockTemp(cUnit, r0);
705 oatLockTemp(cUnit, r1);
706 oatLockTemp(cUnit, r2);
707 oatLockTemp(cUnit, r3);
buzbee67bf8852011-08-17 17:51:35 -0700708}
709
buzbee0d966cf2011-09-08 17:34:58 -0700710/* To be used when explicitly managing register use */
711extern void oatFreeCallTemps(CompilationUnit* cUnit)
712{
713 //TODO: Arm specific - move to target dependent code
714 oatFreeTemp(cUnit, r0);
715 oatFreeTemp(cUnit, r1);
716 oatFreeTemp(cUnit, r2);
717 oatFreeTemp(cUnit, r3);
718}
719
buzbee67bf8852011-08-17 17:51:35 -0700720// Make sure nothing is live and dirty
buzbeeed3e9302011-09-23 17:34:19 -0700721STATIC void flushAllRegsBody(CompilationUnit* cUnit, RegisterInfo* info,
buzbee67bf8852011-08-17 17:51:35 -0700722 int numRegs)
723{
724 int i;
725 for (i=0; i < numRegs; i++) {
726 if (info[i].live && info[i].dirty) {
727 if (info[i].pair) {
728 oatFlushRegWide(cUnit, info[i].reg, info[i].partner);
729 } else {
730 oatFlushReg(cUnit, info[i].reg);
731 }
732 }
733 }
734}
735
736extern void oatFlushAllRegs(CompilationUnit* cUnit)
737{
738 flushAllRegsBody(cUnit, cUnit->regPool->coreRegs,
739 cUnit->regPool->numCoreRegs);
740 flushAllRegsBody(cUnit, cUnit->regPool->FPRegs,
741 cUnit->regPool->numFPRegs);
742 oatClobberAllRegs(cUnit);
743}
744
745
746//TUNING: rewrite all of this reg stuff. Probably use an attribute table
buzbeeed3e9302011-09-23 17:34:19 -0700747STATIC bool regClassMatches(int regClass, int reg)
buzbee67bf8852011-08-17 17:51:35 -0700748{
749 if (regClass == kAnyReg) {
750 return true;
751 } else if (regClass == kCoreReg) {
752 return !FPREG(reg);
753 } else {
754 return FPREG(reg);
755 }
756}
757
758extern void oatMarkLive(CompilationUnit* cUnit, int reg, int sReg)
759{
buzbee68253262011-10-07 14:02:25 -0700760 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
buzbee67bf8852011-08-17 17:51:35 -0700761 if ((info->reg == reg) && (info->sReg == sReg) && info->live) {
762 return; /* already live */
763 } else if (sReg != INVALID_SREG) {
764 oatClobberSReg(cUnit, sReg);
765 if (info->isTemp) {
766 info->live = true;
767 }
768 } else {
769 /* Can't be live if no associated sReg */
buzbeeed3e9302011-09-23 17:34:19 -0700770 DCHECK(info->isTemp);
buzbee67bf8852011-08-17 17:51:35 -0700771 info->live = false;
772 }
773 info->sReg = sReg;
774}
775
776extern void oatMarkTemp(CompilationUnit* cUnit, int reg)
777{
buzbee68253262011-10-07 14:02:25 -0700778 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
buzbee67bf8852011-08-17 17:51:35 -0700779 info->isTemp = true;
780}
781
buzbee9e0f9b02011-08-24 15:32:46 -0700782extern void oatUnmarkTemp(CompilationUnit* cUnit, int reg)
783{
buzbee68253262011-10-07 14:02:25 -0700784 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
buzbee9e0f9b02011-08-24 15:32:46 -0700785 info->isTemp = false;
786}
787
buzbee67bf8852011-08-17 17:51:35 -0700788extern void oatMarkPair(CompilationUnit* cUnit, int lowReg, int highReg)
789{
buzbee68253262011-10-07 14:02:25 -0700790 RegisterInfo* infoLo = oatGetRegInfo(cUnit, lowReg);
791 RegisterInfo* infoHi = oatGetRegInfo(cUnit, highReg);
buzbee67bf8852011-08-17 17:51:35 -0700792 infoLo->pair = infoHi->pair = true;
793 infoLo->partner = highReg;
794 infoHi->partner = lowReg;
795}
796
797extern void oatMarkClean(CompilationUnit* cUnit, RegLocation loc)
798{
buzbee68253262011-10-07 14:02:25 -0700799 RegisterInfo* info = oatGetRegInfo(cUnit, loc.lowReg);
buzbee67bf8852011-08-17 17:51:35 -0700800 info->dirty = false;
801 if (loc.wide) {
buzbee68253262011-10-07 14:02:25 -0700802 info = oatGetRegInfo(cUnit, loc.highReg);
buzbee67bf8852011-08-17 17:51:35 -0700803 info->dirty = false;
804 }
805}
806
807extern void oatMarkDirty(CompilationUnit* cUnit, RegLocation loc)
808{
809 if (loc.home) {
810 // If already home, can't be dirty
811 return;
812 }
buzbee68253262011-10-07 14:02:25 -0700813 RegisterInfo* info = oatGetRegInfo(cUnit, loc.lowReg);
buzbee67bf8852011-08-17 17:51:35 -0700814 info->dirty = true;
815 if (loc.wide) {
buzbee68253262011-10-07 14:02:25 -0700816 info = oatGetRegInfo(cUnit, loc.highReg);
buzbee67bf8852011-08-17 17:51:35 -0700817 info->dirty = true;
818 }
819}
820
821extern void oatMarkInUse(CompilationUnit* cUnit, int reg)
822{
buzbee68253262011-10-07 14:02:25 -0700823 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
buzbee67bf8852011-08-17 17:51:35 -0700824 info->inUse = true;
825}
826
buzbeeed3e9302011-09-23 17:34:19 -0700827STATIC void copyRegInfo(CompilationUnit* cUnit, int newReg, int oldReg)
buzbee67bf8852011-08-17 17:51:35 -0700828{
buzbee68253262011-10-07 14:02:25 -0700829 RegisterInfo* newInfo = oatGetRegInfo(cUnit, newReg);
830 RegisterInfo* oldInfo = oatGetRegInfo(cUnit, oldReg);
buzbeeec5adf32011-09-11 15:25:43 -0700831 // Target temp status must not change
832 bool isTemp = newInfo->isTemp;
buzbee67bf8852011-08-17 17:51:35 -0700833 *newInfo = *oldInfo;
buzbeeec5adf32011-09-11 15:25:43 -0700834 // Restore target's temp status
835 newInfo->isTemp = isTemp;
buzbee67bf8852011-08-17 17:51:35 -0700836 newInfo->reg = newReg;
837}
838
839/*
840 * Return an updated location record with current in-register status.
841 * If the value lives in live temps, reflect that fact. No code
buzbeeb29e4d12011-09-26 15:05:48 -0700842 * is generated. If the live value is part of an older pair,
buzbee67bf8852011-08-17 17:51:35 -0700843 * clobber both low and high.
844 * TUNING: clobbering both is a bit heavy-handed, but the alternative
845 * is a bit complex when dealing with FP regs. Examine code to see
846 * if it's worthwhile trying to be more clever here.
847 */
848
849extern RegLocation oatUpdateLoc(CompilationUnit* cUnit, RegLocation loc)
850{
buzbeeed3e9302011-09-23 17:34:19 -0700851 DCHECK(!loc.wide);
buzbee6181f792011-09-29 11:14:04 -0700852 DCHECK(oatCheckCorePoolSanity(cUnit));
buzbee67bf8852011-08-17 17:51:35 -0700853 if (loc.location == kLocDalvikFrame) {
854 RegisterInfo* infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
855 if (infoLo) {
856 if (infoLo->pair) {
857 oatClobber(cUnit, infoLo->reg);
858 oatClobber(cUnit, infoLo->partner);
buzbee58f92742011-10-01 11:22:17 -0700859 oatFreeTemp(cUnit, infoLo->reg);
buzbee67bf8852011-08-17 17:51:35 -0700860 } else {
861 loc.lowReg = infoLo->reg;
862 loc.location = kLocPhysReg;
863 }
864 }
865 }
866
867 return loc;
868}
869
buzbee6181f792011-09-29 11:14:04 -0700870bool oatCheckCorePoolSanity(CompilationUnit* cUnit)
871{
872 for (static int i = 0; i < cUnit->regPool->numCoreRegs; i++) {
873 if (cUnit->regPool->coreRegs[i].pair) {
874 static int myReg = cUnit->regPool->coreRegs[i].reg;
875 static int mySreg = cUnit->regPool->coreRegs[i].sReg;
876 static int partnerReg = cUnit->regPool->coreRegs[i].partner;
buzbee68253262011-10-07 14:02:25 -0700877 static RegisterInfo* partner = oatGetRegInfo(cUnit, partnerReg);
buzbee6181f792011-09-29 11:14:04 -0700878 DCHECK(partner != NULL);
879 DCHECK(partner->pair);
880 DCHECK_EQ(myReg, partner->partner);
881 static int partnerSreg = partner->sReg;
882 if (mySreg == INVALID_SREG) {
883 DCHECK_EQ(partnerSreg, INVALID_SREG);
884 } else {
885 int diff = mySreg - partnerSreg;
886 DCHECK((diff == -1) || (diff == 1));
887 }
888 }
889 if (!cUnit->regPool->coreRegs[i].live) {
890 DCHECK(cUnit->regPool->coreRegs[i].defStart == NULL);
891 DCHECK(cUnit->regPool->coreRegs[i].defEnd == NULL);
892 }
893 }
894 return true;
895}
896
buzbee67bf8852011-08-17 17:51:35 -0700897/* see comments for updateLoc */
898extern RegLocation oatUpdateLocWide(CompilationUnit* cUnit,
899 RegLocation loc)
900{
buzbeeed3e9302011-09-23 17:34:19 -0700901 DCHECK(loc.wide);
buzbee6181f792011-09-29 11:14:04 -0700902 DCHECK(oatCheckCorePoolSanity(cUnit));
buzbee67bf8852011-08-17 17:51:35 -0700903 if (loc.location == kLocDalvikFrame) {
904 // Are the dalvik regs already live in physical registers?
905 RegisterInfo* infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
906 RegisterInfo* infoHi = allocLive(cUnit,
907 oatSRegHi(loc.sRegLow), kAnyReg);
908 bool match = true;
909 match = match && (infoLo != NULL);
910 match = match && (infoHi != NULL);
911 // Are they both core or both FP?
912 match = match && (FPREG(infoLo->reg) == FPREG(infoHi->reg));
913 // If a pair of floating point singles, are they properly aligned?
914 if (match && FPREG(infoLo->reg)) {
915 match &= ((infoLo->reg & 0x1) == 0);
916 match &= ((infoHi->reg - infoLo->reg) == 1);
917 }
918 // If previously used as a pair, it is the same pair?
919 if (match && (infoLo->pair || infoHi->pair)) {
920 match = (infoLo->pair == infoHi->pair);
921 match &= ((infoLo->reg == infoHi->partner) &&
922 (infoHi->reg == infoLo->partner));
923 }
924 if (match) {
925 // Can reuse - update the register usage info
926 loc.lowReg = infoLo->reg;
927 loc.highReg = infoHi->reg;
928 loc.location = kLocPhysReg;
929 oatMarkPair(cUnit, loc.lowReg, loc.highReg);
buzbeeed3e9302011-09-23 17:34:19 -0700930 DCHECK(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
buzbee67bf8852011-08-17 17:51:35 -0700931 return loc;
932 }
buzbee58f92742011-10-01 11:22:17 -0700933 // Can't easily reuse - clobber and free any overlaps
buzbee67bf8852011-08-17 17:51:35 -0700934 if (infoLo) {
935 oatClobber(cUnit, infoLo->reg);
buzbee58f92742011-10-01 11:22:17 -0700936 oatFreeTemp(cUnit, infoLo->reg);
buzbee67bf8852011-08-17 17:51:35 -0700937 if (infoLo->pair)
938 oatClobber(cUnit, infoLo->partner);
939 }
940 if (infoHi) {
941 oatClobber(cUnit, infoHi->reg);
buzbee58f92742011-10-01 11:22:17 -0700942 oatFreeTemp(cUnit, infoHi->reg);
buzbee67bf8852011-08-17 17:51:35 -0700943 if (infoHi->pair)
944 oatClobber(cUnit, infoHi->partner);
945 }
946 }
947 return loc;
948}
949
buzbeeed3e9302011-09-23 17:34:19 -0700950
951/* For use in cases we don't know (or care) width */
952extern RegLocation oatUpdateRawLoc(CompilationUnit* cUnit,
953 RegLocation loc)
954{
955 if (loc.wide)
956 return oatUpdateLocWide(cUnit, loc);
957 else
958 return oatUpdateLoc(cUnit, loc);
959}
960
961STATIC RegLocation evalLocWide(CompilationUnit* cUnit, RegLocation loc,
buzbee67bf8852011-08-17 17:51:35 -0700962 int regClass, bool update)
963{
buzbeeed3e9302011-09-23 17:34:19 -0700964 DCHECK(loc.wide);
buzbee67bf8852011-08-17 17:51:35 -0700965 int newRegs;
966 int lowReg;
967 int highReg;
968
969 loc = oatUpdateLocWide(cUnit, loc);
970
971 /* If already in registers, we can assume proper form. Right reg class? */
972 if (loc.location == kLocPhysReg) {
buzbeeed3e9302011-09-23 17:34:19 -0700973 DCHECK_EQ(FPREG(loc.lowReg), FPREG(loc.highReg));
974 DCHECK(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
buzbee67bf8852011-08-17 17:51:35 -0700975 if (!regClassMatches(regClass, loc.lowReg)) {
976 /* Wrong register class. Reallocate and copy */
977 newRegs = oatAllocTypedTempPair(cUnit, loc.fp, regClass);
978 lowReg = newRegs & 0xff;
979 highReg = (newRegs >> 8) & 0xff;
980 oatRegCopyWide(cUnit, lowReg, highReg, loc.lowReg,
981 loc.highReg);
982 copyRegInfo(cUnit, lowReg, loc.lowReg);
983 copyRegInfo(cUnit, highReg, loc.highReg);
984 oatClobber(cUnit, loc.lowReg);
985 oatClobber(cUnit, loc.highReg);
986 loc.lowReg = lowReg;
987 loc.highReg = highReg;
988 oatMarkPair(cUnit, loc.lowReg, loc.highReg);
buzbeeed3e9302011-09-23 17:34:19 -0700989 DCHECK(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
buzbee67bf8852011-08-17 17:51:35 -0700990 }
991 return loc;
992 }
993
buzbeeed3e9302011-09-23 17:34:19 -0700994 DCHECK_NE(loc.sRegLow, INVALID_SREG);
995 DCHECK_NE(oatSRegHi(loc.sRegLow), INVALID_SREG);
buzbee67bf8852011-08-17 17:51:35 -0700996
997 newRegs = oatAllocTypedTempPair(cUnit, loc.fp, regClass);
998 loc.lowReg = newRegs & 0xff;
999 loc.highReg = (newRegs >> 8) & 0xff;
1000
1001 oatMarkPair(cUnit, loc.lowReg, loc.highReg);
1002 if (update) {
1003 loc.location = kLocPhysReg;
1004 oatMarkLive(cUnit, loc.lowReg, loc.sRegLow);
1005 oatMarkLive(cUnit, loc.highReg, oatSRegHi(loc.sRegLow));
1006 }
buzbeeed3e9302011-09-23 17:34:19 -07001007 DCHECK(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
buzbee67bf8852011-08-17 17:51:35 -07001008 return loc;
1009}
1010
1011extern RegLocation oatEvalLoc(CompilationUnit* cUnit, RegLocation loc,
1012 int regClass, bool update)
1013{
1014 int newReg;
1015
1016 if (loc.wide)
1017 return evalLocWide(cUnit, loc, regClass, update);
1018
1019 loc = oatUpdateLoc(cUnit, loc);
1020
1021 if (loc.location == kLocPhysReg) {
1022 if (!regClassMatches(regClass, loc.lowReg)) {
1023 /* Wrong register class. Realloc, copy and transfer ownership */
1024 newReg = oatAllocTypedTemp(cUnit, loc.fp, regClass);
1025 oatRegCopy(cUnit, newReg, loc.lowReg);
1026 copyRegInfo(cUnit, newReg, loc.lowReg);
1027 oatClobber(cUnit, loc.lowReg);
1028 loc.lowReg = newReg;
1029 }
1030 return loc;
1031 }
1032
buzbeeed3e9302011-09-23 17:34:19 -07001033 DCHECK_NE(loc.sRegLow, INVALID_SREG);
buzbee67bf8852011-08-17 17:51:35 -07001034
1035 newReg = oatAllocTypedTemp(cUnit, loc.fp, regClass);
1036 loc.lowReg = newReg;
1037
1038 if (update) {
1039 loc.location = kLocPhysReg;
1040 oatMarkLive(cUnit, loc.lowReg, loc.sRegLow);
1041 }
1042 return loc;
1043}
1044
1045extern RegLocation oatGetDest(CompilationUnit* cUnit, MIR* mir, int num)
1046{
buzbeee9a72f62011-09-04 17:59:07 -07001047 RegLocation res = cUnit->regLocation[mir->ssaRep->defs[num]];
buzbeeed3e9302011-09-23 17:34:19 -07001048 DCHECK(!res.wide);
buzbeee9a72f62011-09-04 17:59:07 -07001049 return res;
buzbee67bf8852011-08-17 17:51:35 -07001050}
1051extern RegLocation oatGetSrc(CompilationUnit* cUnit, MIR* mir, int num)
1052{
buzbeee9a72f62011-09-04 17:59:07 -07001053 RegLocation res = cUnit->regLocation[mir->ssaRep->uses[num]];
buzbeeed3e9302011-09-23 17:34:19 -07001054 DCHECK(!res.wide);
buzbeee9a72f62011-09-04 17:59:07 -07001055 return res;
1056}
1057extern RegLocation oatGetRawSrc(CompilationUnit* cUnit, MIR* mir, int num)
1058{
1059 RegLocation res = cUnit->regLocation[mir->ssaRep->uses[num]];
1060 return res;
buzbee67bf8852011-08-17 17:51:35 -07001061}
1062extern RegLocation oatGetDestWide(CompilationUnit* cUnit, MIR* mir,
1063 int low, int high)
1064{
buzbeee9a72f62011-09-04 17:59:07 -07001065 RegLocation res = cUnit->regLocation[mir->ssaRep->defs[low]];
buzbeeed3e9302011-09-23 17:34:19 -07001066 DCHECK(res.wide);
buzbeee9a72f62011-09-04 17:59:07 -07001067 return res;
buzbee67bf8852011-08-17 17:51:35 -07001068}
1069
1070extern RegLocation oatGetSrcWide(CompilationUnit* cUnit, MIR* mir,
1071 int low, int high)
1072{
buzbeee9a72f62011-09-04 17:59:07 -07001073 RegLocation res = cUnit->regLocation[mir->ssaRep->uses[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}