blob: 9d3717a2794fd50f3e4a97a0109fa56b849d86e9 [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 -0700100/* Get info for a reg. */
buzbeeed3e9302011-09-23 17:34:19 -0700101STATIC RegisterInfo* getRegInfo(CompilationUnit* cUnit, int reg)
buzbee67bf8852011-08-17 17:51:35 -0700102{
103 int numRegs = cUnit->regPool->numCoreRegs;
104 RegisterInfo* p = cUnit->regPool->coreRegs;
105 int i;
106 for (i=0; i< numRegs; i++) {
107 if (p[i].reg == reg) {
108 return &p[i];
109 }
110 }
111 p = cUnit->regPool->FPRegs;
112 numRegs = cUnit->regPool->numFPRegs;
113 for (i=0; i< numRegs; i++) {
114 if (p[i].reg == reg) {
115 return &p[i];
116 }
117 }
118 LOG(FATAL) << "Tried to get info on a non-existant reg :r" << reg;
119 return NULL; // Quiet gcc
120}
121
122void oatFlushRegWide(CompilationUnit* cUnit, int reg1, int reg2)
123{
124 RegisterInfo* info1 = getRegInfo(cUnit, reg1);
125 RegisterInfo* info2 = getRegInfo(cUnit, reg2);
buzbeeed3e9302011-09-23 17:34:19 -0700126 DCHECK(info1 && info2 && info1->pair && info2->pair &&
buzbee67bf8852011-08-17 17:51:35 -0700127 (info1->partner == info2->reg) &&
128 (info2->partner == info1->reg));
129 if ((info1->live && info1->dirty) || (info2->live && info2->dirty)) {
130 if (!(info1->isTemp && info2->isTemp)) {
131 /* Should not happen. If it does, there's a problem in evalLoc */
132 LOG(FATAL) << "Long half-temp, half-promoted";
133 }
134
135 info1->dirty = false;
136 info2->dirty = false;
137 if (oatS2VReg(cUnit, info2->sReg) <
138 oatS2VReg(cUnit, info1->sReg))
139 info1 = info2;
140 int vReg = oatS2VReg(cUnit, info1->sReg);
141 oatFlushRegWideImpl(cUnit, rSP,
142 oatVRegOffset(cUnit, vReg),
143 info1->reg, info1->partner);
144 }
145}
146
147void oatFlushReg(CompilationUnit* cUnit, int reg)
148{
149 RegisterInfo* info = getRegInfo(cUnit, reg);
150 if (info->live && info->dirty) {
151 info->dirty = false;
152 int vReg = oatS2VReg(cUnit, info->sReg);
153 oatFlushRegImpl(cUnit, rSP,
154 oatVRegOffset(cUnit, vReg),
155 reg, kWord);
156 }
157}
158
159/* return true if found reg to clobber */
buzbeeed3e9302011-09-23 17:34:19 -0700160STATIC bool clobberRegBody(CompilationUnit* cUnit, RegisterInfo* p,
buzbee67bf8852011-08-17 17:51:35 -0700161 int numRegs, int reg)
162{
163 int i;
164 for (i=0; i< numRegs; i++) {
165 if (p[i].reg == reg) {
166 if (p[i].isTemp) {
buzbee6181f792011-09-29 11:14:04 -0700167 if (p[i].live && p[i].dirty) {
168 LOG(FATAL) << "Live & dirty temp in clobber";
buzbee67bf8852011-08-17 17:51:35 -0700169 }
170 p[i].live = false;
171 p[i].sReg = INVALID_SREG;
172 }
173 p[i].defStart = NULL;
174 p[i].defEnd = NULL;
175 if (p[i].pair) {
176 p[i].pair = false;
177 /* partners should be in same pool */
178 clobberRegBody(cUnit, p, numRegs, p[i].partner);
179 }
180 return true;
181 }
182 }
183 return false;
184}
185
186/* Mark a temp register as dead. Does not affect allocation state. */
187void oatClobber(CompilationUnit* cUnit, int reg)
188{
189 if (!clobberRegBody(cUnit, cUnit->regPool->coreRegs,
190 cUnit->regPool->numCoreRegs, reg)) {
191 clobberRegBody(cUnit, cUnit->regPool->FPRegs,
192 cUnit->regPool->numFPRegs, reg);
193 }
194}
195
buzbeeed3e9302011-09-23 17:34:19 -0700196STATIC void clobberSRegBody(RegisterInfo* p, int numRegs, int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700197{
198 int i;
199 for (i=0; i< numRegs; i++) {
200 if (p[i].sReg == sReg) {
201 if (p[i].isTemp) {
202 p[i].live = false;
203 }
204 p[i].defStart = NULL;
205 p[i].defEnd = NULL;
206 }
207 }
208}
209
210/* Clobber any temp associated with an sReg. Could be in either class */
211extern void oatClobberSReg(CompilationUnit* cUnit, int sReg)
212{
213 clobberSRegBody(cUnit->regPool->coreRegs, cUnit->regPool->numCoreRegs,
214 sReg);
215 clobberSRegBody(cUnit->regPool->FPRegs, cUnit->regPool->numFPRegs,
216 sReg);
217}
218
219/* Reserve a callee-save register. Return -1 if none available */
220extern int oatAllocPreservedCoreReg(CompilationUnit* cUnit, int sReg)
221{
222 int res = -1;
223 RegisterInfo* coreRegs = cUnit->regPool->coreRegs;
224 for (int i = 0; i < cUnit->regPool->numCoreRegs; i++) {
225 if (!coreRegs[i].isTemp && !coreRegs[i].inUse) {
226 res = coreRegs[i].reg;
227 coreRegs[i].inUse = true;
228 cUnit->coreSpillMask |= (1 << res);
buzbeec41e5b52011-09-23 12:46:19 -0700229 cUnit->coreVmapTable.push_back(sReg);
buzbeebbaf8942011-10-02 13:08:29 -0700230 cUnit->numCoreSpills++;
buzbee67bf8852011-08-17 17:51:35 -0700231 cUnit->regLocation[sReg].location = kLocPhysReg;
232 cUnit->regLocation[sReg].lowReg = res;
233 cUnit->regLocation[sReg].home = true;
234 break;
235 }
236 }
237 return res;
238}
239
240/*
buzbeebbaf8942011-10-02 13:08:29 -0700241 * Mark a callee-save fp register as promoted. Note that
242 * vpush/vpop uses contiguous register lists so we must
243 * include any holes in the mask. Associate holes with
buzbee3ddc0d12011-10-05 10:36:21 -0700244 * Dalvik register INVALID_VREG (0xFFFFU).
buzbeebbaf8942011-10-02 13:08:29 -0700245 */
246STATIC void markPreservedSingle(CompilationUnit* cUnit, int sReg, int reg)
247{
248 DCHECK_GE(reg, FP_REG_MASK + FP_CALLEE_SAVE_BASE);
249 reg = (reg & FP_REG_MASK) - FP_CALLEE_SAVE_BASE;
250 // Ensure fpVmapTable is large enough
251 int tableSize = cUnit->fpVmapTable.size();
252 for (int i = tableSize; i < (reg + 1); i++) {
buzbee3ddc0d12011-10-05 10:36:21 -0700253 cUnit->fpVmapTable.push_back(INVALID_VREG);
buzbeebbaf8942011-10-02 13:08:29 -0700254 }
255 // Add the current mapping
256 cUnit->fpVmapTable[reg] = sReg;
257 // Size of fpVmapTable is high-water mark, use to set mask
258 cUnit->numFPSpills = cUnit->fpVmapTable.size();
259 cUnit->fpSpillMask = ((1 << cUnit->numFPSpills) - 1) << FP_CALLEE_SAVE_BASE;
260}
261
262/*
buzbee67bf8852011-08-17 17:51:35 -0700263 * Reserve a callee-save fp single register. Try to fullfill request for
264 * even/odd allocation, but go ahead and allocate anything if not
265 * available. If nothing's available, return -1.
266 */
buzbeeed3e9302011-09-23 17:34:19 -0700267STATIC int allocPreservedSingle(CompilationUnit* cUnit, int sReg, bool even)
buzbee67bf8852011-08-17 17:51:35 -0700268{
269 int res = -1;
270 RegisterInfo* FPRegs = cUnit->regPool->FPRegs;
271 for (int i = 0; i < cUnit->regPool->numFPRegs; i++) {
272 if (!FPRegs[i].isTemp && !FPRegs[i].inUse &&
273 ((FPRegs[i].reg & 0x1) == 0) == even) {
274 res = FPRegs[i].reg;
275 FPRegs[i].inUse = true;
buzbeebbaf8942011-10-02 13:08:29 -0700276 markPreservedSingle(cUnit, sReg, res);
buzbee67bf8852011-08-17 17:51:35 -0700277 cUnit->regLocation[sReg].fpLocation = kLocPhysReg;
278 cUnit->regLocation[sReg].fpLowReg = res;
279 cUnit->regLocation[sReg].home = true;
280 break;
281 }
282 }
283 return res;
284}
285
286/*
287 * Somewhat messy code here. We want to allocate a pair of contiguous
288 * physical single-precision floating point registers starting with
289 * an even numbered reg. It is possible that the paired sReg (sReg+1)
290 * has already been allocated - try to fit if possible. Fail to
291 * allocate if we can't meet the requirements for the pair of
292 * sReg<=sX[even] & (sReg+1)<= sX+1.
293 */
buzbeeed3e9302011-09-23 17:34:19 -0700294STATIC int allocPreservedDouble(CompilationUnit* cUnit, int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700295{
296 int res = -1; // Assume failure
297 if (cUnit->regLocation[sReg+1].fpLocation == kLocPhysReg) {
298 // Upper reg is already allocated. Can we fit?
299 int highReg = cUnit->regLocation[sReg+1].fpLowReg;
300 if ((highReg & 1) == 0) {
301 // High reg is even - fail.
302 return res;
303 }
304 // Is the low reg of the pair free?
305 RegisterInfo* p = getRegInfo(cUnit, highReg-1);
306 if (p->inUse || p->isTemp) {
307 // Already allocated or not preserved - fail.
308 return res;
309 }
310 // OK - good to go.
311 res = p->reg;
312 p->inUse = true;
buzbeeed3e9302011-09-23 17:34:19 -0700313 DCHECK_EQ((res & 1), 0);
buzbeebbaf8942011-10-02 13:08:29 -0700314 markPreservedSingle(cUnit, sReg, res);
buzbee67bf8852011-08-17 17:51:35 -0700315 } else {
316 RegisterInfo* FPRegs = cUnit->regPool->FPRegs;
317 for (int i = 0; i < cUnit->regPool->numFPRegs; i++) {
318 if (!FPRegs[i].isTemp && !FPRegs[i].inUse &&
319 ((FPRegs[i].reg & 0x1) == 0x0) &&
320 !FPRegs[i+1].isTemp && !FPRegs[i+1].inUse &&
321 ((FPRegs[i+1].reg & 0x1) == 0x1) &&
322 (FPRegs[i].reg + 1) == FPRegs[i+1].reg) {
323 res = FPRegs[i].reg;
324 FPRegs[i].inUse = true;
buzbeebbaf8942011-10-02 13:08:29 -0700325 markPreservedSingle(cUnit, sReg, res);
buzbee67bf8852011-08-17 17:51:35 -0700326 FPRegs[i+1].inUse = true;
buzbeebbaf8942011-10-02 13:08:29 -0700327 DCHECK_EQ(res + 1, FPRegs[i+1].reg);
328 markPreservedSingle(cUnit, sReg+1, res+1);
buzbee67bf8852011-08-17 17:51:35 -0700329 break;
330 }
331 }
332 }
333 if (res != -1) {
334 cUnit->regLocation[sReg].fpLocation = kLocPhysReg;
335 cUnit->regLocation[sReg].fpLowReg = res;
336 cUnit->regLocation[sReg].home = true;
337 cUnit->regLocation[sReg+1].fpLocation = kLocPhysReg;
338 cUnit->regLocation[sReg+1].fpLowReg = res + 1;
339 cUnit->regLocation[sReg+1].home = true;
340 }
341 return res;
342}
343
344
345/*
346 * Reserve a callee-save fp register. If this register can be used
347 * as the first of a double, attempt to allocate an even pair of fp
348 * single regs (but if can't still attempt to allocate a single, preferring
349 * first to allocate an odd register.
350 */
351extern int oatAllocPreservedFPReg(CompilationUnit* cUnit, int sReg,
352 bool doubleStart)
353{
354 int res = -1;
355 if (doubleStart) {
356 res = allocPreservedDouble(cUnit, sReg);
357 } else {
358 }
359 if (res == -1) {
360 res = allocPreservedSingle(cUnit, sReg, false /* try odd # */);
361 }
362 if (res == -1)
363 res = allocPreservedSingle(cUnit, sReg, true /* try even # */);
364 return res;
365}
366
buzbeeed3e9302011-09-23 17:34:19 -0700367STATIC int allocTempBody(CompilationUnit* cUnit, RegisterInfo* p, int numRegs,
buzbee67bf8852011-08-17 17:51:35 -0700368 int* nextTemp, bool required)
369{
370 int i;
371 int next = *nextTemp;
372 for (i=0; i< numRegs; i++) {
373 if (next >= numRegs)
374 next = 0;
375 if (p[next].isTemp && !p[next].inUse && !p[next].live) {
376 oatClobber(cUnit, p[next].reg);
377 p[next].inUse = true;
378 p[next].pair = false;
379 *nextTemp = next + 1;
380 return p[next].reg;
381 }
382 next++;
383 }
384 next = *nextTemp;
385 for (i=0; i< numRegs; i++) {
386 if (next >= numRegs)
387 next = 0;
388 if (p[next].isTemp && !p[next].inUse) {
389 oatClobber(cUnit, p[next].reg);
390 p[next].inUse = true;
391 p[next].pair = false;
392 *nextTemp = next + 1;
393 return p[next].reg;
394 }
395 next++;
396 }
397 if (required) {
buzbee6181f792011-09-29 11:14:04 -0700398 oatCodegenDump(cUnit);
buzbee67bf8852011-08-17 17:51:35 -0700399 dumpRegPool(cUnit->regPool->coreRegs,
400 cUnit->regPool->numCoreRegs);
401 LOG(FATAL) << "No free temp registers";
402 }
403 return -1; // No register available
404}
405
406//REDO: too many assumptions.
407extern int oatAllocTempDouble(CompilationUnit* cUnit)
408{
409 RegisterInfo* p = cUnit->regPool->FPRegs;
410 int numRegs = cUnit->regPool->numFPRegs;
411 int next = cUnit->regPool->nextFPReg;
412 int i;
413
414 for (i=0; i < numRegs; i+=2) {
415 /* Cleanup - not all targets need aligned regs */
416 if (next & 1)
417 next++;
418 if (next >= numRegs)
419 next = 0;
420 if ((p[next].isTemp && !p[next].inUse && !p[next].live) &&
421 (p[next+1].isTemp && !p[next+1].inUse && !p[next+1].live)) {
422 oatClobber(cUnit, p[next].reg);
423 oatClobber(cUnit, p[next+1].reg);
424 p[next].inUse = true;
425 p[next+1].inUse = true;
buzbeeed3e9302011-09-23 17:34:19 -0700426 DCHECK_EQ((p[next].reg+1), p[next+1].reg);
427 DCHECK_EQ((p[next].reg & 0x1), 0);
buzbee67bf8852011-08-17 17:51:35 -0700428 cUnit->regPool->nextFPReg += 2;
429 return p[next].reg;
430 }
431 next += 2;
432 }
433 next = cUnit->regPool->nextFPReg;
434 for (i=0; i < numRegs; i+=2) {
435 if (next >= numRegs)
436 next = 0;
437 if (p[next].isTemp && !p[next].inUse && p[next+1].isTemp &&
438 !p[next+1].inUse) {
439 oatClobber(cUnit, p[next].reg);
440 oatClobber(cUnit, p[next+1].reg);
441 p[next].inUse = true;
442 p[next+1].inUse = true;
buzbeeed3e9302011-09-23 17:34:19 -0700443 DCHECK_EQ((p[next].reg+1), p[next+1].reg);
444 DCHECK_EQ((p[next].reg & 0x1), 0);
buzbee67bf8852011-08-17 17:51:35 -0700445 cUnit->regPool->nextFPReg += 2;
446 return p[next].reg;
447 }
448 next += 2;
449 }
buzbee6181f792011-09-29 11:14:04 -0700450 LOG(FATAL) << "No free temp registers (pair)";
buzbee67bf8852011-08-17 17:51:35 -0700451 return -1;
452}
453
454/* Return a temp if one is available, -1 otherwise */
455extern int oatAllocFreeTemp(CompilationUnit* cUnit)
456{
457 return allocTempBody(cUnit, cUnit->regPool->coreRegs,
458 cUnit->regPool->numCoreRegs,
459 &cUnit->regPool->nextCoreReg, true);
460}
461
462extern int oatAllocTemp(CompilationUnit* cUnit)
463{
464 return allocTempBody(cUnit, cUnit->regPool->coreRegs,
465 cUnit->regPool->numCoreRegs,
466 &cUnit->regPool->nextCoreReg, true);
467}
468
469extern int oatAllocTempFloat(CompilationUnit* cUnit)
470{
471 return allocTempBody(cUnit, cUnit->regPool->FPRegs,
472 cUnit->regPool->numFPRegs,
473 &cUnit->regPool->nextFPReg, true);
474}
475
buzbeeed3e9302011-09-23 17:34:19 -0700476STATIC RegisterInfo* allocLiveBody(RegisterInfo* p, int numRegs, int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700477{
478 int i;
479 if (sReg == -1)
480 return NULL;
481 for (i=0; i < numRegs; i++) {
482 if (p[i].live && (p[i].sReg == sReg)) {
483 if (p[i].isTemp)
484 p[i].inUse = true;
485 return &p[i];
486 }
487 }
488 return NULL;
489}
490
buzbeeed3e9302011-09-23 17:34:19 -0700491STATIC RegisterInfo* allocLive(CompilationUnit* cUnit, int sReg,
buzbee67bf8852011-08-17 17:51:35 -0700492 int regClass)
493{
494 RegisterInfo* res = NULL;
495 switch(regClass) {
496 case kAnyReg:
497 res = allocLiveBody(cUnit->regPool->FPRegs,
498 cUnit->regPool->numFPRegs, sReg);
499 if (res)
500 break;
501 /* Intentional fallthrough */
502 case kCoreReg:
503 res = allocLiveBody(cUnit->regPool->coreRegs,
504 cUnit->regPool->numCoreRegs, sReg);
505 break;
506 case kFPReg:
507 res = allocLiveBody(cUnit->regPool->FPRegs,
508 cUnit->regPool->numFPRegs, sReg);
509 break;
510 default:
511 LOG(FATAL) << "Invalid register type";
512 }
513 return res;
514}
515
516extern void oatFreeTemp(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 if (p[i].isTemp) {
524 p[i].inUse = false;
525 }
526 p[i].pair = false;
527 return;
528 }
529 }
530 p = cUnit->regPool->FPRegs;
531 numRegs = cUnit->regPool->numFPRegs;
532 for (i=0; i< numRegs; i++) {
533 if (p[i].reg == reg) {
534 if (p[i].isTemp) {
535 p[i].inUse = false;
536 }
537 p[i].pair = false;
538 return;
539 }
540 }
541 LOG(FATAL) << "Tried to free a non-existant temp: r" << reg;
542}
543
544extern RegisterInfo* oatIsLive(CompilationUnit* cUnit, int reg)
545{
546 RegisterInfo* p = cUnit->regPool->coreRegs;
547 int numRegs = cUnit->regPool->numCoreRegs;
548 int i;
549 for (i=0; i< numRegs; i++) {
550 if (p[i].reg == reg) {
551 return p[i].live ? &p[i] : NULL;
552 }
553 }
554 p = cUnit->regPool->FPRegs;
555 numRegs = cUnit->regPool->numFPRegs;
556 for (i=0; i< numRegs; i++) {
557 if (p[i].reg == reg) {
558 return p[i].live ? &p[i] : NULL;
559 }
560 }
561 return NULL;
562}
563
564extern RegisterInfo* oatIsTemp(CompilationUnit* cUnit, int reg)
565{
566 RegisterInfo* p = getRegInfo(cUnit, reg);
567 return (p->isTemp) ? p : NULL;
568}
569
buzbeeb29e4d12011-09-26 15:05:48 -0700570extern RegisterInfo* oatIsPromoted(CompilationUnit* cUnit, int reg)
571{
572 RegisterInfo* p = getRegInfo(cUnit, reg);
573 return (p->isTemp) ? NULL : p;
574}
575
buzbee67bf8852011-08-17 17:51:35 -0700576extern bool oatIsDirty(CompilationUnit* cUnit, int reg)
577{
578 RegisterInfo* p = getRegInfo(cUnit, reg);
579 return p->dirty;
580}
581
582/*
583 * Similar to oatAllocTemp(), but forces the allocation of a specific
584 * register. No check is made to see if the register was previously
585 * allocated. Use with caution.
586 */
587extern void oatLockTemp(CompilationUnit* cUnit, int reg)
588{
589 RegisterInfo* p = cUnit->regPool->coreRegs;
590 int numRegs = cUnit->regPool->numCoreRegs;
591 int i;
592 for (i=0; i< numRegs; i++) {
593 if (p[i].reg == reg) {
buzbeeed3e9302011-09-23 17:34:19 -0700594 DCHECK(p[i].isTemp);
buzbee67bf8852011-08-17 17:51:35 -0700595 p[i].inUse = true;
596 p[i].live = false;
597 return;
598 }
599 }
600 p = cUnit->regPool->FPRegs;
601 numRegs = cUnit->regPool->numFPRegs;
602 for (i=0; i< numRegs; i++) {
603 if (p[i].reg == reg) {
buzbeeed3e9302011-09-23 17:34:19 -0700604 DCHECK(p[i].isTemp);
buzbee67bf8852011-08-17 17:51:35 -0700605 p[i].inUse = true;
606 p[i].live = false;
607 return;
608 }
609 }
610 LOG(FATAL) << "Tried to lock a non-existant temp: r" << reg;
611}
612
613extern void oatResetDef(CompilationUnit* cUnit, int reg)
614{
615 RegisterInfo* p = getRegInfo(cUnit, reg);
616 p->defStart = NULL;
617 p->defEnd = NULL;
618}
619
buzbeeed3e9302011-09-23 17:34:19 -0700620STATIC void nullifyRange(CompilationUnit* cUnit, LIR *start, LIR *finish,
buzbee67bf8852011-08-17 17:51:35 -0700621 int sReg1, int sReg2)
622{
623 if (start && finish) {
624 LIR *p;
buzbeeed3e9302011-09-23 17:34:19 -0700625 DCHECK_EQ(sReg1, sReg2);
buzbee67bf8852011-08-17 17:51:35 -0700626 for (p = start; ;p = p->next) {
627 ((ArmLIR *)p)->flags.isNop = true;
buzbee6181f792011-09-29 11:14:04 -0700628 ((ArmLIR *)p)->flags.squashed = true;
buzbee67bf8852011-08-17 17:51:35 -0700629 if (p == finish)
630 break;
631 }
632 }
633}
634
635/*
636 * Mark the beginning and end LIR of a def sequence. Note that
637 * on entry start points to the LIR prior to the beginning of the
638 * sequence.
639 */
640extern void oatMarkDef(CompilationUnit* cUnit, RegLocation rl,
641 LIR *start, LIR *finish)
642{
buzbeeed3e9302011-09-23 17:34:19 -0700643 DCHECK(!rl.wide);
644 DCHECK(start && start->next);
645 DCHECK(finish);
buzbee67bf8852011-08-17 17:51:35 -0700646 RegisterInfo* p = getRegInfo(cUnit, rl.lowReg);
647 p->defStart = start->next;
648 p->defEnd = finish;
649}
650
651/*
652 * Mark the beginning and end LIR of a def sequence. Note that
653 * on entry start points to the LIR prior to the beginning of the
654 * sequence.
655 */
656extern void oatMarkDefWide(CompilationUnit* cUnit, RegLocation rl,
657 LIR *start, LIR *finish)
658{
buzbeeed3e9302011-09-23 17:34:19 -0700659 DCHECK(rl.wide);
660 DCHECK(start && start->next);
661 DCHECK(finish);
buzbee67bf8852011-08-17 17:51:35 -0700662 RegisterInfo* p = getRegInfo(cUnit, rl.lowReg);
663 oatResetDef(cUnit, rl.highReg); // Only track low of pair
664 p->defStart = start->next;
665 p->defEnd = finish;
666}
667
668extern RegLocation oatWideToNarrow(CompilationUnit* cUnit,
669 RegLocation rl)
670{
buzbeeed3e9302011-09-23 17:34:19 -0700671 DCHECK(rl.wide);
buzbee67bf8852011-08-17 17:51:35 -0700672 if (rl.location == kLocPhysReg) {
673 RegisterInfo* infoLo = getRegInfo(cUnit, rl.lowReg);
674 RegisterInfo* infoHi = getRegInfo(cUnit, rl.highReg);
buzbee0c7f26d2011-09-07 12:28:51 -0700675 if (infoLo->isTemp) {
676 infoLo->pair = false;
677 infoLo->defStart = NULL;
678 infoLo->defEnd = NULL;
buzbee67bf8852011-08-17 17:51:35 -0700679 }
buzbee0c7f26d2011-09-07 12:28:51 -0700680 if (infoHi->isTemp) {
681 infoHi->pair = false;
682 infoHi->defStart = NULL;
683 infoHi->defEnd = NULL;
buzbee67bf8852011-08-17 17:51:35 -0700684 }
buzbee67bf8852011-08-17 17:51:35 -0700685 }
686 rl.wide = false;
687 return rl;
688}
689
690extern void oatResetDefLoc(CompilationUnit* cUnit, RegLocation rl)
691{
buzbeeed3e9302011-09-23 17:34:19 -0700692 DCHECK(!rl.wide);
buzbee6181f792011-09-29 11:14:04 -0700693 RegisterInfo* p = oatIsTemp(cUnit, rl.lowReg);
694 if (p && !(cUnit->disableOpt & (1 << kSuppressLoads))) {
buzbeeed3e9302011-09-23 17:34:19 -0700695 DCHECK(!p->pair);
buzbee67bf8852011-08-17 17:51:35 -0700696 nullifyRange(cUnit, p->defStart, p->defEnd,
697 p->sReg, rl.sRegLow);
698 }
699 oatResetDef(cUnit, rl.lowReg);
700}
701
702extern void oatResetDefLocWide(CompilationUnit* cUnit, RegLocation rl)
703{
buzbeeed3e9302011-09-23 17:34:19 -0700704 DCHECK(rl.wide);
buzbee6181f792011-09-29 11:14:04 -0700705 RegisterInfo* pLow = oatIsTemp(cUnit, rl.lowReg);
706 RegisterInfo* pHigh = oatIsTemp(cUnit, rl.highReg);
707 if (pLow && !(cUnit->disableOpt & (1 << kSuppressLoads))) {
708 DCHECK(pLow->pair);
709 nullifyRange(cUnit, pLow->defStart, pLow->defEnd,
710 pLow->sReg, rl.sRegLow);
711 }
712 if (pHigh && !(cUnit->disableOpt & (1 << kSuppressLoads))) {
713 DCHECK(pHigh->pair);
buzbee67bf8852011-08-17 17:51:35 -0700714 }
715 oatResetDef(cUnit, rl.lowReg);
716 oatResetDef(cUnit, rl.highReg);
717}
718
719extern void oatResetDefTracking(CompilationUnit* cUnit)
720{
721 int i;
722 for (i=0; i< cUnit->regPool->numCoreRegs; i++) {
723 oatResetDef(cUnit, cUnit->regPool->coreRegs[i].reg);
724 }
725 for (i=0; i< cUnit->regPool->numFPRegs; i++) {
726 oatResetDef(cUnit, cUnit->regPool->FPRegs[i].reg);
727 }
728}
729
730extern void oatClobberAllRegs(CompilationUnit* cUnit)
731{
732 int i;
733 for (i=0; i< cUnit->regPool->numCoreRegs; i++) {
734 oatClobber(cUnit, cUnit->regPool->coreRegs[i].reg);
735 }
736 for (i=0; i< cUnit->regPool->numFPRegs; i++) {
737 oatClobber(cUnit, cUnit->regPool->FPRegs[i].reg);
738 }
739}
740
741/* To be used when explicitly managing register use */
buzbee2e748f32011-08-29 21:02:19 -0700742extern void oatLockCallTemps(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700743{
buzbee2e748f32011-08-29 21:02:19 -0700744 //TODO: Arm specific - move to target dependent code
745 oatLockTemp(cUnit, r0);
746 oatLockTemp(cUnit, r1);
747 oatLockTemp(cUnit, r2);
748 oatLockTemp(cUnit, r3);
buzbee67bf8852011-08-17 17:51:35 -0700749}
750
buzbee0d966cf2011-09-08 17:34:58 -0700751/* To be used when explicitly managing register use */
752extern void oatFreeCallTemps(CompilationUnit* cUnit)
753{
754 //TODO: Arm specific - move to target dependent code
755 oatFreeTemp(cUnit, r0);
756 oatFreeTemp(cUnit, r1);
757 oatFreeTemp(cUnit, r2);
758 oatFreeTemp(cUnit, r3);
759}
760
buzbee67bf8852011-08-17 17:51:35 -0700761// Make sure nothing is live and dirty
buzbeeed3e9302011-09-23 17:34:19 -0700762STATIC void flushAllRegsBody(CompilationUnit* cUnit, RegisterInfo* info,
buzbee67bf8852011-08-17 17:51:35 -0700763 int numRegs)
764{
765 int i;
766 for (i=0; i < numRegs; i++) {
767 if (info[i].live && info[i].dirty) {
768 if (info[i].pair) {
769 oatFlushRegWide(cUnit, info[i].reg, info[i].partner);
770 } else {
771 oatFlushReg(cUnit, info[i].reg);
772 }
773 }
774 }
775}
776
777extern void oatFlushAllRegs(CompilationUnit* cUnit)
778{
779 flushAllRegsBody(cUnit, cUnit->regPool->coreRegs,
780 cUnit->regPool->numCoreRegs);
781 flushAllRegsBody(cUnit, cUnit->regPool->FPRegs,
782 cUnit->regPool->numFPRegs);
783 oatClobberAllRegs(cUnit);
784}
785
786
787//TUNING: rewrite all of this reg stuff. Probably use an attribute table
buzbeeed3e9302011-09-23 17:34:19 -0700788STATIC bool regClassMatches(int regClass, int reg)
buzbee67bf8852011-08-17 17:51:35 -0700789{
790 if (regClass == kAnyReg) {
791 return true;
792 } else if (regClass == kCoreReg) {
793 return !FPREG(reg);
794 } else {
795 return FPREG(reg);
796 }
797}
798
799extern void oatMarkLive(CompilationUnit* cUnit, int reg, int sReg)
800{
801 RegisterInfo* info = getRegInfo(cUnit, reg);
802 if ((info->reg == reg) && (info->sReg == sReg) && info->live) {
803 return; /* already live */
804 } else if (sReg != INVALID_SREG) {
805 oatClobberSReg(cUnit, sReg);
806 if (info->isTemp) {
807 info->live = true;
808 }
809 } else {
810 /* Can't be live if no associated sReg */
buzbeeed3e9302011-09-23 17:34:19 -0700811 DCHECK(info->isTemp);
buzbee67bf8852011-08-17 17:51:35 -0700812 info->live = false;
813 }
814 info->sReg = sReg;
815}
816
817extern void oatMarkTemp(CompilationUnit* cUnit, int reg)
818{
819 RegisterInfo* info = getRegInfo(cUnit, reg);
820 info->isTemp = true;
821}
822
buzbee9e0f9b02011-08-24 15:32:46 -0700823extern void oatUnmarkTemp(CompilationUnit* cUnit, int reg)
824{
825 RegisterInfo* info = getRegInfo(cUnit, reg);
826 info->isTemp = false;
827}
828
buzbee67bf8852011-08-17 17:51:35 -0700829extern void oatMarkPair(CompilationUnit* cUnit, int lowReg, int highReg)
830{
831 RegisterInfo* infoLo = getRegInfo(cUnit, lowReg);
832 RegisterInfo* infoHi = getRegInfo(cUnit, highReg);
833 infoLo->pair = infoHi->pair = true;
834 infoLo->partner = highReg;
835 infoHi->partner = lowReg;
836}
837
838extern void oatMarkClean(CompilationUnit* cUnit, RegLocation loc)
839{
840 RegisterInfo* info = getRegInfo(cUnit, loc.lowReg);
841 info->dirty = false;
842 if (loc.wide) {
843 info = getRegInfo(cUnit, loc.highReg);
844 info->dirty = false;
845 }
846}
847
848extern void oatMarkDirty(CompilationUnit* cUnit, RegLocation loc)
849{
850 if (loc.home) {
851 // If already home, can't be dirty
852 return;
853 }
854 RegisterInfo* info = getRegInfo(cUnit, loc.lowReg);
855 info->dirty = true;
856 if (loc.wide) {
857 info = getRegInfo(cUnit, loc.highReg);
858 info->dirty = true;
859 }
860}
861
862extern void oatMarkInUse(CompilationUnit* cUnit, int reg)
863{
864 RegisterInfo* info = getRegInfo(cUnit, reg);
865 info->inUse = true;
866}
867
buzbeeed3e9302011-09-23 17:34:19 -0700868STATIC void copyRegInfo(CompilationUnit* cUnit, int newReg, int oldReg)
buzbee67bf8852011-08-17 17:51:35 -0700869{
870 RegisterInfo* newInfo = getRegInfo(cUnit, newReg);
871 RegisterInfo* oldInfo = getRegInfo(cUnit, oldReg);
buzbeeec5adf32011-09-11 15:25:43 -0700872 // Target temp status must not change
873 bool isTemp = newInfo->isTemp;
buzbee67bf8852011-08-17 17:51:35 -0700874 *newInfo = *oldInfo;
buzbeeec5adf32011-09-11 15:25:43 -0700875 // Restore target's temp status
876 newInfo->isTemp = isTemp;
buzbee67bf8852011-08-17 17:51:35 -0700877 newInfo->reg = newReg;
878}
879
880/*
881 * Return an updated location record with current in-register status.
882 * If the value lives in live temps, reflect that fact. No code
buzbeeb29e4d12011-09-26 15:05:48 -0700883 * is generated. If the live value is part of an older pair,
buzbee67bf8852011-08-17 17:51:35 -0700884 * clobber both low and high.
885 * TUNING: clobbering both is a bit heavy-handed, but the alternative
886 * is a bit complex when dealing with FP regs. Examine code to see
887 * if it's worthwhile trying to be more clever here.
888 */
889
890extern RegLocation oatUpdateLoc(CompilationUnit* cUnit, RegLocation loc)
891{
buzbeeed3e9302011-09-23 17:34:19 -0700892 DCHECK(!loc.wide);
buzbee6181f792011-09-29 11:14:04 -0700893 DCHECK(oatCheckCorePoolSanity(cUnit));
buzbee67bf8852011-08-17 17:51:35 -0700894 if (loc.location == kLocDalvikFrame) {
895 RegisterInfo* infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
896 if (infoLo) {
897 if (infoLo->pair) {
898 oatClobber(cUnit, infoLo->reg);
899 oatClobber(cUnit, infoLo->partner);
buzbee58f92742011-10-01 11:22:17 -0700900 oatFreeTemp(cUnit, infoLo->reg);
buzbee67bf8852011-08-17 17:51:35 -0700901 } else {
902 loc.lowReg = infoLo->reg;
903 loc.location = kLocPhysReg;
904 }
905 }
906 }
907
908 return loc;
909}
910
buzbee6181f792011-09-29 11:14:04 -0700911bool oatCheckCorePoolSanity(CompilationUnit* cUnit)
912{
913 for (static int i = 0; i < cUnit->regPool->numCoreRegs; i++) {
914 if (cUnit->regPool->coreRegs[i].pair) {
915 static int myReg = cUnit->regPool->coreRegs[i].reg;
916 static int mySreg = cUnit->regPool->coreRegs[i].sReg;
917 static int partnerReg = cUnit->regPool->coreRegs[i].partner;
918 static RegisterInfo* partner = getRegInfo(cUnit, partnerReg);
919 DCHECK(partner != NULL);
920 DCHECK(partner->pair);
921 DCHECK_EQ(myReg, partner->partner);
922 static int partnerSreg = partner->sReg;
923 if (mySreg == INVALID_SREG) {
924 DCHECK_EQ(partnerSreg, INVALID_SREG);
925 } else {
926 int diff = mySreg - partnerSreg;
927 DCHECK((diff == -1) || (diff == 1));
928 }
929 }
930 if (!cUnit->regPool->coreRegs[i].live) {
931 DCHECK(cUnit->regPool->coreRegs[i].defStart == NULL);
932 DCHECK(cUnit->regPool->coreRegs[i].defEnd == NULL);
933 }
934 }
935 return true;
936}
937
buzbee67bf8852011-08-17 17:51:35 -0700938/* see comments for updateLoc */
939extern RegLocation oatUpdateLocWide(CompilationUnit* cUnit,
940 RegLocation loc)
941{
buzbeeed3e9302011-09-23 17:34:19 -0700942 DCHECK(loc.wide);
buzbee6181f792011-09-29 11:14:04 -0700943 DCHECK(oatCheckCorePoolSanity(cUnit));
buzbee67bf8852011-08-17 17:51:35 -0700944 if (loc.location == kLocDalvikFrame) {
945 // Are the dalvik regs already live in physical registers?
946 RegisterInfo* infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
947 RegisterInfo* infoHi = allocLive(cUnit,
948 oatSRegHi(loc.sRegLow), kAnyReg);
949 bool match = true;
950 match = match && (infoLo != NULL);
951 match = match && (infoHi != NULL);
952 // Are they both core or both FP?
953 match = match && (FPREG(infoLo->reg) == FPREG(infoHi->reg));
954 // If a pair of floating point singles, are they properly aligned?
955 if (match && FPREG(infoLo->reg)) {
956 match &= ((infoLo->reg & 0x1) == 0);
957 match &= ((infoHi->reg - infoLo->reg) == 1);
958 }
959 // If previously used as a pair, it is the same pair?
960 if (match && (infoLo->pair || infoHi->pair)) {
961 match = (infoLo->pair == infoHi->pair);
962 match &= ((infoLo->reg == infoHi->partner) &&
963 (infoHi->reg == infoLo->partner));
964 }
965 if (match) {
966 // Can reuse - update the register usage info
967 loc.lowReg = infoLo->reg;
968 loc.highReg = infoHi->reg;
969 loc.location = kLocPhysReg;
970 oatMarkPair(cUnit, loc.lowReg, loc.highReg);
buzbeeed3e9302011-09-23 17:34:19 -0700971 DCHECK(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
buzbee67bf8852011-08-17 17:51:35 -0700972 return loc;
973 }
buzbee58f92742011-10-01 11:22:17 -0700974 // Can't easily reuse - clobber and free any overlaps
buzbee67bf8852011-08-17 17:51:35 -0700975 if (infoLo) {
976 oatClobber(cUnit, infoLo->reg);
buzbee58f92742011-10-01 11:22:17 -0700977 oatFreeTemp(cUnit, infoLo->reg);
buzbee67bf8852011-08-17 17:51:35 -0700978 if (infoLo->pair)
979 oatClobber(cUnit, infoLo->partner);
980 }
981 if (infoHi) {
982 oatClobber(cUnit, infoHi->reg);
buzbee58f92742011-10-01 11:22:17 -0700983 oatFreeTemp(cUnit, infoHi->reg);
buzbee67bf8852011-08-17 17:51:35 -0700984 if (infoHi->pair)
985 oatClobber(cUnit, infoHi->partner);
986 }
987 }
988 return loc;
989}
990
buzbeeed3e9302011-09-23 17:34:19 -0700991
992/* For use in cases we don't know (or care) width */
993extern RegLocation oatUpdateRawLoc(CompilationUnit* cUnit,
994 RegLocation loc)
995{
996 if (loc.wide)
997 return oatUpdateLocWide(cUnit, loc);
998 else
999 return oatUpdateLoc(cUnit, loc);
1000}
1001
1002STATIC RegLocation evalLocWide(CompilationUnit* cUnit, RegLocation loc,
buzbee67bf8852011-08-17 17:51:35 -07001003 int regClass, bool update)
1004{
buzbeeed3e9302011-09-23 17:34:19 -07001005 DCHECK(loc.wide);
buzbee67bf8852011-08-17 17:51:35 -07001006 int newRegs;
1007 int lowReg;
1008 int highReg;
1009
1010 loc = oatUpdateLocWide(cUnit, loc);
1011
1012 /* If already in registers, we can assume proper form. Right reg class? */
1013 if (loc.location == kLocPhysReg) {
buzbeeed3e9302011-09-23 17:34:19 -07001014 DCHECK_EQ(FPREG(loc.lowReg), FPREG(loc.highReg));
1015 DCHECK(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
buzbee67bf8852011-08-17 17:51:35 -07001016 if (!regClassMatches(regClass, loc.lowReg)) {
1017 /* Wrong register class. Reallocate and copy */
1018 newRegs = oatAllocTypedTempPair(cUnit, loc.fp, regClass);
1019 lowReg = newRegs & 0xff;
1020 highReg = (newRegs >> 8) & 0xff;
1021 oatRegCopyWide(cUnit, lowReg, highReg, loc.lowReg,
1022 loc.highReg);
1023 copyRegInfo(cUnit, lowReg, loc.lowReg);
1024 copyRegInfo(cUnit, highReg, loc.highReg);
1025 oatClobber(cUnit, loc.lowReg);
1026 oatClobber(cUnit, loc.highReg);
1027 loc.lowReg = lowReg;
1028 loc.highReg = highReg;
1029 oatMarkPair(cUnit, loc.lowReg, loc.highReg);
buzbeeed3e9302011-09-23 17:34:19 -07001030 DCHECK(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
buzbee67bf8852011-08-17 17:51:35 -07001031 }
1032 return loc;
1033 }
1034
buzbeeed3e9302011-09-23 17:34:19 -07001035 DCHECK_NE(loc.sRegLow, INVALID_SREG);
1036 DCHECK_NE(oatSRegHi(loc.sRegLow), INVALID_SREG);
buzbee67bf8852011-08-17 17:51:35 -07001037
1038 newRegs = oatAllocTypedTempPair(cUnit, loc.fp, regClass);
1039 loc.lowReg = newRegs & 0xff;
1040 loc.highReg = (newRegs >> 8) & 0xff;
1041
1042 oatMarkPair(cUnit, loc.lowReg, loc.highReg);
1043 if (update) {
1044 loc.location = kLocPhysReg;
1045 oatMarkLive(cUnit, loc.lowReg, loc.sRegLow);
1046 oatMarkLive(cUnit, loc.highReg, oatSRegHi(loc.sRegLow));
1047 }
buzbeeed3e9302011-09-23 17:34:19 -07001048 DCHECK(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
buzbee67bf8852011-08-17 17:51:35 -07001049 return loc;
1050}
1051
1052extern RegLocation oatEvalLoc(CompilationUnit* cUnit, RegLocation loc,
1053 int regClass, bool update)
1054{
1055 int newReg;
1056
1057 if (loc.wide)
1058 return evalLocWide(cUnit, loc, regClass, update);
1059
1060 loc = oatUpdateLoc(cUnit, loc);
1061
1062 if (loc.location == kLocPhysReg) {
1063 if (!regClassMatches(regClass, loc.lowReg)) {
1064 /* Wrong register class. Realloc, copy and transfer ownership */
1065 newReg = oatAllocTypedTemp(cUnit, loc.fp, regClass);
1066 oatRegCopy(cUnit, newReg, loc.lowReg);
1067 copyRegInfo(cUnit, newReg, loc.lowReg);
1068 oatClobber(cUnit, loc.lowReg);
1069 loc.lowReg = newReg;
1070 }
1071 return loc;
1072 }
1073
buzbeeed3e9302011-09-23 17:34:19 -07001074 DCHECK_NE(loc.sRegLow, INVALID_SREG);
buzbee67bf8852011-08-17 17:51:35 -07001075
1076 newReg = oatAllocTypedTemp(cUnit, loc.fp, regClass);
1077 loc.lowReg = newReg;
1078
1079 if (update) {
1080 loc.location = kLocPhysReg;
1081 oatMarkLive(cUnit, loc.lowReg, loc.sRegLow);
1082 }
1083 return loc;
1084}
1085
1086extern RegLocation oatGetDest(CompilationUnit* cUnit, MIR* mir, int num)
1087{
buzbeee9a72f62011-09-04 17:59:07 -07001088 RegLocation res = cUnit->regLocation[mir->ssaRep->defs[num]];
buzbeeed3e9302011-09-23 17:34:19 -07001089 DCHECK(!res.wide);
buzbeee9a72f62011-09-04 17:59:07 -07001090 return res;
buzbee67bf8852011-08-17 17:51:35 -07001091}
1092extern RegLocation oatGetSrc(CompilationUnit* cUnit, MIR* mir, int num)
1093{
buzbeee9a72f62011-09-04 17:59:07 -07001094 RegLocation res = cUnit->regLocation[mir->ssaRep->uses[num]];
buzbeeed3e9302011-09-23 17:34:19 -07001095 DCHECK(!res.wide);
buzbeee9a72f62011-09-04 17:59:07 -07001096 return res;
1097}
1098extern RegLocation oatGetRawSrc(CompilationUnit* cUnit, MIR* mir, int num)
1099{
1100 RegLocation res = cUnit->regLocation[mir->ssaRep->uses[num]];
1101 return res;
buzbee67bf8852011-08-17 17:51:35 -07001102}
1103extern RegLocation oatGetDestWide(CompilationUnit* cUnit, MIR* mir,
1104 int low, int high)
1105{
buzbeee9a72f62011-09-04 17:59:07 -07001106 RegLocation res = cUnit->regLocation[mir->ssaRep->defs[low]];
buzbeeed3e9302011-09-23 17:34:19 -07001107 DCHECK(res.wide);
buzbeee9a72f62011-09-04 17:59:07 -07001108 return res;
buzbee67bf8852011-08-17 17:51:35 -07001109}
1110
1111extern RegLocation oatGetSrcWide(CompilationUnit* cUnit, MIR* mir,
1112 int low, int high)
1113{
buzbeee9a72f62011-09-04 17:59:07 -07001114 RegLocation res = cUnit->regLocation[mir->ssaRep->uses[low]];
buzbeeed3e9302011-09-23 17:34:19 -07001115 DCHECK(res.wide);
buzbeee9a72f62011-09-04 17:59:07 -07001116 return res;
buzbee67bf8852011-08-17 17:51:35 -07001117}