blob: 9035f93c75a2ad4c19d94305ff0c955451a6fcec [file] [log] [blame]
Bill Buzbee1465db52009-09-23 17:17:35 -07001/*
2 * Copyright (C) 2009 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
Ben Cheng5d90c202009-11-22 23:31:11 -080025#include "compiler/CompilerUtility.h"
26#include "compiler/CompilerIR.h"
27#include "compiler/Dataflow.h"
28#include "ArmLIR.h"
Bill Buzbee1465db52009-09-23 17:17:35 -070029#include "Codegen.h"
Ben Cheng5d90c202009-11-22 23:31:11 -080030#include "Ralloc.h"
31
32/*
Bill Buzbee1465db52009-09-23 17:17:35 -070033 * Register usage for 16-bit Thumb systems:
34 * r0-r3: Temp/argument
35 * lr(r14): Temp for translations, return address for handlers
36 * rGLUE(r6): Pointer to InterpState
37 * rFP(r5): Dalvik frame pointer
38 * r4, r7: Temp for translations
39 * r8, r9, r10: Temp preserved across C calls
40 * r11, ip(r12): Temp not preserved across C calls
41 *
42 * Register usage for 32-bit Thumb systems:
43 * r0-r3: Temp/argument
44 * lr(r14): Temp for translations, return address for handlers
45 * rGLUE(r6): Pointer to InterpState
46 * rFP(r5): Dalvik frame pointer
47 * r4, r7: Temp for translations
48 * r8, r9, r10 Temp preserved across C calls
49 * r11, ip(r12): Temp not preserved across C calls
50 * fp0-fp15: Hot temps, not preserved across C calls
51 * fp16-fp31: Promotion pool
52 *
53 */
54
Bill Buzbee1465db52009-09-23 17:17:35 -070055#define SREG(c, s) ((c)->regLocation[(s)].sRegLow)
56/*
57 * Get the "real" sreg number associated with an sReg slot. In general,
58 * sReg values passed through codegen are the SSA names created by
59 * dataflow analysis and refer to slot numbers in the cUnit->regLocation
60 * array. However, renaming is accomplished by simply replacing RegLocation
61 * entries in the cUnit->reglocation[] array. Therefore, when location
62 * records for operands are first created, we need to ask the locRecord
63 * identified by the dataflow pass what it's new name is.
64 */
65
Bill Buzbee1465db52009-09-23 17:17:35 -070066/*
67 * Free all allocated temps in the temp pools. Note that this does
68 * not affect the "liveness" of a temp register, which will stay
69 * live until it is either explicitly killed or reallocated.
70 */
Bill Buzbeec6f10662010-02-09 11:16:15 -080071extern void dvmCompilerResetRegPool(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -070072{
73 int i;
74 for (i=0; i < cUnit->regPool->numCoreTemps; i++) {
75 cUnit->regPool->coreTemps[i].inUse = false;
76 }
77 for (i=0; i < cUnit->regPool->numFPTemps; i++) {
78 cUnit->regPool->FPTemps[i].inUse = false;
79 }
80}
81
82 /* Set up temp & preserved register pools specialized by target */
Bill Buzbeec6f10662010-02-09 11:16:15 -080083extern void dvmCompilerInitPool(RegisterInfo *regs, int *regNums, int num)
Bill Buzbee1465db52009-09-23 17:17:35 -070084{
85 int i;
86 for (i=0; i < num; i++) {
87 regs[i].reg = regNums[i];
88 regs[i].inUse = false;
89 regs[i].pair = false;
90 regs[i].live = false;
91 regs[i].dirty = false;
92 regs[i].sReg = INVALID_SREG;
93 }
94}
95
96static void dumpRegPool(RegisterInfo *p, int numRegs)
97{
98 int i;
99 LOGE("================================================");
100 for (i=0; i < numRegs; i++ ){
101 LOGE("R[%d]: U:%d, P:%d, part:%d, LV:%d, D:%d, SR:%d, ST:%x, EN:%x",
102 p[i].reg, p[i].inUse, p[i].pair, p[i].partner, p[i].live,
103 p[i].dirty, p[i].sReg,(int)p[i].defStart, (int)p[i].defEnd);
104 }
105 LOGE("================================================");
106}
107
Ben Cheng5d90c202009-11-22 23:31:11 -0800108static RegisterInfo *getRegInfo(CompilationUnit *cUnit, int reg)
109{
110 int numTemps = cUnit->regPool->numCoreTemps;
111 RegisterInfo *p = cUnit->regPool->coreTemps;
112 int i;
113 for (i=0; i< numTemps; i++) {
114 if (p[i].reg == reg) {
115 return &p[i];
116 }
117 }
118 p = cUnit->regPool->FPTemps;
119 numTemps = cUnit->regPool->numFPTemps;
120 for (i=0; i< numTemps; i++) {
121 if (p[i].reg == reg) {
122 return &p[i];
123 }
124 }
125 LOGE("Tried to get info on a non-existant temp: r%d",reg);
126 dvmAbort();
127 return NULL;
128}
129
130static void flushRegWide(CompilationUnit *cUnit, int reg1, int reg2)
131{
132 RegisterInfo *info1 = getRegInfo(cUnit, reg1);
133 RegisterInfo *info2 = getRegInfo(cUnit, reg2);
134 assert(info1 && info2 && info1->pair && info2->pair &&
135 (info1->partner == info2->reg) &&
136 (info2->partner == info1->reg));
137 if ((info1->live && info1->dirty) || (info2->live && info2->dirty)) {
138 info1->dirty = false;
139 info2->dirty = false;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800140 if (dvmCompilerS2VReg(cUnit, info2->sReg) <
141 dvmCompilerS2VReg(cUnit, info1->sReg))
Ben Cheng5d90c202009-11-22 23:31:11 -0800142 info1 = info2;
143 dvmCompilerFlushRegWideImpl(cUnit, rFP,
Bill Buzbeec6f10662010-02-09 11:16:15 -0800144 dvmCompilerS2VReg(cUnit, info1->sReg) << 2,
Ben Cheng5d90c202009-11-22 23:31:11 -0800145 info1->reg, info1->partner);
146 }
147}
148
149static void flushReg(CompilationUnit *cUnit, int reg)
150{
151 RegisterInfo *info = getRegInfo(cUnit, reg);
152 if (info->live && info->dirty) {
153 info->dirty = false;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800154 dvmCompilerFlushRegImpl(cUnit, rFP,
155 dvmCompilerS2VReg(cUnit, info->sReg) << 2,
Ben Cheng5d90c202009-11-22 23:31:11 -0800156 reg, kWord);
157 }
158}
159
160/* return true if found reg to clobber */
161static bool clobberRegBody(CompilationUnit *cUnit, RegisterInfo *p,
162 int numTemps, int reg)
163{
164 int i;
165 for (i=0; i< numTemps; i++) {
166 if (p[i].reg == reg) {
167 if (p[i].live && p[i].dirty) {
168 if (p[i].pair) {
169 flushRegWide(cUnit, p[i].reg, p[i].partner);
170 } else {
171 flushReg(cUnit, p[i].reg);
172 }
173 }
174 p[i].live = false;
175 p[i].sReg = INVALID_SREG;
176 p[i].defStart = NULL;
177 p[i].defEnd = NULL;
178 if (p[i].pair) {
179 p[i].pair = false;
180 /* partners should be in same pool */
181 clobberRegBody(cUnit, p, numTemps, p[i].partner);
182 }
183 return true;
184 }
185 }
186 return false;
187}
188
189/* Mark a temp register as dead. Does not affect allocation state. */
Bill Buzbeec6f10662010-02-09 11:16:15 -0800190void dvmCompilerClobber(CompilationUnit *cUnit, int reg)
Ben Cheng5d90c202009-11-22 23:31:11 -0800191{
192 if (!clobberRegBody(cUnit, cUnit->regPool->coreTemps,
193 cUnit->regPool->numCoreTemps, reg)) {
194 clobberRegBody(cUnit, cUnit->regPool->FPTemps,
195 cUnit->regPool->numFPTemps, reg);
196 }
197}
198
199static void clobberSRegBody(RegisterInfo *p, int numTemps, int sReg)
200{
201 int i;
202 for (i=0; i< numTemps; i++) {
203 if (p[i].sReg == sReg) {
204 p[i].live = false;
205 p[i].defStart = NULL;
206 p[i].defEnd = NULL;
207 }
208 }
209}
210
211/* Clobber any temp associated with an sReg. Could be in either class */
Bill Buzbeec6f10662010-02-09 11:16:15 -0800212extern void dvmCompilerClobberSReg(CompilationUnit *cUnit, int sReg)
Ben Cheng5d90c202009-11-22 23:31:11 -0800213{
214 clobberSRegBody(cUnit->regPool->coreTemps, cUnit->regPool->numCoreTemps,
215 sReg);
216 clobberSRegBody(cUnit->regPool->FPTemps, cUnit->regPool->numFPTemps,
217 sReg);
218}
219
Bill Buzbee1465db52009-09-23 17:17:35 -0700220static int allocTempBody(CompilationUnit *cUnit, RegisterInfo *p, int numTemps,
221 bool required)
222{
223 int i;
224 //Tuning: redo this to widen the live window on freed temps
225 for (i=0; i< numTemps; i++) {
226 if (!p[i].inUse && !p[i].live) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800227 dvmCompilerClobber(cUnit, p[i].reg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700228 p[i].inUse = true;
229 p[i].pair = false;
230 return p[i].reg;
231 }
232 }
233 for (i=0; i< numTemps; i++) {
234 if (!p[i].inUse) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800235 dvmCompilerClobber(cUnit, p[i].reg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700236 p[i].inUse = true;
237 p[i].pair = false;
238 return p[i].reg;
239 }
240 }
241 if (required) {
242 LOGE("No free temp registers");
243 assert(0);
244 }
245 return -1; // No register available
246}
247
248//REDO: too many assumptions.
Bill Buzbeec6f10662010-02-09 11:16:15 -0800249extern int dvmCompilerAllocTempDouble(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -0700250{
251 RegisterInfo *p = cUnit->regPool->FPTemps;
252 int numTemps = cUnit->regPool->numFPTemps;
253 int i;
254
255 for (i=0; i < numTemps; i+=2) {
256 if ((!p[i].inUse && !p[i].live) &&
257 (!p[i+1].inUse && !p[i+1].live)) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800258 dvmCompilerClobber(cUnit, p[i].reg);
259 dvmCompilerClobber(cUnit, p[i+1].reg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700260 p[i].inUse = true;
261 p[i+1].inUse = true;
262 assert((p[i].reg+1) == p[i+1].reg);
263 assert((p[i].reg & 0x1) == 0);
264 return p[i].reg;
265 }
266 }
267 for (i=0; i < numTemps; i+=2) {
268 if (!p[i].inUse && !p[i+1].inUse) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800269 dvmCompilerClobber(cUnit, p[i].reg);
270 dvmCompilerClobber(cUnit, p[i+1].reg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700271 p[i].inUse = true;
272 p[i+1].inUse = true;
273 assert((p[i].reg+1) == p[i+1].reg);
274 assert((p[i].reg & 0x1) == 0);
275 return p[i].reg;
276 }
277 }
278 LOGE("No free temp registers");
279 *((int*)0) = 0; //For development, die instantly. Later abort translation
280 dvmAbort();
281 return -1;
282}
283
284/* Return a temp if one is available, -1 otherwise */
Bill Buzbeec6f10662010-02-09 11:16:15 -0800285extern int dvmCompilerAllocFreeTemp(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -0700286{
287 return allocTempBody(cUnit, cUnit->regPool->coreTemps,
288 cUnit->regPool->numCoreTemps, true);
289}
290
Bill Buzbeec6f10662010-02-09 11:16:15 -0800291extern int dvmCompilerAllocTemp(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -0700292{
293 return allocTempBody(cUnit, cUnit->regPool->coreTemps,
294 cUnit->regPool->numCoreTemps, true);
295}
296
Bill Buzbeec6f10662010-02-09 11:16:15 -0800297extern int dvmCompilerAllocTempFloat(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -0700298{
299 return allocTempBody(cUnit, cUnit->regPool->FPTemps,
300 cUnit->regPool->numFPTemps, true);
301}
302
303static RegisterInfo *allocLiveBody(RegisterInfo *p, int numTemps, int sReg)
304{
305 int i;
306 if (sReg == -1)
307 return NULL;
308 for (i=0; i < numTemps; i++) {
309 if (p[i].live && (p[i].sReg == sReg)) {
310 p[i].inUse = true;
311 return &p[i];
312 }
313 }
314 return NULL;
315}
316
317static RegisterInfo *allocLive(CompilationUnit *cUnit, int sReg,
318 int regClass)
319{
320 RegisterInfo *res = NULL;
321 switch(regClass) {
322 case kAnyReg:
323 res = allocLiveBody(cUnit->regPool->FPTemps,
324 cUnit->regPool->numFPTemps, sReg);
325 if (res)
326 break;
327 /* Intentional fallthrough */
328 case kCoreReg:
329 res = allocLiveBody(cUnit->regPool->coreTemps,
330 cUnit->regPool->numCoreTemps, sReg);
331 break;
332 case kFPReg:
333 res = allocLiveBody(cUnit->regPool->FPTemps,
334 cUnit->regPool->numFPTemps, sReg);
335 break;
336 default:
337 LOGE("Invalid register type");
338 assert(0);
339 dvmAbort();
340 }
341 return res;
342}
343
Bill Buzbeec6f10662010-02-09 11:16:15 -0800344extern void dvmCompilerFreeTemp(CompilationUnit *cUnit, int reg)
Bill Buzbee1465db52009-09-23 17:17:35 -0700345{
346 RegisterInfo *p = cUnit->regPool->coreTemps;
347 int numTemps = cUnit->regPool->numCoreTemps;
348 int i;
349 for (i=0; i< numTemps; i++) {
350 if (p[i].reg == reg) {
351 p[i].inUse = false;
352 p[i].pair = false;
353 return;
354 }
355 }
356 p = cUnit->regPool->FPTemps;
357 numTemps = cUnit->regPool->numFPTemps;
358 for (i=0; i< numTemps; i++) {
359 if (p[i].reg == reg) {
360 p[i].inUse = false;
361 p[i].pair = false;
362 return;
363 }
364 }
365 LOGE("Tried to free a non-existant temp: r%d",reg);
366 dvmAbort();
367}
368
369//FIXME - this needs to also check the preserved pool.
Bill Buzbeec6f10662010-02-09 11:16:15 -0800370extern RegisterInfo *dvmCompilerIsLive(CompilationUnit *cUnit, int reg)
Bill Buzbee1465db52009-09-23 17:17:35 -0700371{
372 RegisterInfo *p = cUnit->regPool->coreTemps;
373 int numTemps = cUnit->regPool->numCoreTemps;
374 int i;
375 for (i=0; i< numTemps; i++) {
376 if (p[i].reg == reg) {
377 return p[i].live ? &p[i] : NULL;
378 }
379 }
380 p = cUnit->regPool->FPTemps;
381 numTemps = cUnit->regPool->numFPTemps;
382 for (i=0; i< numTemps; i++) {
383 if (p[i].reg == reg) {
384 return p[i].live ? &p[i] : NULL;
385 }
386 }
387 return NULL;
388}
389
Bill Buzbeec6f10662010-02-09 11:16:15 -0800390extern RegisterInfo *dvmCompilerIsTemp(CompilationUnit *cUnit, int reg)
Bill Buzbee1465db52009-09-23 17:17:35 -0700391{
392 RegisterInfo *p = cUnit->regPool->coreTemps;
393 int numTemps = cUnit->regPool->numCoreTemps;
394 int i;
395 for (i=0; i< numTemps; i++) {
396 if (p[i].reg == reg) {
397 return &p[i];
398 }
399 }
400 p = cUnit->regPool->FPTemps;
401 numTemps = cUnit->regPool->numFPTemps;
402 for (i=0; i< numTemps; i++) {
403 if (p[i].reg == reg) {
404 return &p[i];
405 }
406 }
407 return NULL;
408}
409
Bill Buzbee1465db52009-09-23 17:17:35 -0700410/*
Bill Buzbeec6f10662010-02-09 11:16:15 -0800411 * Similar to dvmCompilerAllocTemp(), but forces the allocation of a specific
Bill Buzbee1465db52009-09-23 17:17:35 -0700412 * register. No check is made to see if the register was previously
413 * allocated. Use with caution.
414 */
Bill Buzbeec6f10662010-02-09 11:16:15 -0800415extern void dvmCompilerLockTemp(CompilationUnit *cUnit, int reg)
Bill Buzbee1465db52009-09-23 17:17:35 -0700416{
417 RegisterInfo *p = cUnit->regPool->coreTemps;
418 int numTemps = cUnit->regPool->numCoreTemps;
419 int i;
420 for (i=0; i< numTemps; i++) {
421 if (p[i].reg == reg) {
422 p[i].inUse = true;
423 p[i].live = false;
424 return;
425 }
426 }
427 p = cUnit->regPool->FPTemps;
428 numTemps = cUnit->regPool->numFPTemps;
429 for (i=0; i< numTemps; i++) {
430 if (p[i].reg == reg) {
431 p[i].inUse = true;
432 p[i].live = false;
433 return;
434 }
435 }
436 LOGE("Tried to lock a non-existant temp: r%d",reg);
437 dvmAbort();
438}
439
440static void lockArgRegs(CompilationUnit *cUnit)
441{
Bill Buzbeec6f10662010-02-09 11:16:15 -0800442 dvmCompilerLockTemp(cUnit, r0);
443 dvmCompilerLockTemp(cUnit, r1);
444 dvmCompilerLockTemp(cUnit, r2);
445 dvmCompilerLockTemp(cUnit, r3);
Bill Buzbee1465db52009-09-23 17:17:35 -0700446}
447
448/* Clobber all regs that might be used by an external C call */
Elliott Hughes6a555132010-02-25 15:41:42 -0800449extern void dvmCompilerClobberCallRegs(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -0700450{
Bill Buzbeec6f10662010-02-09 11:16:15 -0800451 dvmCompilerClobber(cUnit, r0);
452 dvmCompilerClobber(cUnit, r1);
453 dvmCompilerClobber(cUnit, r2);
454 dvmCompilerClobber(cUnit, r3);
Elliott Hughes6a555132010-02-25 15:41:42 -0800455 dvmCompilerClobber(cUnit, r9); // Need to do this?, be conservative
Bill Buzbeec6f10662010-02-09 11:16:15 -0800456 dvmCompilerClobber(cUnit, r11);
457 dvmCompilerClobber(cUnit, r12);
458 dvmCompilerClobber(cUnit, rlr);
Bill Buzbee1465db52009-09-23 17:17:35 -0700459}
460
461/* Clobber all of the temps that might be used by a handler. */
Bill Buzbeec6f10662010-02-09 11:16:15 -0800462extern void dvmCompilerClobberHandlerRegs(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -0700463{
464 //TUNING: reduce the set of regs used by handlers. Only a few need lots.
Elliott Hughes6a555132010-02-25 15:41:42 -0800465 dvmCompilerClobberCallRegs(cUnit);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800466 dvmCompilerClobber(cUnit, r4PC);
467 dvmCompilerClobber(cUnit, r9);
468 dvmCompilerClobber(cUnit, r10);
Bill Buzbee1465db52009-09-23 17:17:35 -0700469}
470
Bill Buzbeec6f10662010-02-09 11:16:15 -0800471extern void dvmCompilerResetDef(CompilationUnit *cUnit, int reg)
Bill Buzbee1465db52009-09-23 17:17:35 -0700472{
473 RegisterInfo *p = getRegInfo(cUnit, reg);
474 p->defStart = NULL;
475 p->defEnd = NULL;
476}
477
478static void nullifyRange(CompilationUnit *cUnit, LIR *start, LIR *finish,
479 int sReg1, int sReg2)
480{
481 if (start && finish) {
482 LIR *p;
483 assert(sReg1 == sReg2);
484 for (p = start; ;p = p->next) {
485 ((ArmLIR *)p)->isNop = true;
486 if (p == finish)
487 break;
488 }
489 }
490}
491
492/*
493 * Mark the beginning and end LIR of a def sequence. Note that
494 * on entry start points to the LIR prior to the beginning of the
495 * sequence.
496 */
Bill Buzbeec6f10662010-02-09 11:16:15 -0800497extern void dvmCompilerMarkDef(CompilationUnit *cUnit, RegLocation rl,
Bill Buzbee1465db52009-09-23 17:17:35 -0700498 LIR *start, LIR *finish)
499{
500 assert(!rl.wide);
501 assert(start && start->next);
502 assert(finish);
503 RegisterInfo *p = getRegInfo(cUnit, rl.lowReg);
504 p->defStart = start->next;
505 p->defEnd = finish;
506}
507
508/*
509 * Mark the beginning and end LIR of a def sequence. Note that
510 * on entry start points to the LIR prior to the beginning of the
511 * sequence.
512 */
Bill Buzbeec6f10662010-02-09 11:16:15 -0800513extern void dvmCompilerMarkDefWide(CompilationUnit *cUnit, RegLocation rl,
Bill Buzbee1465db52009-09-23 17:17:35 -0700514 LIR *start, LIR *finish)
515{
516 assert(rl.wide);
517 assert(start && start->next);
518 assert(finish);
519 RegisterInfo *p = getRegInfo(cUnit, rl.lowReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800520 dvmCompilerResetDef(cUnit, rl.highReg); // Only track low of pair
Bill Buzbee1465db52009-09-23 17:17:35 -0700521 p->defStart = start->next;
522 p->defEnd = finish;
523}
524
Bill Buzbeec6f10662010-02-09 11:16:15 -0800525extern RegLocation dvmCompilerWideToNarrow(CompilationUnit *cUnit,
526 RegLocation rl)
Bill Buzbee1465db52009-09-23 17:17:35 -0700527{
528 assert(rl.wide);
529 if (rl.location == kLocPhysReg) {
530 RegisterInfo *infoLo = getRegInfo(cUnit, rl.lowReg);
531 RegisterInfo *infoHi = getRegInfo(cUnit, rl.highReg);
532 if (!infoLo->pair) {
Ben Cheng5d90c202009-11-22 23:31:11 -0800533 dumpRegPool(cUnit->regPool->coreTemps,
534 cUnit->regPool->numCoreTemps);
Bill Buzbee1465db52009-09-23 17:17:35 -0700535 assert(infoLo->pair);
536 }
537 if (!infoHi->pair) {
Ben Cheng5d90c202009-11-22 23:31:11 -0800538 dumpRegPool(cUnit->regPool->coreTemps,
539 cUnit->regPool->numCoreTemps);
Bill Buzbee1465db52009-09-23 17:17:35 -0700540 assert(infoHi->pair);
541 }
542 assert(infoLo->pair);
543 assert(infoHi->pair);
544 assert(infoLo->partner == infoHi->reg);
545 assert(infoHi->partner == infoLo->reg);
546 infoLo->pair = false;
547 infoHi->pair = false;
548 infoLo->defStart = NULL;
549 infoLo->defEnd = NULL;
550 infoHi->defStart = NULL;
551 infoHi->defEnd = NULL;
552 }
553 rl.wide = false;
554 return rl;
555}
556
Bill Buzbeec6f10662010-02-09 11:16:15 -0800557extern void dvmCompilerResetDefLoc(CompilationUnit *cUnit, RegLocation rl)
Bill Buzbee1465db52009-09-23 17:17:35 -0700558{
559 assert(!rl.wide);
560 if (!(gDvmJit.disableOpt & (1 << kSuppressLoads))) {
561 RegisterInfo *p = getRegInfo(cUnit, rl.lowReg);
562 assert(!p->pair);
563 nullifyRange(cUnit, p->defStart, p->defEnd,
564 p->sReg, rl.sRegLow);
565 }
Bill Buzbeec6f10662010-02-09 11:16:15 -0800566 dvmCompilerResetDef(cUnit, rl.lowReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700567}
568
Bill Buzbeec6f10662010-02-09 11:16:15 -0800569extern void dvmCompilerResetDefLocWide(CompilationUnit *cUnit, RegLocation rl)
Bill Buzbee1465db52009-09-23 17:17:35 -0700570{
571 assert(rl.wide);
572 if (!(gDvmJit.disableOpt & (1 << kSuppressLoads))) {
573 RegisterInfo *p = getRegInfo(cUnit, rl.lowReg);
574 assert(p->pair);
575 nullifyRange(cUnit, p->defStart, p->defEnd,
576 p->sReg, rl.sRegLow);
577 }
Bill Buzbeec6f10662010-02-09 11:16:15 -0800578 dvmCompilerResetDef(cUnit, rl.lowReg);
579 dvmCompilerResetDef(cUnit, rl.highReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700580}
581
Bill Buzbeec6f10662010-02-09 11:16:15 -0800582extern void dvmCompilerResetDefTracking(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -0700583{
584 int i;
585 for (i=0; i< cUnit->regPool->numCoreTemps; i++) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800586 dvmCompilerResetDef(cUnit, cUnit->regPool->coreTemps[i].reg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700587 }
588 for (i=0; i< cUnit->regPool->numFPTemps; i++) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800589 dvmCompilerResetDef(cUnit, cUnit->regPool->FPTemps[i].reg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700590 }
591}
592
Bill Buzbeec6f10662010-02-09 11:16:15 -0800593extern void dvmCompilerClobberAllRegs(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -0700594{
595 int i;
596 for (i=0; i< cUnit->regPool->numCoreTemps; i++) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800597 dvmCompilerClobber(cUnit, cUnit->regPool->coreTemps[i].reg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700598 }
599 for (i=0; i< cUnit->regPool->numFPTemps; i++) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800600 dvmCompilerClobber(cUnit, cUnit->regPool->FPTemps[i].reg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700601 }
602}
603
604/* To be used when explicitly managing register use */
Bill Buzbeec6f10662010-02-09 11:16:15 -0800605extern void dvmCompilerLockAllTemps(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -0700606{
607 int i;
608 for (i=0; i< cUnit->regPool->numCoreTemps; i++) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800609 dvmCompilerLockTemp(cUnit, cUnit->regPool->coreTemps[i].reg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700610 }
611}
612
613// Make sure nothing is live and dirty
614static void flushAllRegsBody(CompilationUnit *cUnit, RegisterInfo *info,
615 int numRegs)
616{
617 int i;
618 for (i=0; i < numRegs; i++) {
619 if (info[i].live && info[i].dirty) {
620 if (info[i].pair) {
621 flushRegWide(cUnit, info[i].reg, info[i].partner);
622 } else {
623 flushReg(cUnit, info[i].reg);
624 }
625 }
626 }
627}
628
Bill Buzbeec6f10662010-02-09 11:16:15 -0800629extern void dvmCompilerFlushAllRegs(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -0700630{
631 flushAllRegsBody(cUnit, cUnit->regPool->coreTemps,
632 cUnit->regPool->numCoreTemps);
633 flushAllRegsBody(cUnit, cUnit->regPool->FPTemps,
634 cUnit->regPool->numFPTemps);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800635 dvmCompilerClobberAllRegs(cUnit);
Bill Buzbee1465db52009-09-23 17:17:35 -0700636}
637
638
639//TUNING: rewrite all of this reg stuff. Probably use an attribute table
640static bool regClassMatches(int regClass, int reg)
641{
642 if (regClass == kAnyReg) {
643 return true;
644 } else if (regClass == kCoreReg) {
645 return !FPREG(reg);
646 } else {
647 return FPREG(reg);
648 }
649}
650
Bill Buzbeec6f10662010-02-09 11:16:15 -0800651extern void dvmCompilerMarkLive(CompilationUnit *cUnit, int reg, int sReg)
Bill Buzbee1465db52009-09-23 17:17:35 -0700652{
653 RegisterInfo *info = getRegInfo(cUnit, reg);
654 if ((info->reg == reg) && (info->sReg == sReg) && info->live) {
655 return; /* already live */
656 } else if (sReg != INVALID_SREG) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800657 dvmCompilerClobberSReg(cUnit, sReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700658 info->live = true;
659 } else {
660 /* Can't be live if no associated sReg */
661 info->live = false;
662 }
663 info->sReg = sReg;
664}
665
Bill Buzbeec6f10662010-02-09 11:16:15 -0800666extern void dvmCompilerMarkPair(CompilationUnit *cUnit, int lowReg, int highReg)
Bill Buzbee1465db52009-09-23 17:17:35 -0700667{
668 RegisterInfo *infoLo = getRegInfo(cUnit, lowReg);
669 RegisterInfo *infoHi = getRegInfo(cUnit, highReg);
670 infoLo->pair = infoHi->pair = true;
671 infoLo->partner = highReg;
672 infoHi->partner = lowReg;
673}
674
675static void markRegSingle(CompilationUnit *cUnit, int reg)
676{
677 RegisterInfo *info = getRegInfo(cUnit, reg);
678 info->pair = false;
679}
680
Bill Buzbeec6f10662010-02-09 11:16:15 -0800681extern void dvmCompilerMarkClean(CompilationUnit *cUnit, int reg)
Bill Buzbee1465db52009-09-23 17:17:35 -0700682{
683 RegisterInfo *info = getRegInfo(cUnit, reg);
684 info->dirty = false;
685}
686
Bill Buzbeec6f10662010-02-09 11:16:15 -0800687extern void dvmCompilerMarkDirty(CompilationUnit *cUnit, int reg)
Bill Buzbee1465db52009-09-23 17:17:35 -0700688{
689 RegisterInfo *info = getRegInfo(cUnit, reg);
690 info->dirty = true;
691}
692
Elliott Hughes6a555132010-02-25 15:41:42 -0800693extern void dvmCompilerMarkInUse(CompilationUnit *cUnit, int reg)
Bill Buzbee1465db52009-09-23 17:17:35 -0700694{
Ben Cheng5d90c202009-11-22 23:31:11 -0800695 RegisterInfo *info = getRegInfo(cUnit, reg);
696 info->inUse = true;
Bill Buzbee1465db52009-09-23 17:17:35 -0700697}
698
699/* Return true if live & dirty */
700static bool isDirty(CompilationUnit *cUnit, int reg)
701{
702 RegisterInfo *info = getRegInfo(cUnit, reg);
703 return (info && info->live && info->dirty);
704}
705
706void copyRegInfo(CompilationUnit *cUnit, int newReg, int oldReg)
707{
708 RegisterInfo *newInfo = getRegInfo(cUnit, newReg);
709 RegisterInfo *oldInfo = getRegInfo(cUnit, oldReg);
710 *newInfo = *oldInfo;
711 newInfo->reg = newReg;
712}
713
714/*
715 * Return an updated location record with current in-register status.
716 * If the value lives in live temps, reflect that fact. No code
717 * is generated. The the live value is part of an older pair,
718 * clobber both low and high.
719 * TUNING: clobbering both is a bit heavy-handed, but the alternative
720 * is a bit complex when dealing with FP regs. Examine code to see
721 * if it's worthwhile trying to be more clever here.
722 */
Bill Buzbeec6f10662010-02-09 11:16:15 -0800723extern RegLocation dvmCompilerUpdateLoc(CompilationUnit *cUnit, RegLocation loc)
Bill Buzbee1465db52009-09-23 17:17:35 -0700724{
725 assert(!loc.wide);
726 if (loc.location == kLocDalvikFrame) {
727 RegisterInfo *infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
728 if (infoLo) {
729 if (infoLo->pair) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800730 dvmCompilerClobber(cUnit, infoLo->reg);
731 dvmCompilerClobber(cUnit, infoLo->partner);
Bill Buzbee1465db52009-09-23 17:17:35 -0700732 } else {
733 loc.lowReg = infoLo->reg;
734 loc.location = kLocPhysReg;
735 }
736 }
737 }
738
739 return loc;
740}
741
742/* see comments for updateLoc */
Bill Buzbeec6f10662010-02-09 11:16:15 -0800743extern RegLocation dvmCompilerUpdateLocWide(CompilationUnit *cUnit,
744 RegLocation loc)
Bill Buzbee1465db52009-09-23 17:17:35 -0700745{
746 assert(loc.wide);
747 if (loc.location == kLocDalvikFrame) {
748 RegisterInfo *infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800749 RegisterInfo *infoHi = allocLive(cUnit,
750 dvmCompilerSRegHi(loc.sRegLow), kAnyReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700751 bool match = true;
752 match = match && (infoLo != NULL);
753 match = match && (infoHi != NULL);
754 match = match && (FPREG(infoLo->reg) == FPREG(infoHi->reg));
755 if (match && FPREG(infoLo->reg)) {
756 match &= ((infoLo->reg & 0x1) == 0);
757 match &= ((infoHi->reg - infoLo->reg) == 1);
758 }
759 if (match) {
760 loc.lowReg = infoLo->reg;
761 loc.highReg = infoHi->reg;
762 loc.location = kLocPhysReg;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800763 dvmCompilerMarkPair(cUnit, loc.lowReg, loc.highReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700764 assert(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
765 return loc;
766 }
767 /* Can't easily reuse - just clobber any overlaps */
768 if (infoLo) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800769 dvmCompilerClobber(cUnit, infoLo->reg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700770 if (infoLo->pair)
Bill Buzbeec6f10662010-02-09 11:16:15 -0800771 dvmCompilerClobber(cUnit, infoLo->partner);
Bill Buzbee1465db52009-09-23 17:17:35 -0700772 }
773 if (infoHi) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800774 dvmCompilerClobber(cUnit, infoHi->reg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700775 if (infoHi->pair)
Bill Buzbeec6f10662010-02-09 11:16:15 -0800776 dvmCompilerClobber(cUnit, infoHi->partner);
Bill Buzbee1465db52009-09-23 17:17:35 -0700777 }
778 }
779
780 return loc;
781}
782
783static RegLocation evalLocWide(CompilationUnit *cUnit, RegLocation loc,
784 int regClass, bool update)
785{
786 assert(loc.wide);
787 int newRegs;
788 int lowReg;
789 int highReg;
790
Bill Buzbeec6f10662010-02-09 11:16:15 -0800791 loc = dvmCompilerUpdateLocWide(cUnit, loc);
Bill Buzbee1465db52009-09-23 17:17:35 -0700792
793 /* If already in registers, we can assume proper form. Right reg class? */
794 if (loc.location == kLocPhysReg) {
795 assert(FPREG(loc.lowReg) == FPREG(loc.highReg));
796 assert(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
797 if (!regClassMatches(regClass, loc.lowReg)) {
798 /* Wrong register class. Reallocate and copy */
Ben Cheng5d90c202009-11-22 23:31:11 -0800799 newRegs = dvmCompilerAllocTypedTempPair(cUnit, loc.fp, regClass);
Bill Buzbee1465db52009-09-23 17:17:35 -0700800 lowReg = newRegs & 0xff;
801 highReg = (newRegs >> 8) & 0xff;
Ben Cheng5d90c202009-11-22 23:31:11 -0800802 dvmCompilerRegCopyWide(cUnit, lowReg, highReg, loc.lowReg,
803 loc.highReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700804 copyRegInfo(cUnit, lowReg, loc.lowReg);
805 copyRegInfo(cUnit, highReg, loc.highReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800806 dvmCompilerClobber(cUnit, loc.lowReg);
807 dvmCompilerClobber(cUnit, loc.highReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700808 loc.lowReg = lowReg;
809 loc.highReg = highReg;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800810 dvmCompilerMarkPair(cUnit, loc.lowReg, loc.highReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700811 assert(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
812 }
813 return loc;
814 }
815
816 assert((loc.location != kLocRetval) || (loc.sRegLow == INVALID_SREG));
Ben Cheng5d90c202009-11-22 23:31:11 -0800817 assert((loc.location != kLocRetval) ||
Bill Buzbeec6f10662010-02-09 11:16:15 -0800818 (dvmCompilerSRegHi(loc.sRegLow) == INVALID_SREG));
Bill Buzbee1465db52009-09-23 17:17:35 -0700819
Ben Cheng5d90c202009-11-22 23:31:11 -0800820 newRegs = dvmCompilerAllocTypedTempPair(cUnit, loc.fp, regClass);
Bill Buzbee1465db52009-09-23 17:17:35 -0700821 loc.lowReg = newRegs & 0xff;
822 loc.highReg = (newRegs >> 8) & 0xff;
823
Bill Buzbeec6f10662010-02-09 11:16:15 -0800824 dvmCompilerMarkPair(cUnit, loc.lowReg, loc.highReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700825 if (update) {
826 loc.location = kLocPhysReg;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800827 dvmCompilerMarkLive(cUnit, loc.lowReg, loc.sRegLow);
828 dvmCompilerMarkLive(cUnit, loc.highReg, dvmCompilerSRegHi(loc.sRegLow));
Bill Buzbee1465db52009-09-23 17:17:35 -0700829 }
830 assert(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
831 return loc;
832}
833
Bill Buzbeec6f10662010-02-09 11:16:15 -0800834extern RegLocation dvmCompilerEvalLoc(CompilationUnit *cUnit, RegLocation loc,
835 int regClass, bool update)
Bill Buzbee1465db52009-09-23 17:17:35 -0700836{
837 RegisterInfo *infoLo = NULL;
838 int newReg;
839 if (loc.wide)
840 return evalLocWide(cUnit, loc, regClass, update);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800841 loc = dvmCompilerUpdateLoc(cUnit, loc);
Bill Buzbee1465db52009-09-23 17:17:35 -0700842
843 if (loc.location == kLocPhysReg) {
844 if (!regClassMatches(regClass, loc.lowReg)) {
845 /* Wrong register class. Realloc, copy and transfer ownership */
Ben Cheng5d90c202009-11-22 23:31:11 -0800846 newReg = dvmCompilerAllocTypedTemp(cUnit, loc.fp, regClass);
847 dvmCompilerRegCopy(cUnit, newReg, loc.lowReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700848 copyRegInfo(cUnit, newReg, loc.lowReg);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800849 dvmCompilerClobber(cUnit, loc.lowReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700850 loc.lowReg = newReg;
851 }
852 return loc;
853 }
854
855 assert((loc.location != kLocRetval) || (loc.sRegLow == INVALID_SREG));
856
Ben Cheng5d90c202009-11-22 23:31:11 -0800857 newReg = dvmCompilerAllocTypedTemp(cUnit, loc.fp, regClass);
Bill Buzbee1465db52009-09-23 17:17:35 -0700858 loc.lowReg = newReg;
859
860 if (update) {
861 loc.location = kLocPhysReg;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800862 dvmCompilerMarkLive(cUnit, loc.lowReg, loc.sRegLow);
Bill Buzbee1465db52009-09-23 17:17:35 -0700863 }
864 return loc;
865}
866
Bill Buzbee1465db52009-09-23 17:17:35 -0700867static inline int getDestSSAName(MIR *mir, int num)
868{
869 assert(mir->ssaRep->numDefs > num);
870 return mir->ssaRep->defs[num];
871}
872
873// Get the LocRecord associated with an SSA name use.
Bill Buzbeec6f10662010-02-09 11:16:15 -0800874extern RegLocation dvmCompilerGetSrc(CompilationUnit *cUnit, MIR *mir, int num)
Bill Buzbee1465db52009-09-23 17:17:35 -0700875{
Bill Buzbeec6f10662010-02-09 11:16:15 -0800876 RegLocation loc = cUnit->regLocation[
877 SREG(cUnit, dvmCompilerSSASrc(mir, num))];
878 loc.fp = cUnit->regLocation[dvmCompilerSSASrc(mir, num)].fp;
Bill Buzbee1465db52009-09-23 17:17:35 -0700879 loc.wide = false;
880 return loc;
881}
882
883// Get the LocRecord associated with an SSA name def.
Bill Buzbeec6f10662010-02-09 11:16:15 -0800884extern RegLocation dvmCompilerGetDest(CompilationUnit *cUnit, MIR *mir,
885 int num)
Bill Buzbee1465db52009-09-23 17:17:35 -0700886{
887 RegLocation loc = cUnit->regLocation[SREG(cUnit, getDestSSAName(mir, num))];
888 loc.fp = cUnit->regLocation[getDestSSAName(mir, num)].fp;
889 loc.wide = false;
890 return loc;
891}
892
893static RegLocation getLocWide(CompilationUnit *cUnit, MIR *mir,
Bill Buzbeec6f10662010-02-09 11:16:15 -0800894 int low, int high, bool isSrc)
Bill Buzbee1465db52009-09-23 17:17:35 -0700895{
896 RegLocation lowLoc;
897 RegLocation highLoc;
898 /* Copy loc record for low word and patch in data from high word */
899 if (isSrc) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800900 lowLoc = dvmCompilerGetSrc(cUnit, mir, low);
901 highLoc = dvmCompilerGetSrc(cUnit, mir, high);
Bill Buzbee1465db52009-09-23 17:17:35 -0700902 } else {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800903 lowLoc = dvmCompilerGetDest(cUnit, mir, low);
904 highLoc = dvmCompilerGetDest(cUnit, mir, high);
Bill Buzbee1465db52009-09-23 17:17:35 -0700905 }
906 /* Avoid this case by either promoting both or neither. */
907 assert(lowLoc.location == highLoc.location);
908 if (lowLoc.location == kLocPhysReg) {
909 /* This case shouldn't happen if we've named correctly */
910 assert(lowLoc.fp == highLoc.fp);
911 }
912 lowLoc.wide = true;
913 lowLoc.highReg = highLoc.lowReg;
914 return lowLoc;
915}
Ben Cheng5d90c202009-11-22 23:31:11 -0800916
Bill Buzbeec6f10662010-02-09 11:16:15 -0800917extern RegLocation dvmCompilerGetDestWide(CompilationUnit *cUnit, MIR *mir,
918 int low, int high)
Bill Buzbee1465db52009-09-23 17:17:35 -0700919{
920 return getLocWide(cUnit, mir, low, high, false);
921}
922
Bill Buzbeec6f10662010-02-09 11:16:15 -0800923extern RegLocation dvmCompilerGetSrcWide(CompilationUnit *cUnit, MIR *mir,
Bill Buzbee1465db52009-09-23 17:17:35 -0700924 int low, int high)
925{
926 return getLocWide(cUnit, mir, low, high, true);
927}
928
Bill Buzbeec6f10662010-02-09 11:16:15 -0800929extern RegLocation dvmCompilerGetReturnWide(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -0700930{
931 RegLocation res = LOC_C_RETURN_WIDE;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800932 dvmCompilerClobber(cUnit, r0);
933 dvmCompilerClobber(cUnit, r1);
Elliott Hughes6a555132010-02-25 15:41:42 -0800934 dvmCompilerMarkInUse(cUnit, r0);
935 dvmCompilerMarkInUse(cUnit, r1);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800936 dvmCompilerMarkPair(cUnit, res.lowReg, res.highReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700937 return res;
938}
939
Bill Buzbeec6f10662010-02-09 11:16:15 -0800940extern RegLocation dvmCompilerGetReturnWideAlt(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -0700941{
942 RegLocation res = LOC_C_RETURN_WIDE;
943 res.lowReg = r2;
944 res.highReg = r3;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800945 dvmCompilerClobber(cUnit, r2);
946 dvmCompilerClobber(cUnit, r3);
Elliott Hughes6a555132010-02-25 15:41:42 -0800947 dvmCompilerMarkInUse(cUnit, r2);
948 dvmCompilerMarkInUse(cUnit, r3);
Bill Buzbeec6f10662010-02-09 11:16:15 -0800949 dvmCompilerMarkPair(cUnit, res.lowReg, res.highReg);
Bill Buzbee1465db52009-09-23 17:17:35 -0700950 return res;
951}
952
Bill Buzbeec6f10662010-02-09 11:16:15 -0800953extern RegLocation dvmCompilerGetReturn(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -0700954{
955 RegLocation res = LOC_C_RETURN;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800956 dvmCompilerClobber(cUnit, r0);
Elliott Hughes6a555132010-02-25 15:41:42 -0800957 dvmCompilerMarkInUse(cUnit, r0);
Bill Buzbee1465db52009-09-23 17:17:35 -0700958 return res;
959}
960
Bill Buzbeec6f10662010-02-09 11:16:15 -0800961extern RegLocation dvmCompilerGetReturnAlt(CompilationUnit *cUnit)
Bill Buzbee1465db52009-09-23 17:17:35 -0700962{
963 RegLocation res = LOC_C_RETURN;
964 res.lowReg = r1;
Bill Buzbeec6f10662010-02-09 11:16:15 -0800965 dvmCompilerClobber(cUnit, r1);
Elliott Hughes6a555132010-02-25 15:41:42 -0800966 dvmCompilerMarkInUse(cUnit, r1);
Bill Buzbee1465db52009-09-23 17:17:35 -0700967 return res;
968}
969
970/* Kill the corresponding bit in the null-checked register list */
Bill Buzbeec6f10662010-02-09 11:16:15 -0800971extern void dvmCompilerKillNullCheckedLoc(CompilationUnit *cUnit,
972 RegLocation loc)
Bill Buzbee1465db52009-09-23 17:17:35 -0700973{
974 if (loc.location != kLocRetval) {
975 assert(loc.sRegLow != INVALID_SREG);
976 dvmClearBit(cUnit->regPool->nullCheckedRegs, loc.sRegLow);
977 if (loc.wide) {
Bill Buzbeec6f10662010-02-09 11:16:15 -0800978 assert(dvmCompilerSRegHi(loc.sRegLow) != INVALID_SREG);
979 dvmClearBit(cUnit->regPool->nullCheckedRegs,
980 dvmCompilerSRegHi(loc.sRegLow));
Bill Buzbee1465db52009-09-23 17:17:35 -0700981 }
982 }
983}
Ben Cheng5d90c202009-11-22 23:31:11 -0800984
985extern void dvmCompilerFlushRegWideForV5TEVFP(CompilationUnit *cUnit,
986 int reg1, int reg2)
987{
988 flushRegWide(cUnit, reg1, reg2);
989}
990
991extern void dvmCompilerFlushRegForV5TEVFP(CompilationUnit *cUnit, int reg)
992{
993 flushReg(cUnit, reg);
994}