blob: f5d13d3f2af69a1fd6c9aaa753d7131fd76e082c [file] [log] [blame]
buzbeeefc63692012-11-14 16:31:52 -08001/*
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#include "../../compiler_internals.h"
18#include "arm_lir.h"
buzbeeeaf09bc2012-11-15 14:51:41 -080019#include "../ralloc_util.h"
20#include "../codegen_util.h"
buzbeeefc63692012-11-14 16:31:52 -080021
22#include <string>
23
24namespace art {
25
26static int coreRegs[] = {r0, r1, r2, r3, rARM_SUSPEND, r5, r6, r7, r8, rARM_SELF, r10,
27 r11, r12, rARM_SP, rARM_LR, rARM_PC};
buzbee52a77fc2012-11-20 19:50:46 -080028static int ReservedRegs[] = {rARM_SUSPEND, rARM_SELF, rARM_SP, rARM_LR, rARM_PC};
29static int FpRegs[] = {fr0, fr1, fr2, fr3, fr4, fr5, fr6, fr7,
buzbeeefc63692012-11-14 16:31:52 -080030 fr8, fr9, fr10, fr11, fr12, fr13, fr14, fr15,
31 fr16, fr17, fr18, fr19, fr20, fr21, fr22, fr23,
32 fr24, fr25, fr26, fr27, fr28, fr29, fr30, fr31};
33static int coreTemps[] = {r0, r1, r2, r3, r12};
34static int fpTemps[] = {fr0, fr1, fr2, fr3, fr4, fr5, fr6, fr7,
35 fr8, fr9, fr10, fr11, fr12, fr13, fr14, fr15};
36
buzbee52a77fc2012-11-20 19:50:46 -080037RegLocation LocCReturn()
buzbeeefc63692012-11-14 16:31:52 -080038{
39 RegLocation res = ARM_LOC_C_RETURN;
40 return res;
41}
42
buzbee52a77fc2012-11-20 19:50:46 -080043RegLocation LocCReturnWide()
buzbeeefc63692012-11-14 16:31:52 -080044{
45 RegLocation res = ARM_LOC_C_RETURN_WIDE;
46 return res;
47}
48
buzbee52a77fc2012-11-20 19:50:46 -080049RegLocation LocCReturnFloat()
buzbeeefc63692012-11-14 16:31:52 -080050{
51 RegLocation res = ARM_LOC_C_RETURN_FLOAT;
52 return res;
53}
54
buzbee52a77fc2012-11-20 19:50:46 -080055RegLocation LocCReturnDouble()
buzbeeefc63692012-11-14 16:31:52 -080056{
57 RegLocation res = ARM_LOC_C_RETURN_DOUBLE;
58 return res;
59}
60
61// Return a target-dependent special register.
buzbee52a77fc2012-11-20 19:50:46 -080062int TargetReg(SpecialTargetRegister reg) {
buzbeeefc63692012-11-14 16:31:52 -080063 int res = INVALID_REG;
64 switch (reg) {
65 case kSelf: res = rARM_SELF; break;
66 case kSuspend: res = rARM_SUSPEND; break;
67 case kLr: res = rARM_LR; break;
68 case kPc: res = rARM_PC; break;
69 case kSp: res = rARM_SP; break;
70 case kArg0: res = rARM_ARG0; break;
71 case kArg1: res = rARM_ARG1; break;
72 case kArg2: res = rARM_ARG2; break;
73 case kArg3: res = rARM_ARG3; break;
74 case kFArg0: res = rARM_FARG0; break;
75 case kFArg1: res = rARM_FARG1; break;
76 case kFArg2: res = rARM_FARG2; break;
77 case kFArg3: res = rARM_FARG3; break;
78 case kRet0: res = rARM_RET0; break;
79 case kRet1: res = rARM_RET1; break;
80 case kInvokeTgt: res = rARM_INVOKE_TGT; break;
81 case kCount: res = rARM_COUNT; break;
82 }
83 return res;
84}
85
86
87// Create a double from a pair of singles.
buzbee52a77fc2012-11-20 19:50:46 -080088int S2d(int lowReg, int highReg)
buzbeeefc63692012-11-14 16:31:52 -080089{
90 return ARM_S2D(lowReg, highReg);
91}
92
93// Is reg a single or double?
buzbee52a77fc2012-11-20 19:50:46 -080094bool FpReg(int reg)
buzbeeefc63692012-11-14 16:31:52 -080095{
96 return ARM_FPREG(reg);
97}
98
99// Is reg a single?
buzbee52a77fc2012-11-20 19:50:46 -0800100bool SingleReg(int reg)
buzbeeefc63692012-11-14 16:31:52 -0800101{
102 return ARM_SINGLEREG(reg);
103}
104
105// Is reg a double?
buzbee52a77fc2012-11-20 19:50:46 -0800106bool DoubleReg(int reg)
buzbeeefc63692012-11-14 16:31:52 -0800107{
108 return ARM_DOUBLEREG(reg);
109}
110
111// Return mask to strip off fp reg flags and bias.
buzbee52a77fc2012-11-20 19:50:46 -0800112uint32_t FpRegMask()
buzbeeefc63692012-11-14 16:31:52 -0800113{
114 return ARM_FP_REG_MASK;
115}
116
117// True if both regs single, both core or both double.
buzbee52a77fc2012-11-20 19:50:46 -0800118bool SameRegType(int reg1, int reg2)
buzbeeefc63692012-11-14 16:31:52 -0800119{
120 return (ARM_REGTYPE(reg1) == ARM_REGTYPE(reg2));
121}
122
123/*
124 * Decode the register id.
125 */
buzbee52a77fc2012-11-20 19:50:46 -0800126uint64_t GetRegMaskCommon(CompilationUnit* cUnit, int reg)
buzbeeefc63692012-11-14 16:31:52 -0800127{
buzbeeeaf09bc2012-11-15 14:51:41 -0800128 uint64_t seed;
buzbeeefc63692012-11-14 16:31:52 -0800129 int shift;
130 int regId;
131
132
133 regId = reg & 0x1f;
134 /* Each double register is equal to a pair of single-precision FP registers */
135 seed = ARM_DOUBLEREG(reg) ? 3 : 1;
136 /* FP register starts at bit position 16 */
137 shift = ARM_FPREG(reg) ? kArmFPReg0 : 0;
138 /* Expand the double register id into single offset */
139 shift += regId;
140 return (seed << shift);
141}
142
buzbee52a77fc2012-11-20 19:50:46 -0800143uint64_t GetPCUseDefEncoding()
buzbeeefc63692012-11-14 16:31:52 -0800144{
145 return ENCODE_ARM_REG_PC;
146}
147
buzbee52a77fc2012-11-20 19:50:46 -0800148void SetupTargetResourceMasks(CompilationUnit* cUnit, LIR* lir)
buzbeeefc63692012-11-14 16:31:52 -0800149{
150 DCHECK_EQ(cUnit->instructionSet, kThumb2);
151
152 // Thumb2 specific setup
153 uint64_t flags = EncodingMap[lir->opcode].flags;
154 int opcode = lir->opcode;
155
156 if (flags & REG_DEF_SP) {
157 lir->defMask |= ENCODE_ARM_REG_SP;
158 }
159
160 if (flags & REG_USE_SP) {
161 lir->useMask |= ENCODE_ARM_REG_SP;
162 }
163
164 if (flags & REG_DEF_LIST0) {
165 lir->defMask |= ENCODE_ARM_REG_LIST(lir->operands[0]);
166 }
167
168 if (flags & REG_DEF_LIST1) {
169 lir->defMask |= ENCODE_ARM_REG_LIST(lir->operands[1]);
170 }
171
172 if (flags & REG_DEF_FPCS_LIST0) {
173 lir->defMask |= ENCODE_ARM_REG_FPCS_LIST(lir->operands[0]);
174 }
175
176 if (flags & REG_DEF_FPCS_LIST2) {
177 for (int i = 0; i < lir->operands[2]; i++) {
buzbee52a77fc2012-11-20 19:50:46 -0800178 SetupRegMask(cUnit, &lir->defMask, lir->operands[1] + i);
buzbeeefc63692012-11-14 16:31:52 -0800179 }
180 }
181
182 if (flags & REG_USE_PC) {
183 lir->useMask |= ENCODE_ARM_REG_PC;
184 }
185
186 /* Conservatively treat the IT block */
187 if (flags & IS_IT) {
188 lir->defMask = ENCODE_ALL;
189 }
190
191 if (flags & REG_USE_LIST0) {
192 lir->useMask |= ENCODE_ARM_REG_LIST(lir->operands[0]);
193 }
194
195 if (flags & REG_USE_LIST1) {
196 lir->useMask |= ENCODE_ARM_REG_LIST(lir->operands[1]);
197 }
198
199 if (flags & REG_USE_FPCS_LIST0) {
200 lir->useMask |= ENCODE_ARM_REG_FPCS_LIST(lir->operands[0]);
201 }
202
203 if (flags & REG_USE_FPCS_LIST2) {
204 for (int i = 0; i < lir->operands[2]; i++) {
buzbee52a77fc2012-11-20 19:50:46 -0800205 SetupRegMask(cUnit, &lir->useMask, lir->operands[1] + i);
buzbeeefc63692012-11-14 16:31:52 -0800206 }
207 }
208 /* Fixup for kThumbPush/lr and kThumbPop/pc */
209 if (opcode == kThumbPush || opcode == kThumbPop) {
buzbee52a77fc2012-11-20 19:50:46 -0800210 uint64_t r8Mask = GetRegMaskCommon(cUnit, r8);
buzbeeefc63692012-11-14 16:31:52 -0800211 if ((opcode == kThumbPush) && (lir->useMask & r8Mask)) {
212 lir->useMask &= ~r8Mask;
213 lir->useMask |= ENCODE_ARM_REG_LR;
214 } else if ((opcode == kThumbPop) && (lir->defMask & r8Mask)) {
215 lir->defMask &= ~r8Mask;
216 lir->defMask |= ENCODE_ARM_REG_PC;
217 }
218 }
219 if (flags & REG_DEF_LR) {
220 lir->defMask |= ENCODE_ARM_REG_LR;
221 }
222}
223
buzbee52a77fc2012-11-20 19:50:46 -0800224ArmConditionCode ArmConditionEncoding(ConditionCode ccode)
buzbeeefc63692012-11-14 16:31:52 -0800225{
226 ArmConditionCode res;
buzbeecbd6d442012-11-17 14:11:25 -0800227 switch (ccode) {
buzbeeefc63692012-11-14 16:31:52 -0800228 case kCondEq: res = kArmCondEq; break;
229 case kCondNe: res = kArmCondNe; break;
230 case kCondCs: res = kArmCondCs; break;
231 case kCondCc: res = kArmCondCc; break;
232 case kCondMi: res = kArmCondMi; break;
233 case kCondPl: res = kArmCondPl; break;
234 case kCondVs: res = kArmCondVs; break;
235 case kCondVc: res = kArmCondVc; break;
236 case kCondHi: res = kArmCondHi; break;
237 case kCondLs: res = kArmCondLs; break;
238 case kCondGe: res = kArmCondGe; break;
239 case kCondLt: res = kArmCondLt; break;
240 case kCondGt: res = kArmCondGt; break;
241 case kCondLe: res = kArmCondLe; break;
242 case kCondAl: res = kArmCondAl; break;
243 case kCondNv: res = kArmCondNv; break;
244 default:
buzbeecbd6d442012-11-17 14:11:25 -0800245 LOG(FATAL) << "Bad condition code " << ccode;
246 res = static_cast<ArmConditionCode>(0); // Quiet gcc
buzbeeefc63692012-11-14 16:31:52 -0800247 }
248 return res;
249}
250
251static const char* coreRegNames[16] = {
252 "r0",
253 "r1",
254 "r2",
255 "r3",
256 "r4",
257 "r5",
258 "r6",
259 "r7",
260 "r8",
261 "rSELF",
262 "r10",
263 "r11",
264 "r12",
265 "sp",
266 "lr",
267 "pc",
268};
269
270
271static const char* shiftNames[4] = {
272 "lsl",
273 "lsr",
274 "asr",
275 "ror"};
276
277/* Decode and print a ARM register name */
buzbeeaad94382012-11-21 07:40:50 -0800278static char* DecodeRegList(int opcode, int vector, char* buf)
buzbeeefc63692012-11-14 16:31:52 -0800279{
280 int i;
281 bool printed = false;
282 buf[0] = 0;
283 for (i = 0; i < 16; i++, vector >>= 1) {
284 if (vector & 0x1) {
285 int regId = i;
286 if (opcode == kThumbPush && i == 8) {
287 regId = r14lr;
288 } else if (opcode == kThumbPop && i == 8) {
289 regId = r15pc;
290 }
291 if (printed) {
292 sprintf(buf + strlen(buf), ", r%d", regId);
293 } else {
294 printed = true;
295 sprintf(buf, "r%d", regId);
296 }
297 }
298 }
299 return buf;
300}
301
buzbeeaad94382012-11-21 07:40:50 -0800302static char* DecodeFPCSRegList(int count, int base, char* buf)
buzbeeefc63692012-11-14 16:31:52 -0800303{
304 sprintf(buf, "s%d", base);
305 for (int i = 1; i < count; i++) {
306 sprintf(buf + strlen(buf), ", s%d",base + i);
307 }
308 return buf;
309}
310
buzbeeaad94382012-11-21 07:40:50 -0800311static int ExpandImmediate(int value)
buzbeeefc63692012-11-14 16:31:52 -0800312{
313 int mode = (value & 0xf00) >> 8;
buzbeeeaf09bc2012-11-15 14:51:41 -0800314 uint32_t bits = value & 0xff;
buzbeeefc63692012-11-14 16:31:52 -0800315 switch (mode) {
316 case 0:
317 return bits;
318 case 1:
319 return (bits << 16) | bits;
320 case 2:
321 return (bits << 24) | (bits << 8);
322 case 3:
323 return (bits << 24) | (bits << 16) | (bits << 8) | bits;
324 default:
325 break;
326 }
327 bits = (bits | 0x80) << 24;
328 return bits >> (((value & 0xf80) >> 7) - 8);
329}
330
331const char* ccNames[] = {"eq","ne","cs","cc","mi","pl","vs","vc",
332 "hi","ls","ge","lt","gt","le","al","nv"};
333/*
334 * Interpret a format string and build a string no longer than size
335 * See format key in Assemble.c.
336 */
buzbee52a77fc2012-11-20 19:50:46 -0800337std::string BuildInsnString(const char* fmt, LIR* lir, unsigned char* baseAddr)
buzbeeefc63692012-11-14 16:31:52 -0800338{
339 std::string buf;
340 int i;
341 const char* fmtEnd = &fmt[strlen(fmt)];
342 char tbuf[256];
343 const char* name;
344 char nc;
345 while (fmt < fmtEnd) {
346 int operand;
347 if (*fmt == '!') {
348 fmt++;
349 DCHECK_LT(fmt, fmtEnd);
350 nc = *fmt++;
351 if (nc=='!') {
352 strcpy(tbuf, "!");
353 } else {
354 DCHECK_LT(fmt, fmtEnd);
buzbeecbd6d442012-11-17 14:11:25 -0800355 DCHECK_LT(static_cast<unsigned>(nc-'0'), 4U);
buzbeeefc63692012-11-14 16:31:52 -0800356 operand = lir->operands[nc-'0'];
357 switch (*fmt++) {
358 case 'H':
359 if (operand != 0) {
360 sprintf(tbuf, ", %s %d",shiftNames[operand & 0x3], operand >> 2);
361 } else {
362 strcpy(tbuf,"");
363 }
364 break;
365 case 'B':
366 switch (operand) {
367 case kSY:
368 name = "sy";
369 break;
370 case kST:
371 name = "st";
372 break;
373 case kISH:
374 name = "ish";
375 break;
376 case kISHST:
377 name = "ishst";
378 break;
379 case kNSH:
380 name = "nsh";
381 break;
382 case kNSHST:
383 name = "shst";
384 break;
385 default:
386 name = "DecodeError2";
387 break;
388 }
389 strcpy(tbuf, name);
390 break;
391 case 'b':
392 strcpy(tbuf,"0000");
393 for (i=3; i>= 0; i--) {
394 tbuf[i] += operand & 1;
395 operand >>= 1;
396 }
397 break;
398 case 'n':
buzbee52a77fc2012-11-20 19:50:46 -0800399 operand = ~ExpandImmediate(operand);
buzbeeefc63692012-11-14 16:31:52 -0800400 sprintf(tbuf,"%d [%#x]", operand, operand);
401 break;
402 case 'm':
buzbee52a77fc2012-11-20 19:50:46 -0800403 operand = ExpandImmediate(operand);
buzbeeefc63692012-11-14 16:31:52 -0800404 sprintf(tbuf,"%d [%#x]", operand, operand);
405 break;
406 case 's':
407 sprintf(tbuf,"s%d",operand & ARM_FP_REG_MASK);
408 break;
409 case 'S':
410 sprintf(tbuf,"d%d",(operand & ARM_FP_REG_MASK) >> 1);
411 break;
412 case 'h':
413 sprintf(tbuf,"%04x", operand);
414 break;
415 case 'M':
416 case 'd':
417 sprintf(tbuf,"%d", operand);
418 break;
419 case 'C':
420 DCHECK_LT(operand, static_cast<int>(
421 sizeof(coreRegNames)/sizeof(coreRegNames[0])));
422 sprintf(tbuf,"%s",coreRegNames[operand]);
423 break;
424 case 'E':
425 sprintf(tbuf,"%d", operand*4);
426 break;
427 case 'F':
428 sprintf(tbuf,"%d", operand*2);
429 break;
430 case 'c':
431 strcpy(tbuf, ccNames[operand]);
432 break;
433 case 't':
434 sprintf(tbuf,"0x%08x (L%p)",
buzbeecbd6d442012-11-17 14:11:25 -0800435 reinterpret_cast<uintptr_t>(baseAddr) + lir->offset + 4 +
buzbeeefc63692012-11-14 16:31:52 -0800436 (operand << 1),
437 lir->target);
438 break;
439 case 'u': {
440 int offset_1 = lir->operands[0];
441 int offset_2 = NEXT_LIR(lir)->operands[0];
buzbeecbd6d442012-11-17 14:11:25 -0800442 uintptr_t target =
443 (((reinterpret_cast<uintptr_t>(baseAddr) + lir->offset + 4) &
buzbeeefc63692012-11-14 16:31:52 -0800444 ~3) + (offset_1 << 21 >> 9) + (offset_2 << 1)) &
445 0xfffffffc;
buzbeecbd6d442012-11-17 14:11:25 -0800446 sprintf(tbuf, "%p", reinterpret_cast<void *>(target));
buzbeeefc63692012-11-14 16:31:52 -0800447 break;
448 }
449
450 /* Nothing to print for BLX_2 */
451 case 'v':
452 strcpy(tbuf, "see above");
453 break;
454 case 'R':
buzbee52a77fc2012-11-20 19:50:46 -0800455 DecodeRegList(lir->opcode, operand, tbuf);
buzbeeefc63692012-11-14 16:31:52 -0800456 break;
457 case 'P':
buzbee52a77fc2012-11-20 19:50:46 -0800458 DecodeFPCSRegList(operand, 16, tbuf);
buzbeeefc63692012-11-14 16:31:52 -0800459 break;
460 case 'Q':
buzbee52a77fc2012-11-20 19:50:46 -0800461 DecodeFPCSRegList(operand, 0, tbuf);
buzbeeefc63692012-11-14 16:31:52 -0800462 break;
463 default:
464 strcpy(tbuf,"DecodeError1");
465 break;
466 }
467 buf += tbuf;
468 }
469 } else {
470 buf += *fmt++;
471 }
472 }
473 return buf;
474}
475
buzbee52a77fc2012-11-20 19:50:46 -0800476void DumpResourceMask(LIR* armLIR, uint64_t mask, const char* prefix)
buzbeeefc63692012-11-14 16:31:52 -0800477{
478 char buf[256];
479 buf[0] = 0;
buzbeeefc63692012-11-14 16:31:52 -0800480
481 if (mask == ENCODE_ALL) {
482 strcpy(buf, "all");
483 } else {
484 char num[8];
485 int i;
486
487 for (i = 0; i < kArmRegEnd; i++) {
488 if (mask & (1ULL << i)) {
489 sprintf(num, "%d ", i);
490 strcat(buf, num);
491 }
492 }
493
494 if (mask & ENCODE_CCODE) {
495 strcat(buf, "cc ");
496 }
497 if (mask & ENCODE_FP_STATUS) {
498 strcat(buf, "fpcc ");
499 }
500
501 /* Memory bits */
502 if (armLIR && (mask & ENCODE_DALVIK_REG)) {
503 sprintf(buf + strlen(buf), "dr%d%s", armLIR->aliasInfo & 0xffff,
504 (armLIR->aliasInfo & 0x80000000) ? "(+1)" : "");
505 }
506 if (mask & ENCODE_LITERAL) {
507 strcat(buf, "lit ");
508 }
509
510 if (mask & ENCODE_HEAP_REF) {
511 strcat(buf, "heap ");
512 }
513 if (mask & ENCODE_MUST_NOT_ALIAS) {
514 strcat(buf, "noalias ");
515 }
516 }
517 if (buf[0]) {
518 LOG(INFO) << prefix << ": " << buf;
519 }
520}
521
buzbee52a77fc2012-11-20 19:50:46 -0800522bool BranchUnconditional(LIR* lir)
buzbeeefc63692012-11-14 16:31:52 -0800523{
buzbeecbd6d442012-11-17 14:11:25 -0800524 return ((lir->opcode == kThumbBUncond) || (lir->opcode == kThumb2BUncond));
buzbeeefc63692012-11-14 16:31:52 -0800525}
526
527/* Common initialization routine for an architecture family */
buzbee52a77fc2012-11-20 19:50:46 -0800528bool ArchInit()
buzbeeefc63692012-11-14 16:31:52 -0800529{
530 int i;
531
532 for (i = 0; i < kArmLast; i++) {
533 if (EncodingMap[i].opcode != i) {
534 LOG(FATAL) << "Encoding order for " << EncodingMap[i].name
535 << " is wrong: expecting " << i << ", seeing "
buzbeecbd6d442012-11-17 14:11:25 -0800536 << static_cast<int>(EncodingMap[i].opcode);
buzbeeefc63692012-11-14 16:31:52 -0800537 }
538 }
539
buzbee52a77fc2012-11-20 19:50:46 -0800540 return ArchVariantInit();
buzbeeefc63692012-11-14 16:31:52 -0800541}
542
543/* Architecture-specific initializations and checks go here */
buzbee52a77fc2012-11-20 19:50:46 -0800544bool ArchVariantInit(void)
buzbeeefc63692012-11-14 16:31:52 -0800545{
546 return true;
547}
548
buzbeeefc63692012-11-14 16:31:52 -0800549/*
550 * Alloc a pair of core registers, or a double. Low reg in low byte,
551 * high reg in next byte.
552 */
buzbee52a77fc2012-11-20 19:50:46 -0800553int AllocTypedTempPair(CompilationUnit* cUnit, bool fpHint, int regClass)
buzbeeefc63692012-11-14 16:31:52 -0800554{
555 int highReg;
556 int lowReg;
557 int res = 0;
558
559 if (((regClass == kAnyReg) && fpHint) || (regClass == kFPReg)) {
buzbee52a77fc2012-11-20 19:50:46 -0800560 lowReg = AllocTempDouble(cUnit);
buzbeeefc63692012-11-14 16:31:52 -0800561 highReg = lowReg + 1;
562 } else {
buzbee52a77fc2012-11-20 19:50:46 -0800563 lowReg = AllocTemp(cUnit);
564 highReg = AllocTemp(cUnit);
buzbeeefc63692012-11-14 16:31:52 -0800565 }
566 res = (lowReg & 0xff) | ((highReg & 0xff) << 8);
567 return res;
568}
569
buzbee52a77fc2012-11-20 19:50:46 -0800570int AllocTypedTemp(CompilationUnit* cUnit, bool fpHint, int regClass)
buzbeeefc63692012-11-14 16:31:52 -0800571{
572 if (((regClass == kAnyReg) && fpHint) || (regClass == kFPReg))
buzbee52a77fc2012-11-20 19:50:46 -0800573 return AllocTempFloat(cUnit);
574 return AllocTemp(cUnit);
buzbeeefc63692012-11-14 16:31:52 -0800575}
576
buzbee52a77fc2012-11-20 19:50:46 -0800577void CompilerInitializeRegAlloc(CompilationUnit* cUnit)
buzbeeefc63692012-11-14 16:31:52 -0800578{
579 int numRegs = sizeof(coreRegs)/sizeof(*coreRegs);
buzbee52a77fc2012-11-20 19:50:46 -0800580 int numReserved = sizeof(ReservedRegs)/sizeof(*ReservedRegs);
buzbeeefc63692012-11-14 16:31:52 -0800581 int numTemps = sizeof(coreTemps)/sizeof(*coreTemps);
buzbee52a77fc2012-11-20 19:50:46 -0800582 int numFPRegs = sizeof(FpRegs)/sizeof(*FpRegs);
buzbeeefc63692012-11-14 16:31:52 -0800583 int numFPTemps = sizeof(fpTemps)/sizeof(*fpTemps);
buzbeecbd6d442012-11-17 14:11:25 -0800584 RegisterPool *pool =
buzbee52a77fc2012-11-20 19:50:46 -0800585 static_cast<RegisterPool*>(NewMem(cUnit, sizeof(*pool), true, kAllocRegAlloc));
buzbeeefc63692012-11-14 16:31:52 -0800586 cUnit->regPool = pool;
587 pool->numCoreRegs = numRegs;
buzbeecbd6d442012-11-17 14:11:25 -0800588 pool->coreRegs = reinterpret_cast<RegisterInfo*>
buzbee52a77fc2012-11-20 19:50:46 -0800589 (NewMem(cUnit, numRegs * sizeof(*cUnit->regPool->coreRegs), true, kAllocRegAlloc));
buzbeeefc63692012-11-14 16:31:52 -0800590 pool->numFPRegs = numFPRegs;
buzbeecbd6d442012-11-17 14:11:25 -0800591 pool->FPRegs = static_cast<RegisterInfo*>
buzbee52a77fc2012-11-20 19:50:46 -0800592 (NewMem(cUnit, numFPRegs * sizeof(*cUnit->regPool->FPRegs), true, kAllocRegAlloc));
593 CompilerInitPool(pool->coreRegs, coreRegs, pool->numCoreRegs);
594 CompilerInitPool(pool->FPRegs, FpRegs, pool->numFPRegs);
buzbeeefc63692012-11-14 16:31:52 -0800595 // Keep special registers from being allocated
596 for (int i = 0; i < numReserved; i++) {
buzbee52a77fc2012-11-20 19:50:46 -0800597 if (NO_SUSPEND && (ReservedRegs[i] == rARM_SUSPEND)) {
buzbeeefc63692012-11-14 16:31:52 -0800598 //To measure cost of suspend check
599 continue;
600 }
buzbee52a77fc2012-11-20 19:50:46 -0800601 MarkInUse(cUnit, ReservedRegs[i]);
buzbeeefc63692012-11-14 16:31:52 -0800602 }
603 // Mark temp regs - all others not in use can be used for promotion
604 for (int i = 0; i < numTemps; i++) {
buzbee52a77fc2012-11-20 19:50:46 -0800605 MarkTemp(cUnit, coreTemps[i]);
buzbeeefc63692012-11-14 16:31:52 -0800606 }
607 for (int i = 0; i < numFPTemps; i++) {
buzbee52a77fc2012-11-20 19:50:46 -0800608 MarkTemp(cUnit, fpTemps[i]);
buzbeeefc63692012-11-14 16:31:52 -0800609 }
610
611 // Start allocation at r2 in an attempt to avoid clobbering return values
612 pool->nextCoreReg = r2;
613
614 // Construct the alias map.
buzbeecbd6d442012-11-17 14:11:25 -0800615 cUnit->phiAliasMap = static_cast<int*>
buzbee52a77fc2012-11-20 19:50:46 -0800616 (NewMem(cUnit, cUnit->numSSARegs * sizeof(cUnit->phiAliasMap[0]), false, kAllocDFInfo));
buzbeeefc63692012-11-14 16:31:52 -0800617 for (int i = 0; i < cUnit->numSSARegs; i++) {
618 cUnit->phiAliasMap[i] = i;
619 }
620 for (MIR* phi = cUnit->phiList; phi; phi = phi->meta.phiNext) {
621 int defReg = phi->ssaRep->defs[0];
622 for (int i = 0; i < phi->ssaRep->numUses; i++) {
623 for (int j = 0; j < cUnit->numSSARegs; j++) {
624 if (cUnit->phiAliasMap[j] == phi->ssaRep->uses[i]) {
625 cUnit->phiAliasMap[j] = defReg;
626 }
627 }
628 }
629 }
630}
631
buzbee52a77fc2012-11-20 19:50:46 -0800632void FreeRegLocTemps(CompilationUnit* cUnit, RegLocation rlKeep,
buzbeeefc63692012-11-14 16:31:52 -0800633 RegLocation rlFree)
634{
635 if ((rlFree.lowReg != rlKeep.lowReg) && (rlFree.lowReg != rlKeep.highReg) &&
636 (rlFree.highReg != rlKeep.lowReg) && (rlFree.highReg != rlKeep.highReg)) {
637 // No overlap, free both
buzbee52a77fc2012-11-20 19:50:46 -0800638 FreeTemp(cUnit, rlFree.lowReg);
639 FreeTemp(cUnit, rlFree.highReg);
buzbeeefc63692012-11-14 16:31:52 -0800640 }
641}
642/*
643 * TUNING: is leaf? Can't just use "hasInvoke" to determine as some
644 * instructions might call out to C/assembly helper functions. Until
645 * machinery is in place, always spill lr.
646 */
647
buzbee52a77fc2012-11-20 19:50:46 -0800648void AdjustSpillMask(CompilationUnit* cUnit)
buzbeeefc63692012-11-14 16:31:52 -0800649{
650 cUnit->coreSpillMask |= (1 << rARM_LR);
651 cUnit->numCoreSpills++;
652}
653
654/*
655 * Mark a callee-save fp register as promoted. Note that
656 * vpush/vpop uses contiguous register lists so we must
657 * include any holes in the mask. Associate holes with
658 * Dalvik register INVALID_VREG (0xFFFFU).
659 */
buzbee52a77fc2012-11-20 19:50:46 -0800660void MarkPreservedSingle(CompilationUnit* cUnit, int vReg, int reg)
buzbeeefc63692012-11-14 16:31:52 -0800661{
662 DCHECK_GE(reg, ARM_FP_REG_MASK + ARM_FP_CALLEE_SAVE_BASE);
663 reg = (reg & ARM_FP_REG_MASK) - ARM_FP_CALLEE_SAVE_BASE;
664 // Ensure fpVmapTable is large enough
665 int tableSize = cUnit->fpVmapTable.size();
666 for (int i = tableSize; i < (reg + 1); i++) {
667 cUnit->fpVmapTable.push_back(INVALID_VREG);
668 }
669 // Add the current mapping
670 cUnit->fpVmapTable[reg] = vReg;
671 // Size of fpVmapTable is high-water mark, use to set mask
672 cUnit->numFPSpills = cUnit->fpVmapTable.size();
673 cUnit->fpSpillMask = ((1 << cUnit->numFPSpills) - 1) << ARM_FP_CALLEE_SAVE_BASE;
674}
675
buzbee52a77fc2012-11-20 19:50:46 -0800676void FlushRegWide(CompilationUnit* cUnit, int reg1, int reg2)
buzbeeefc63692012-11-14 16:31:52 -0800677{
buzbee52a77fc2012-11-20 19:50:46 -0800678 RegisterInfo* info1 = GetRegInfo(cUnit, reg1);
679 RegisterInfo* info2 = GetRegInfo(cUnit, reg2);
buzbeeefc63692012-11-14 16:31:52 -0800680 DCHECK(info1 && info2 && info1->pair && info2->pair &&
681 (info1->partner == info2->reg) &&
682 (info2->partner == info1->reg));
683 if ((info1->live && info1->dirty) || (info2->live && info2->dirty)) {
684 if (!(info1->isTemp && info2->isTemp)) {
685 /* Should not happen. If it does, there's a problem in evalLoc */
686 LOG(FATAL) << "Long half-temp, half-promoted";
687 }
688
689 info1->dirty = false;
690 info2->dirty = false;
691 if (SRegToVReg(cUnit, info2->sReg) <
692 SRegToVReg(cUnit, info1->sReg))
693 info1 = info2;
694 int vReg = SRegToVReg(cUnit, info1->sReg);
buzbee52a77fc2012-11-20 19:50:46 -0800695 StoreBaseDispWide(cUnit, rARM_SP, VRegOffset(cUnit, vReg), info1->reg, info1->partner);
buzbeeefc63692012-11-14 16:31:52 -0800696 }
697}
698
buzbee52a77fc2012-11-20 19:50:46 -0800699void FlushReg(CompilationUnit* cUnit, int reg)
buzbeeefc63692012-11-14 16:31:52 -0800700{
buzbee52a77fc2012-11-20 19:50:46 -0800701 RegisterInfo* info = GetRegInfo(cUnit, reg);
buzbeeefc63692012-11-14 16:31:52 -0800702 if (info->live && info->dirty) {
703 info->dirty = false;
704 int vReg = SRegToVReg(cUnit, info->sReg);
buzbee52a77fc2012-11-20 19:50:46 -0800705 StoreBaseDisp(cUnit, rARM_SP, VRegOffset(cUnit, vReg), reg, kWord);
buzbeeefc63692012-11-14 16:31:52 -0800706 }
707}
708
709/* Give access to the target-dependent FP register encoding to common code */
buzbee52a77fc2012-11-20 19:50:46 -0800710bool IsFpReg(int reg) {
buzbeeefc63692012-11-14 16:31:52 -0800711 return ARM_FPREG(reg);
712}
713
buzbeeefc63692012-11-14 16:31:52 -0800714/* Clobber all regs that might be used by an external C call */
buzbee52a77fc2012-11-20 19:50:46 -0800715void ClobberCalleeSave(CompilationUnit *cUnit)
buzbeeefc63692012-11-14 16:31:52 -0800716{
buzbee52a77fc2012-11-20 19:50:46 -0800717 Clobber(cUnit, r0);
718 Clobber(cUnit, r1);
719 Clobber(cUnit, r2);
720 Clobber(cUnit, r3);
721 Clobber(cUnit, r12);
722 Clobber(cUnit, r14lr);
723 Clobber(cUnit, fr0);
724 Clobber(cUnit, fr1);
725 Clobber(cUnit, fr2);
726 Clobber(cUnit, fr3);
727 Clobber(cUnit, fr4);
728 Clobber(cUnit, fr5);
729 Clobber(cUnit, fr6);
730 Clobber(cUnit, fr7);
731 Clobber(cUnit, fr8);
732 Clobber(cUnit, fr9);
733 Clobber(cUnit, fr10);
734 Clobber(cUnit, fr11);
735 Clobber(cUnit, fr12);
736 Clobber(cUnit, fr13);
737 Clobber(cUnit, fr14);
738 Clobber(cUnit, fr15);
buzbeeefc63692012-11-14 16:31:52 -0800739}
740
buzbeeaad94382012-11-21 07:40:50 -0800741RegLocation GetReturnWideAlt(CompilationUnit* cUnit)
buzbeeefc63692012-11-14 16:31:52 -0800742{
buzbee52a77fc2012-11-20 19:50:46 -0800743 RegLocation res = LocCReturnWide();
buzbeeefc63692012-11-14 16:31:52 -0800744 res.lowReg = r2;
745 res.highReg = r3;
buzbee52a77fc2012-11-20 19:50:46 -0800746 Clobber(cUnit, r2);
747 Clobber(cUnit, r3);
748 MarkInUse(cUnit, r2);
749 MarkInUse(cUnit, r3);
750 MarkPair(cUnit, res.lowReg, res.highReg);
buzbeeefc63692012-11-14 16:31:52 -0800751 return res;
752}
753
buzbeeaad94382012-11-21 07:40:50 -0800754RegLocation GetReturnAlt(CompilationUnit* cUnit)
buzbeeefc63692012-11-14 16:31:52 -0800755{
buzbee52a77fc2012-11-20 19:50:46 -0800756 RegLocation res = LocCReturn();
buzbeeefc63692012-11-14 16:31:52 -0800757 res.lowReg = r1;
buzbee52a77fc2012-11-20 19:50:46 -0800758 Clobber(cUnit, r1);
759 MarkInUse(cUnit, r1);
buzbeeefc63692012-11-14 16:31:52 -0800760 return res;
761}
762
buzbeeaad94382012-11-21 07:40:50 -0800763RegisterInfo* GetRegInfo(CompilationUnit* cUnit, int reg)
buzbeeefc63692012-11-14 16:31:52 -0800764{
765 return ARM_FPREG(reg) ? &cUnit->regPool->FPRegs[reg & ARM_FP_REG_MASK]
766 : &cUnit->regPool->coreRegs[reg];
767}
768
769/* To be used when explicitly managing register use */
buzbeeaad94382012-11-21 07:40:50 -0800770void LockCallTemps(CompilationUnit* cUnit)
buzbeeefc63692012-11-14 16:31:52 -0800771{
buzbee52a77fc2012-11-20 19:50:46 -0800772 LockTemp(cUnit, r0);
773 LockTemp(cUnit, r1);
774 LockTemp(cUnit, r2);
775 LockTemp(cUnit, r3);
buzbeeefc63692012-11-14 16:31:52 -0800776}
777
778/* To be used when explicitly managing register use */
buzbeeaad94382012-11-21 07:40:50 -0800779void FreeCallTemps(CompilationUnit* cUnit)
buzbeeefc63692012-11-14 16:31:52 -0800780{
buzbee52a77fc2012-11-20 19:50:46 -0800781 FreeTemp(cUnit, r0);
782 FreeTemp(cUnit, r1);
783 FreeTemp(cUnit, r2);
784 FreeTemp(cUnit, r3);
buzbeeefc63692012-11-14 16:31:52 -0800785}
786
buzbee52a77fc2012-11-20 19:50:46 -0800787int LoadHelper(CompilationUnit* cUnit, int offset)
buzbeeefc63692012-11-14 16:31:52 -0800788{
buzbee52a77fc2012-11-20 19:50:46 -0800789 LoadWordDisp(cUnit, rARM_SELF, offset, rARM_LR);
buzbeeefc63692012-11-14 16:31:52 -0800790 return rARM_LR;
791}
792
buzbee52a77fc2012-11-20 19:50:46 -0800793uint64_t GetTargetInstFlags(int opcode)
buzbee1bc37c62012-11-20 13:35:41 -0800794{
795 return EncodingMap[opcode].flags;
796}
797
buzbee52a77fc2012-11-20 19:50:46 -0800798const char* GetTargetInstName(int opcode)
buzbee1bc37c62012-11-20 13:35:41 -0800799{
800 return EncodingMap[opcode].name;
801}
802
buzbee52a77fc2012-11-20 19:50:46 -0800803const char* GetTargetInstFmt(int opcode)
buzbee1bc37c62012-11-20 13:35:41 -0800804{
805 return EncodingMap[opcode].fmt;
806}
807
buzbeeefc63692012-11-14 16:31:52 -0800808} // namespace art