blob: 9df80bd49b97f1b608c237a9586d0d0a4c831399 [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);
buzbee67bf8852011-08-17 17:51:35 -0700230 cUnit->numSpills++;
231 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/*
241 * Reserve a callee-save fp single register. Try to fullfill request for
242 * even/odd allocation, but go ahead and allocate anything if not
243 * available. If nothing's available, return -1.
244 */
buzbeeed3e9302011-09-23 17:34:19 -0700245STATIC int allocPreservedSingle(CompilationUnit* cUnit, int sReg, bool even)
buzbee67bf8852011-08-17 17:51:35 -0700246{
247 int res = -1;
248 RegisterInfo* FPRegs = cUnit->regPool->FPRegs;
249 for (int i = 0; i < cUnit->regPool->numFPRegs; i++) {
250 if (!FPRegs[i].isTemp && !FPRegs[i].inUse &&
251 ((FPRegs[i].reg & 0x1) == 0) == even) {
252 res = FPRegs[i].reg;
253 FPRegs[i].inUse = true;
254 cUnit->fpSpillMask |= (1 << (res & FP_REG_MASK));
buzbeec41e5b52011-09-23 12:46:19 -0700255 cUnit->fpVmapTable.push_back(sReg);
buzbee67bf8852011-08-17 17:51:35 -0700256 cUnit->numSpills++;
257 cUnit->numFPSpills++;
258 cUnit->regLocation[sReg].fpLocation = kLocPhysReg;
259 cUnit->regLocation[sReg].fpLowReg = res;
260 cUnit->regLocation[sReg].home = true;
261 break;
262 }
263 }
264 return res;
265}
266
267/*
268 * Somewhat messy code here. We want to allocate a pair of contiguous
269 * physical single-precision floating point registers starting with
270 * an even numbered reg. It is possible that the paired sReg (sReg+1)
271 * has already been allocated - try to fit if possible. Fail to
272 * allocate if we can't meet the requirements for the pair of
273 * sReg<=sX[even] & (sReg+1)<= sX+1.
274 */
buzbeeed3e9302011-09-23 17:34:19 -0700275STATIC int allocPreservedDouble(CompilationUnit* cUnit, int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700276{
277 int res = -1; // Assume failure
278 if (cUnit->regLocation[sReg+1].fpLocation == kLocPhysReg) {
279 // Upper reg is already allocated. Can we fit?
280 int highReg = cUnit->regLocation[sReg+1].fpLowReg;
281 if ((highReg & 1) == 0) {
282 // High reg is even - fail.
283 return res;
284 }
285 // Is the low reg of the pair free?
286 RegisterInfo* p = getRegInfo(cUnit, highReg-1);
287 if (p->inUse || p->isTemp) {
288 // Already allocated or not preserved - fail.
289 return res;
290 }
291 // OK - good to go.
292 res = p->reg;
293 p->inUse = true;
buzbeeed3e9302011-09-23 17:34:19 -0700294 DCHECK_EQ((res & 1), 0);
buzbee67bf8852011-08-17 17:51:35 -0700295 cUnit->fpSpillMask |= (1 << (res & FP_REG_MASK));
buzbee042946d2011-09-23 15:49:27 -0700296 cUnit->fpVmapTable.push_back(sReg);
buzbee67bf8852011-08-17 17:51:35 -0700297 cUnit->numSpills++;
298 cUnit->numFPSpills ++;
299 } else {
300 RegisterInfo* FPRegs = cUnit->regPool->FPRegs;
301 for (int i = 0; i < cUnit->regPool->numFPRegs; i++) {
302 if (!FPRegs[i].isTemp && !FPRegs[i].inUse &&
303 ((FPRegs[i].reg & 0x1) == 0x0) &&
304 !FPRegs[i+1].isTemp && !FPRegs[i+1].inUse &&
305 ((FPRegs[i+1].reg & 0x1) == 0x1) &&
306 (FPRegs[i].reg + 1) == FPRegs[i+1].reg) {
307 res = FPRegs[i].reg;
308 FPRegs[i].inUse = true;
309 cUnit->fpSpillMask |= (1 << (res & FP_REG_MASK));
buzbee042946d2011-09-23 15:49:27 -0700310 cUnit->fpVmapTable.push_back(sReg);
buzbee67bf8852011-08-17 17:51:35 -0700311 FPRegs[i+1].inUse = true;
312 cUnit->fpSpillMask |= (1 << ((res+1) & FP_REG_MASK));
buzbee042946d2011-09-23 15:49:27 -0700313 cUnit->fpVmapTable.push_back(sReg);
buzbee67bf8852011-08-17 17:51:35 -0700314 cUnit->numSpills += 2;
315 cUnit->numFPSpills += 2;
316 break;
317 }
318 }
319 }
320 if (res != -1) {
321 cUnit->regLocation[sReg].fpLocation = kLocPhysReg;
322 cUnit->regLocation[sReg].fpLowReg = res;
323 cUnit->regLocation[sReg].home = true;
324 cUnit->regLocation[sReg+1].fpLocation = kLocPhysReg;
325 cUnit->regLocation[sReg+1].fpLowReg = res + 1;
326 cUnit->regLocation[sReg+1].home = true;
327 }
328 return res;
329}
330
331
332/*
333 * Reserve a callee-save fp register. If this register can be used
334 * as the first of a double, attempt to allocate an even pair of fp
335 * single regs (but if can't still attempt to allocate a single, preferring
336 * first to allocate an odd register.
337 */
338extern int oatAllocPreservedFPReg(CompilationUnit* cUnit, int sReg,
339 bool doubleStart)
340{
341 int res = -1;
342 if (doubleStart) {
343 res = allocPreservedDouble(cUnit, sReg);
344 } else {
345 }
346 if (res == -1) {
347 res = allocPreservedSingle(cUnit, sReg, false /* try odd # */);
348 }
349 if (res == -1)
350 res = allocPreservedSingle(cUnit, sReg, true /* try even # */);
351 return res;
352}
353
buzbeeed3e9302011-09-23 17:34:19 -0700354STATIC int allocTempBody(CompilationUnit* cUnit, RegisterInfo* p, int numRegs,
buzbee67bf8852011-08-17 17:51:35 -0700355 int* nextTemp, bool required)
356{
357 int i;
358 int next = *nextTemp;
359 for (i=0; i< numRegs; i++) {
360 if (next >= numRegs)
361 next = 0;
362 if (p[next].isTemp && !p[next].inUse && !p[next].live) {
363 oatClobber(cUnit, p[next].reg);
364 p[next].inUse = true;
365 p[next].pair = false;
366 *nextTemp = next + 1;
367 return p[next].reg;
368 }
369 next++;
370 }
371 next = *nextTemp;
372 for (i=0; i< numRegs; i++) {
373 if (next >= numRegs)
374 next = 0;
375 if (p[next].isTemp && !p[next].inUse) {
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 if (required) {
buzbee6181f792011-09-29 11:14:04 -0700385 oatCodegenDump(cUnit);
buzbee67bf8852011-08-17 17:51:35 -0700386 dumpRegPool(cUnit->regPool->coreRegs,
387 cUnit->regPool->numCoreRegs);
388 LOG(FATAL) << "No free temp registers";
389 }
390 return -1; // No register available
391}
392
393//REDO: too many assumptions.
394extern int oatAllocTempDouble(CompilationUnit* cUnit)
395{
396 RegisterInfo* p = cUnit->regPool->FPRegs;
397 int numRegs = cUnit->regPool->numFPRegs;
398 int next = cUnit->regPool->nextFPReg;
399 int i;
400
401 for (i=0; i < numRegs; i+=2) {
402 /* Cleanup - not all targets need aligned regs */
403 if (next & 1)
404 next++;
405 if (next >= numRegs)
406 next = 0;
407 if ((p[next].isTemp && !p[next].inUse && !p[next].live) &&
408 (p[next+1].isTemp && !p[next+1].inUse && !p[next+1].live)) {
409 oatClobber(cUnit, p[next].reg);
410 oatClobber(cUnit, p[next+1].reg);
411 p[next].inUse = true;
412 p[next+1].inUse = true;
buzbeeed3e9302011-09-23 17:34:19 -0700413 DCHECK_EQ((p[next].reg+1), p[next+1].reg);
414 DCHECK_EQ((p[next].reg & 0x1), 0);
buzbee67bf8852011-08-17 17:51:35 -0700415 cUnit->regPool->nextFPReg += 2;
416 return p[next].reg;
417 }
418 next += 2;
419 }
420 next = cUnit->regPool->nextFPReg;
421 for (i=0; i < numRegs; i+=2) {
422 if (next >= numRegs)
423 next = 0;
424 if (p[next].isTemp && !p[next].inUse && p[next+1].isTemp &&
425 !p[next+1].inUse) {
426 oatClobber(cUnit, p[next].reg);
427 oatClobber(cUnit, p[next+1].reg);
428 p[next].inUse = true;
429 p[next+1].inUse = true;
buzbeeed3e9302011-09-23 17:34:19 -0700430 DCHECK_EQ((p[next].reg+1), p[next+1].reg);
431 DCHECK_EQ((p[next].reg & 0x1), 0);
buzbee67bf8852011-08-17 17:51:35 -0700432 cUnit->regPool->nextFPReg += 2;
433 return p[next].reg;
434 }
435 next += 2;
436 }
buzbee6181f792011-09-29 11:14:04 -0700437 LOG(FATAL) << "No free temp registers (pair)";
buzbee67bf8852011-08-17 17:51:35 -0700438 return -1;
439}
440
441/* Return a temp if one is available, -1 otherwise */
442extern int oatAllocFreeTemp(CompilationUnit* cUnit)
443{
444 return allocTempBody(cUnit, cUnit->regPool->coreRegs,
445 cUnit->regPool->numCoreRegs,
446 &cUnit->regPool->nextCoreReg, true);
447}
448
449extern int oatAllocTemp(CompilationUnit* cUnit)
450{
451 return allocTempBody(cUnit, cUnit->regPool->coreRegs,
452 cUnit->regPool->numCoreRegs,
453 &cUnit->regPool->nextCoreReg, true);
454}
455
456extern int oatAllocTempFloat(CompilationUnit* cUnit)
457{
458 return allocTempBody(cUnit, cUnit->regPool->FPRegs,
459 cUnit->regPool->numFPRegs,
460 &cUnit->regPool->nextFPReg, true);
461}
462
buzbeeed3e9302011-09-23 17:34:19 -0700463STATIC RegisterInfo* allocLiveBody(RegisterInfo* p, int numRegs, int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700464{
465 int i;
466 if (sReg == -1)
467 return NULL;
468 for (i=0; i < numRegs; i++) {
469 if (p[i].live && (p[i].sReg == sReg)) {
470 if (p[i].isTemp)
471 p[i].inUse = true;
472 return &p[i];
473 }
474 }
475 return NULL;
476}
477
buzbeeed3e9302011-09-23 17:34:19 -0700478STATIC RegisterInfo* allocLive(CompilationUnit* cUnit, int sReg,
buzbee67bf8852011-08-17 17:51:35 -0700479 int regClass)
480{
481 RegisterInfo* res = NULL;
482 switch(regClass) {
483 case kAnyReg:
484 res = allocLiveBody(cUnit->regPool->FPRegs,
485 cUnit->regPool->numFPRegs, sReg);
486 if (res)
487 break;
488 /* Intentional fallthrough */
489 case kCoreReg:
490 res = allocLiveBody(cUnit->regPool->coreRegs,
491 cUnit->regPool->numCoreRegs, sReg);
492 break;
493 case kFPReg:
494 res = allocLiveBody(cUnit->regPool->FPRegs,
495 cUnit->regPool->numFPRegs, sReg);
496 break;
497 default:
498 LOG(FATAL) << "Invalid register type";
499 }
500 return res;
501}
502
503extern void oatFreeTemp(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 if (p[i].isTemp) {
511 p[i].inUse = false;
512 }
513 p[i].pair = false;
514 return;
515 }
516 }
517 p = cUnit->regPool->FPRegs;
518 numRegs = cUnit->regPool->numFPRegs;
519 for (i=0; i< numRegs; i++) {
520 if (p[i].reg == reg) {
521 if (p[i].isTemp) {
522 p[i].inUse = false;
523 }
524 p[i].pair = false;
525 return;
526 }
527 }
528 LOG(FATAL) << "Tried to free a non-existant temp: r" << reg;
529}
530
531extern RegisterInfo* oatIsLive(CompilationUnit* cUnit, int reg)
532{
533 RegisterInfo* p = cUnit->regPool->coreRegs;
534 int numRegs = cUnit->regPool->numCoreRegs;
535 int i;
536 for (i=0; i< numRegs; i++) {
537 if (p[i].reg == reg) {
538 return p[i].live ? &p[i] : NULL;
539 }
540 }
541 p = cUnit->regPool->FPRegs;
542 numRegs = cUnit->regPool->numFPRegs;
543 for (i=0; i< numRegs; i++) {
544 if (p[i].reg == reg) {
545 return p[i].live ? &p[i] : NULL;
546 }
547 }
548 return NULL;
549}
550
551extern RegisterInfo* oatIsTemp(CompilationUnit* cUnit, int reg)
552{
553 RegisterInfo* p = getRegInfo(cUnit, reg);
554 return (p->isTemp) ? p : NULL;
555}
556
buzbeeb29e4d12011-09-26 15:05:48 -0700557extern RegisterInfo* oatIsPromoted(CompilationUnit* cUnit, int reg)
558{
559 RegisterInfo* p = getRegInfo(cUnit, reg);
560 return (p->isTemp) ? NULL : p;
561}
562
buzbee67bf8852011-08-17 17:51:35 -0700563extern bool oatIsDirty(CompilationUnit* cUnit, int reg)
564{
565 RegisterInfo* p = getRegInfo(cUnit, reg);
566 return p->dirty;
567}
568
569/*
570 * Similar to oatAllocTemp(), but forces the allocation of a specific
571 * register. No check is made to see if the register was previously
572 * allocated. Use with caution.
573 */
574extern void oatLockTemp(CompilationUnit* cUnit, int reg)
575{
576 RegisterInfo* p = cUnit->regPool->coreRegs;
577 int numRegs = cUnit->regPool->numCoreRegs;
578 int i;
579 for (i=0; i< numRegs; i++) {
580 if (p[i].reg == reg) {
buzbeeed3e9302011-09-23 17:34:19 -0700581 DCHECK(p[i].isTemp);
buzbee67bf8852011-08-17 17:51:35 -0700582 p[i].inUse = true;
583 p[i].live = false;
584 return;
585 }
586 }
587 p = cUnit->regPool->FPRegs;
588 numRegs = cUnit->regPool->numFPRegs;
589 for (i=0; i< numRegs; i++) {
590 if (p[i].reg == reg) {
buzbeeed3e9302011-09-23 17:34:19 -0700591 DCHECK(p[i].isTemp);
buzbee67bf8852011-08-17 17:51:35 -0700592 p[i].inUse = true;
593 p[i].live = false;
594 return;
595 }
596 }
597 LOG(FATAL) << "Tried to lock a non-existant temp: r" << reg;
598}
599
600extern void oatResetDef(CompilationUnit* cUnit, int reg)
601{
602 RegisterInfo* p = getRegInfo(cUnit, reg);
603 p->defStart = NULL;
604 p->defEnd = NULL;
605}
606
buzbeeed3e9302011-09-23 17:34:19 -0700607STATIC void nullifyRange(CompilationUnit* cUnit, LIR *start, LIR *finish,
buzbee67bf8852011-08-17 17:51:35 -0700608 int sReg1, int sReg2)
609{
610 if (start && finish) {
611 LIR *p;
buzbeeed3e9302011-09-23 17:34:19 -0700612 DCHECK_EQ(sReg1, sReg2);
buzbee67bf8852011-08-17 17:51:35 -0700613 for (p = start; ;p = p->next) {
614 ((ArmLIR *)p)->flags.isNop = true;
buzbee6181f792011-09-29 11:14:04 -0700615 ((ArmLIR *)p)->flags.squashed = true;
buzbee67bf8852011-08-17 17:51:35 -0700616 if (p == finish)
617 break;
618 }
619 }
620}
621
622/*
623 * Mark the beginning and end LIR of a def sequence. Note that
624 * on entry start points to the LIR prior to the beginning of the
625 * sequence.
626 */
627extern void oatMarkDef(CompilationUnit* cUnit, RegLocation rl,
628 LIR *start, LIR *finish)
629{
buzbeeed3e9302011-09-23 17:34:19 -0700630 DCHECK(!rl.wide);
631 DCHECK(start && start->next);
632 DCHECK(finish);
buzbee67bf8852011-08-17 17:51:35 -0700633 RegisterInfo* p = getRegInfo(cUnit, rl.lowReg);
634 p->defStart = start->next;
635 p->defEnd = finish;
636}
637
638/*
639 * Mark the beginning and end LIR of a def sequence. Note that
640 * on entry start points to the LIR prior to the beginning of the
641 * sequence.
642 */
643extern void oatMarkDefWide(CompilationUnit* cUnit, RegLocation rl,
644 LIR *start, LIR *finish)
645{
buzbeeed3e9302011-09-23 17:34:19 -0700646 DCHECK(rl.wide);
647 DCHECK(start && start->next);
648 DCHECK(finish);
buzbee67bf8852011-08-17 17:51:35 -0700649 RegisterInfo* p = getRegInfo(cUnit, rl.lowReg);
650 oatResetDef(cUnit, rl.highReg); // Only track low of pair
651 p->defStart = start->next;
652 p->defEnd = finish;
653}
654
655extern RegLocation oatWideToNarrow(CompilationUnit* cUnit,
656 RegLocation rl)
657{
buzbeeed3e9302011-09-23 17:34:19 -0700658 DCHECK(rl.wide);
buzbee67bf8852011-08-17 17:51:35 -0700659 if (rl.location == kLocPhysReg) {
660 RegisterInfo* infoLo = getRegInfo(cUnit, rl.lowReg);
661 RegisterInfo* infoHi = getRegInfo(cUnit, rl.highReg);
buzbee0c7f26d2011-09-07 12:28:51 -0700662 if (infoLo->isTemp) {
663 infoLo->pair = false;
664 infoLo->defStart = NULL;
665 infoLo->defEnd = NULL;
buzbee67bf8852011-08-17 17:51:35 -0700666 }
buzbee0c7f26d2011-09-07 12:28:51 -0700667 if (infoHi->isTemp) {
668 infoHi->pair = false;
669 infoHi->defStart = NULL;
670 infoHi->defEnd = NULL;
buzbee67bf8852011-08-17 17:51:35 -0700671 }
buzbee67bf8852011-08-17 17:51:35 -0700672 }
673 rl.wide = false;
674 return rl;
675}
676
677extern void oatResetDefLoc(CompilationUnit* cUnit, RegLocation rl)
678{
buzbeeed3e9302011-09-23 17:34:19 -0700679 DCHECK(!rl.wide);
buzbee6181f792011-09-29 11:14:04 -0700680 RegisterInfo* p = oatIsTemp(cUnit, rl.lowReg);
681 if (p && !(cUnit->disableOpt & (1 << kSuppressLoads))) {
buzbeeed3e9302011-09-23 17:34:19 -0700682 DCHECK(!p->pair);
buzbee67bf8852011-08-17 17:51:35 -0700683 nullifyRange(cUnit, p->defStart, p->defEnd,
684 p->sReg, rl.sRegLow);
685 }
686 oatResetDef(cUnit, rl.lowReg);
687}
688
689extern void oatResetDefLocWide(CompilationUnit* cUnit, RegLocation rl)
690{
buzbeeed3e9302011-09-23 17:34:19 -0700691 DCHECK(rl.wide);
buzbee6181f792011-09-29 11:14:04 -0700692 RegisterInfo* pLow = oatIsTemp(cUnit, rl.lowReg);
693 RegisterInfo* pHigh = oatIsTemp(cUnit, rl.highReg);
694 if (pLow && !(cUnit->disableOpt & (1 << kSuppressLoads))) {
695 DCHECK(pLow->pair);
696 nullifyRange(cUnit, pLow->defStart, pLow->defEnd,
697 pLow->sReg, rl.sRegLow);
698 }
699 if (pHigh && !(cUnit->disableOpt & (1 << kSuppressLoads))) {
700 DCHECK(pHigh->pair);
buzbee67bf8852011-08-17 17:51:35 -0700701 }
702 oatResetDef(cUnit, rl.lowReg);
703 oatResetDef(cUnit, rl.highReg);
704}
705
706extern void oatResetDefTracking(CompilationUnit* cUnit)
707{
708 int i;
709 for (i=0; i< cUnit->regPool->numCoreRegs; i++) {
710 oatResetDef(cUnit, cUnit->regPool->coreRegs[i].reg);
711 }
712 for (i=0; i< cUnit->regPool->numFPRegs; i++) {
713 oatResetDef(cUnit, cUnit->regPool->FPRegs[i].reg);
714 }
715}
716
717extern void oatClobberAllRegs(CompilationUnit* cUnit)
718{
719 int i;
720 for (i=0; i< cUnit->regPool->numCoreRegs; i++) {
721 oatClobber(cUnit, cUnit->regPool->coreRegs[i].reg);
722 }
723 for (i=0; i< cUnit->regPool->numFPRegs; i++) {
724 oatClobber(cUnit, cUnit->regPool->FPRegs[i].reg);
725 }
726}
727
728/* To be used when explicitly managing register use */
buzbee2e748f32011-08-29 21:02:19 -0700729extern void oatLockCallTemps(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700730{
buzbee2e748f32011-08-29 21:02:19 -0700731 //TODO: Arm specific - move to target dependent code
732 oatLockTemp(cUnit, r0);
733 oatLockTemp(cUnit, r1);
734 oatLockTemp(cUnit, r2);
735 oatLockTemp(cUnit, r3);
buzbee67bf8852011-08-17 17:51:35 -0700736}
737
buzbee0d966cf2011-09-08 17:34:58 -0700738/* To be used when explicitly managing register use */
739extern void oatFreeCallTemps(CompilationUnit* cUnit)
740{
741 //TODO: Arm specific - move to target dependent code
742 oatFreeTemp(cUnit, r0);
743 oatFreeTemp(cUnit, r1);
744 oatFreeTemp(cUnit, r2);
745 oatFreeTemp(cUnit, r3);
746}
747
buzbee67bf8852011-08-17 17:51:35 -0700748// Make sure nothing is live and dirty
buzbeeed3e9302011-09-23 17:34:19 -0700749STATIC void flushAllRegsBody(CompilationUnit* cUnit, RegisterInfo* info,
buzbee67bf8852011-08-17 17:51:35 -0700750 int numRegs)
751{
752 int i;
753 for (i=0; i < numRegs; i++) {
754 if (info[i].live && info[i].dirty) {
755 if (info[i].pair) {
756 oatFlushRegWide(cUnit, info[i].reg, info[i].partner);
757 } else {
758 oatFlushReg(cUnit, info[i].reg);
759 }
760 }
761 }
762}
763
764extern void oatFlushAllRegs(CompilationUnit* cUnit)
765{
766 flushAllRegsBody(cUnit, cUnit->regPool->coreRegs,
767 cUnit->regPool->numCoreRegs);
768 flushAllRegsBody(cUnit, cUnit->regPool->FPRegs,
769 cUnit->regPool->numFPRegs);
770 oatClobberAllRegs(cUnit);
771}
772
773
774//TUNING: rewrite all of this reg stuff. Probably use an attribute table
buzbeeed3e9302011-09-23 17:34:19 -0700775STATIC bool regClassMatches(int regClass, int reg)
buzbee67bf8852011-08-17 17:51:35 -0700776{
777 if (regClass == kAnyReg) {
778 return true;
779 } else if (regClass == kCoreReg) {
780 return !FPREG(reg);
781 } else {
782 return FPREG(reg);
783 }
784}
785
786extern void oatMarkLive(CompilationUnit* cUnit, int reg, int sReg)
787{
788 RegisterInfo* info = getRegInfo(cUnit, reg);
789 if ((info->reg == reg) && (info->sReg == sReg) && info->live) {
790 return; /* already live */
791 } else if (sReg != INVALID_SREG) {
792 oatClobberSReg(cUnit, sReg);
793 if (info->isTemp) {
794 info->live = true;
795 }
796 } else {
797 /* Can't be live if no associated sReg */
buzbeeed3e9302011-09-23 17:34:19 -0700798 DCHECK(info->isTemp);
buzbee67bf8852011-08-17 17:51:35 -0700799 info->live = false;
800 }
801 info->sReg = sReg;
802}
803
804extern void oatMarkTemp(CompilationUnit* cUnit, int reg)
805{
806 RegisterInfo* info = getRegInfo(cUnit, reg);
807 info->isTemp = true;
808}
809
buzbee9e0f9b02011-08-24 15:32:46 -0700810extern void oatUnmarkTemp(CompilationUnit* cUnit, int reg)
811{
812 RegisterInfo* info = getRegInfo(cUnit, reg);
813 info->isTemp = false;
814}
815
buzbee67bf8852011-08-17 17:51:35 -0700816extern void oatMarkPair(CompilationUnit* cUnit, int lowReg, int highReg)
817{
818 RegisterInfo* infoLo = getRegInfo(cUnit, lowReg);
819 RegisterInfo* infoHi = getRegInfo(cUnit, highReg);
820 infoLo->pair = infoHi->pair = true;
821 infoLo->partner = highReg;
822 infoHi->partner = lowReg;
823}
824
825extern void oatMarkClean(CompilationUnit* cUnit, RegLocation loc)
826{
827 RegisterInfo* info = getRegInfo(cUnit, loc.lowReg);
828 info->dirty = false;
829 if (loc.wide) {
830 info = getRegInfo(cUnit, loc.highReg);
831 info->dirty = false;
832 }
833}
834
835extern void oatMarkDirty(CompilationUnit* cUnit, RegLocation loc)
836{
837 if (loc.home) {
838 // If already home, can't be dirty
839 return;
840 }
841 RegisterInfo* info = getRegInfo(cUnit, loc.lowReg);
842 info->dirty = true;
843 if (loc.wide) {
844 info = getRegInfo(cUnit, loc.highReg);
845 info->dirty = true;
846 }
847}
848
849extern void oatMarkInUse(CompilationUnit* cUnit, int reg)
850{
851 RegisterInfo* info = getRegInfo(cUnit, reg);
852 info->inUse = true;
853}
854
buzbeeed3e9302011-09-23 17:34:19 -0700855STATIC void copyRegInfo(CompilationUnit* cUnit, int newReg, int oldReg)
buzbee67bf8852011-08-17 17:51:35 -0700856{
857 RegisterInfo* newInfo = getRegInfo(cUnit, newReg);
858 RegisterInfo* oldInfo = getRegInfo(cUnit, oldReg);
buzbeeec5adf32011-09-11 15:25:43 -0700859 // Target temp status must not change
860 bool isTemp = newInfo->isTemp;
buzbee67bf8852011-08-17 17:51:35 -0700861 *newInfo = *oldInfo;
buzbeeec5adf32011-09-11 15:25:43 -0700862 // Restore target's temp status
863 newInfo->isTemp = isTemp;
buzbee67bf8852011-08-17 17:51:35 -0700864 newInfo->reg = newReg;
865}
866
867/*
868 * Return an updated location record with current in-register status.
869 * If the value lives in live temps, reflect that fact. No code
buzbeeb29e4d12011-09-26 15:05:48 -0700870 * is generated. If the live value is part of an older pair,
buzbee67bf8852011-08-17 17:51:35 -0700871 * clobber both low and high.
872 * TUNING: clobbering both is a bit heavy-handed, but the alternative
873 * is a bit complex when dealing with FP regs. Examine code to see
874 * if it's worthwhile trying to be more clever here.
875 */
876
877extern RegLocation oatUpdateLoc(CompilationUnit* cUnit, RegLocation loc)
878{
buzbeeed3e9302011-09-23 17:34:19 -0700879 DCHECK(!loc.wide);
buzbee6181f792011-09-29 11:14:04 -0700880 DCHECK(oatCheckCorePoolSanity(cUnit));
buzbee67bf8852011-08-17 17:51:35 -0700881 if (loc.location == kLocDalvikFrame) {
882 RegisterInfo* infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
883 if (infoLo) {
884 if (infoLo->pair) {
885 oatClobber(cUnit, infoLo->reg);
886 oatClobber(cUnit, infoLo->partner);
buzbee58f92742011-10-01 11:22:17 -0700887 oatFreeTemp(cUnit, infoLo->reg);
buzbee67bf8852011-08-17 17:51:35 -0700888 } else {
889 loc.lowReg = infoLo->reg;
890 loc.location = kLocPhysReg;
891 }
892 }
893 }
894
895 return loc;
896}
897
buzbee6181f792011-09-29 11:14:04 -0700898bool oatCheckCorePoolSanity(CompilationUnit* cUnit)
899{
900 for (static int i = 0; i < cUnit->regPool->numCoreRegs; i++) {
901 if (cUnit->regPool->coreRegs[i].pair) {
902 static int myReg = cUnit->regPool->coreRegs[i].reg;
903 static int mySreg = cUnit->regPool->coreRegs[i].sReg;
904 static int partnerReg = cUnit->regPool->coreRegs[i].partner;
905 static RegisterInfo* partner = getRegInfo(cUnit, partnerReg);
906 DCHECK(partner != NULL);
907 DCHECK(partner->pair);
908 DCHECK_EQ(myReg, partner->partner);
909 static int partnerSreg = partner->sReg;
910 if (mySreg == INVALID_SREG) {
911 DCHECK_EQ(partnerSreg, INVALID_SREG);
912 } else {
913 int diff = mySreg - partnerSreg;
914 DCHECK((diff == -1) || (diff == 1));
915 }
916 }
917 if (!cUnit->regPool->coreRegs[i].live) {
918 DCHECK(cUnit->regPool->coreRegs[i].defStart == NULL);
919 DCHECK(cUnit->regPool->coreRegs[i].defEnd == NULL);
920 }
921 }
922 return true;
923}
924
buzbee67bf8852011-08-17 17:51:35 -0700925/* see comments for updateLoc */
926extern RegLocation oatUpdateLocWide(CompilationUnit* cUnit,
927 RegLocation loc)
928{
buzbeeed3e9302011-09-23 17:34:19 -0700929 DCHECK(loc.wide);
buzbee6181f792011-09-29 11:14:04 -0700930 DCHECK(oatCheckCorePoolSanity(cUnit));
buzbee67bf8852011-08-17 17:51:35 -0700931 if (loc.location == kLocDalvikFrame) {
932 // Are the dalvik regs already live in physical registers?
933 RegisterInfo* infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
934 RegisterInfo* infoHi = allocLive(cUnit,
935 oatSRegHi(loc.sRegLow), kAnyReg);
936 bool match = true;
937 match = match && (infoLo != NULL);
938 match = match && (infoHi != NULL);
939 // Are they both core or both FP?
940 match = match && (FPREG(infoLo->reg) == FPREG(infoHi->reg));
941 // If a pair of floating point singles, are they properly aligned?
942 if (match && FPREG(infoLo->reg)) {
943 match &= ((infoLo->reg & 0x1) == 0);
944 match &= ((infoHi->reg - infoLo->reg) == 1);
945 }
946 // If previously used as a pair, it is the same pair?
947 if (match && (infoLo->pair || infoHi->pair)) {
948 match = (infoLo->pair == infoHi->pair);
949 match &= ((infoLo->reg == infoHi->partner) &&
950 (infoHi->reg == infoLo->partner));
951 }
952 if (match) {
953 // Can reuse - update the register usage info
954 loc.lowReg = infoLo->reg;
955 loc.highReg = infoHi->reg;
956 loc.location = kLocPhysReg;
957 oatMarkPair(cUnit, loc.lowReg, loc.highReg);
buzbeeed3e9302011-09-23 17:34:19 -0700958 DCHECK(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
buzbee67bf8852011-08-17 17:51:35 -0700959 return loc;
960 }
buzbee58f92742011-10-01 11:22:17 -0700961 // Can't easily reuse - clobber and free any overlaps
buzbee67bf8852011-08-17 17:51:35 -0700962 if (infoLo) {
963 oatClobber(cUnit, infoLo->reg);
buzbee58f92742011-10-01 11:22:17 -0700964 oatFreeTemp(cUnit, infoLo->reg);
buzbee67bf8852011-08-17 17:51:35 -0700965 if (infoLo->pair)
966 oatClobber(cUnit, infoLo->partner);
967 }
968 if (infoHi) {
969 oatClobber(cUnit, infoHi->reg);
buzbee58f92742011-10-01 11:22:17 -0700970 oatFreeTemp(cUnit, infoHi->reg);
buzbee67bf8852011-08-17 17:51:35 -0700971 if (infoHi->pair)
972 oatClobber(cUnit, infoHi->partner);
973 }
974 }
975 return loc;
976}
977
buzbeeed3e9302011-09-23 17:34:19 -0700978
979/* For use in cases we don't know (or care) width */
980extern RegLocation oatUpdateRawLoc(CompilationUnit* cUnit,
981 RegLocation loc)
982{
983 if (loc.wide)
984 return oatUpdateLocWide(cUnit, loc);
985 else
986 return oatUpdateLoc(cUnit, loc);
987}
988
989STATIC RegLocation evalLocWide(CompilationUnit* cUnit, RegLocation loc,
buzbee67bf8852011-08-17 17:51:35 -0700990 int regClass, bool update)
991{
buzbeeed3e9302011-09-23 17:34:19 -0700992 DCHECK(loc.wide);
buzbee67bf8852011-08-17 17:51:35 -0700993 int newRegs;
994 int lowReg;
995 int highReg;
996
997 loc = oatUpdateLocWide(cUnit, loc);
998
999 /* If already in registers, we can assume proper form. Right reg class? */
1000 if (loc.location == kLocPhysReg) {
buzbeeed3e9302011-09-23 17:34:19 -07001001 DCHECK_EQ(FPREG(loc.lowReg), FPREG(loc.highReg));
1002 DCHECK(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
buzbee67bf8852011-08-17 17:51:35 -07001003 if (!regClassMatches(regClass, loc.lowReg)) {
1004 /* Wrong register class. Reallocate and copy */
1005 newRegs = oatAllocTypedTempPair(cUnit, loc.fp, regClass);
1006 lowReg = newRegs & 0xff;
1007 highReg = (newRegs >> 8) & 0xff;
1008 oatRegCopyWide(cUnit, lowReg, highReg, loc.lowReg,
1009 loc.highReg);
1010 copyRegInfo(cUnit, lowReg, loc.lowReg);
1011 copyRegInfo(cUnit, highReg, loc.highReg);
1012 oatClobber(cUnit, loc.lowReg);
1013 oatClobber(cUnit, loc.highReg);
1014 loc.lowReg = lowReg;
1015 loc.highReg = highReg;
1016 oatMarkPair(cUnit, loc.lowReg, loc.highReg);
buzbeeed3e9302011-09-23 17:34:19 -07001017 DCHECK(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
buzbee67bf8852011-08-17 17:51:35 -07001018 }
1019 return loc;
1020 }
1021
buzbeeed3e9302011-09-23 17:34:19 -07001022 DCHECK_NE(loc.sRegLow, INVALID_SREG);
1023 DCHECK_NE(oatSRegHi(loc.sRegLow), INVALID_SREG);
buzbee67bf8852011-08-17 17:51:35 -07001024
1025 newRegs = oatAllocTypedTempPair(cUnit, loc.fp, regClass);
1026 loc.lowReg = newRegs & 0xff;
1027 loc.highReg = (newRegs >> 8) & 0xff;
1028
1029 oatMarkPair(cUnit, loc.lowReg, loc.highReg);
1030 if (update) {
1031 loc.location = kLocPhysReg;
1032 oatMarkLive(cUnit, loc.lowReg, loc.sRegLow);
1033 oatMarkLive(cUnit, loc.highReg, oatSRegHi(loc.sRegLow));
1034 }
buzbeeed3e9302011-09-23 17:34:19 -07001035 DCHECK(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
buzbee67bf8852011-08-17 17:51:35 -07001036 return loc;
1037}
1038
1039extern RegLocation oatEvalLoc(CompilationUnit* cUnit, RegLocation loc,
1040 int regClass, bool update)
1041{
1042 int newReg;
1043
1044 if (loc.wide)
1045 return evalLocWide(cUnit, loc, regClass, update);
1046
1047 loc = oatUpdateLoc(cUnit, loc);
1048
1049 if (loc.location == kLocPhysReg) {
1050 if (!regClassMatches(regClass, loc.lowReg)) {
1051 /* Wrong register class. Realloc, copy and transfer ownership */
1052 newReg = oatAllocTypedTemp(cUnit, loc.fp, regClass);
1053 oatRegCopy(cUnit, newReg, loc.lowReg);
1054 copyRegInfo(cUnit, newReg, loc.lowReg);
1055 oatClobber(cUnit, loc.lowReg);
1056 loc.lowReg = newReg;
1057 }
1058 return loc;
1059 }
1060
buzbeeed3e9302011-09-23 17:34:19 -07001061 DCHECK_NE(loc.sRegLow, INVALID_SREG);
buzbee67bf8852011-08-17 17:51:35 -07001062
1063 newReg = oatAllocTypedTemp(cUnit, loc.fp, regClass);
1064 loc.lowReg = newReg;
1065
1066 if (update) {
1067 loc.location = kLocPhysReg;
1068 oatMarkLive(cUnit, loc.lowReg, loc.sRegLow);
1069 }
1070 return loc;
1071}
1072
1073extern RegLocation oatGetDest(CompilationUnit* cUnit, MIR* mir, int num)
1074{
buzbeee9a72f62011-09-04 17:59:07 -07001075 RegLocation res = cUnit->regLocation[mir->ssaRep->defs[num]];
buzbeeed3e9302011-09-23 17:34:19 -07001076 DCHECK(!res.wide);
buzbeee9a72f62011-09-04 17:59:07 -07001077 return res;
buzbee67bf8852011-08-17 17:51:35 -07001078}
1079extern RegLocation oatGetSrc(CompilationUnit* cUnit, MIR* mir, int num)
1080{
buzbeee9a72f62011-09-04 17:59:07 -07001081 RegLocation res = cUnit->regLocation[mir->ssaRep->uses[num]];
buzbeeed3e9302011-09-23 17:34:19 -07001082 DCHECK(!res.wide);
buzbeee9a72f62011-09-04 17:59:07 -07001083 return res;
1084}
1085extern RegLocation oatGetRawSrc(CompilationUnit* cUnit, MIR* mir, int num)
1086{
1087 RegLocation res = cUnit->regLocation[mir->ssaRep->uses[num]];
1088 return res;
buzbee67bf8852011-08-17 17:51:35 -07001089}
1090extern RegLocation oatGetDestWide(CompilationUnit* cUnit, MIR* mir,
1091 int low, int high)
1092{
buzbeee9a72f62011-09-04 17:59:07 -07001093 RegLocation res = cUnit->regLocation[mir->ssaRep->defs[low]];
buzbeeed3e9302011-09-23 17:34:19 -07001094 DCHECK(res.wide);
buzbeee9a72f62011-09-04 17:59:07 -07001095 return res;
buzbee67bf8852011-08-17 17:51:35 -07001096}
1097
1098extern RegLocation oatGetSrcWide(CompilationUnit* cUnit, MIR* mir,
1099 int low, int high)
1100{
buzbeee9a72f62011-09-04 17:59:07 -07001101 RegLocation res = cUnit->regLocation[mir->ssaRep->uses[low]];
buzbeeed3e9302011-09-23 17:34:19 -07001102 DCHECK(res.wide);
buzbeee9a72f62011-09-04 17:59:07 -07001103 return res;
buzbee67bf8852011-08-17 17:51:35 -07001104}