1 /* 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 <string> 18 19 #include "arm_lir.h" 20 #include "codegen_arm.h" 21 #include "dex/compiler_internals.h" 22 #include "dex/quick/mir_to_lir-inl.h" 23 24 namespace art { 25 26 static int core_regs[] = {r0, r1, r2, r3, rARM_SUSPEND, r5, r6, r7, r8, rARM_SELF, r10, 27 r11, r12, rARM_SP, rARM_LR, rARM_PC}; 28 static int ReservedRegs[] = {rARM_SUSPEND, rARM_SELF, rARM_SP, rARM_LR, rARM_PC}; 29 static int FpRegs[] = {fr0, fr1, fr2, fr3, fr4, fr5, fr6, fr7, 30 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}; 33 static int core_temps[] = {r0, r1, r2, r3, r12}; 34 static int fp_temps[] = {fr0, fr1, fr2, fr3, fr4, fr5, fr6, fr7, 35 fr8, fr9, fr10, fr11, fr12, fr13, fr14, fr15}; 36 37 RegLocation ArmMir2Lir::LocCReturn() { 38 RegLocation res = ARM_LOC_C_RETURN; 39 return res; 40 } 41 42 RegLocation ArmMir2Lir::LocCReturnWide() { 43 RegLocation res = ARM_LOC_C_RETURN_WIDE; 44 return res; 45 } 46 47 RegLocation ArmMir2Lir::LocCReturnFloat() { 48 RegLocation res = ARM_LOC_C_RETURN_FLOAT; 49 return res; 50 } 51 52 RegLocation ArmMir2Lir::LocCReturnDouble() { 53 RegLocation res = ARM_LOC_C_RETURN_DOUBLE; 54 return res; 55 } 56 57 // Return a target-dependent special register. 58 int ArmMir2Lir::TargetReg(SpecialTargetRegister reg) { 59 int res = INVALID_REG; 60 switch (reg) { 61 case kSelf: res = rARM_SELF; break; 62 case kSuspend: res = rARM_SUSPEND; break; 63 case kLr: res = rARM_LR; break; 64 case kPc: res = rARM_PC; break; 65 case kSp: res = rARM_SP; break; 66 case kArg0: res = rARM_ARG0; break; 67 case kArg1: res = rARM_ARG1; break; 68 case kArg2: res = rARM_ARG2; break; 69 case kArg3: res = rARM_ARG3; break; 70 case kFArg0: res = rARM_FARG0; break; 71 case kFArg1: res = rARM_FARG1; break; 72 case kFArg2: res = rARM_FARG2; break; 73 case kFArg3: res = rARM_FARG3; break; 74 case kRet0: res = rARM_RET0; break; 75 case kRet1: res = rARM_RET1; break; 76 case kInvokeTgt: res = rARM_INVOKE_TGT; break; 77 case kCount: res = rARM_COUNT; break; 78 } 79 return res; 80 } 81 82 83 // Create a double from a pair of singles. 84 int ArmMir2Lir::S2d(int low_reg, int high_reg) { 85 return ARM_S2D(low_reg, high_reg); 86 } 87 88 // Return mask to strip off fp reg flags and bias. 89 uint32_t ArmMir2Lir::FpRegMask() { 90 return ARM_FP_REG_MASK; 91 } 92 93 // True if both regs single, both core or both double. 94 bool ArmMir2Lir::SameRegType(int reg1, int reg2) { 95 return (ARM_REGTYPE(reg1) == ARM_REGTYPE(reg2)); 96 } 97 98 /* 99 * Decode the register id. 100 */ 101 uint64_t ArmMir2Lir::GetRegMaskCommon(int reg) { 102 uint64_t seed; 103 int shift; 104 int reg_id; 105 106 107 reg_id = reg & 0x1f; 108 /* Each double register is equal to a pair of single-precision FP registers */ 109 seed = ARM_DOUBLEREG(reg) ? 3 : 1; 110 /* FP register starts at bit position 16 */ 111 shift = ARM_FPREG(reg) ? kArmFPReg0 : 0; 112 /* Expand the double register id into single offset */ 113 shift += reg_id; 114 return (seed << shift); 115 } 116 117 uint64_t ArmMir2Lir::GetPCUseDefEncoding() { 118 return ENCODE_ARM_REG_PC; 119 } 120 121 void ArmMir2Lir::SetupTargetResourceMasks(LIR* lir) { 122 DCHECK_EQ(cu_->instruction_set, kThumb2); 123 124 // Thumb2 specific setup 125 uint64_t flags = ArmMir2Lir::EncodingMap[lir->opcode].flags; 126 int opcode = lir->opcode; 127 128 if (flags & REG_DEF_SP) { 129 lir->def_mask |= ENCODE_ARM_REG_SP; 130 } 131 132 if (flags & REG_USE_SP) { 133 lir->use_mask |= ENCODE_ARM_REG_SP; 134 } 135 136 if (flags & REG_DEF_LIST0) { 137 lir->def_mask |= ENCODE_ARM_REG_LIST(lir->operands[0]); 138 } 139 140 if (flags & REG_DEF_LIST1) { 141 lir->def_mask |= ENCODE_ARM_REG_LIST(lir->operands[1]); 142 } 143 144 if (flags & REG_DEF_FPCS_LIST0) { 145 lir->def_mask |= ENCODE_ARM_REG_FPCS_LIST(lir->operands[0]); 146 } 147 148 if (flags & REG_DEF_FPCS_LIST2) { 149 for (int i = 0; i < lir->operands[2]; i++) { 150 SetupRegMask(&lir->def_mask, lir->operands[1] + i); 151 } 152 } 153 154 if (flags & REG_USE_PC) { 155 lir->use_mask |= ENCODE_ARM_REG_PC; 156 } 157 158 /* Conservatively treat the IT block */ 159 if (flags & IS_IT) { 160 lir->def_mask = ENCODE_ALL; 161 } 162 163 if (flags & REG_USE_LIST0) { 164 lir->use_mask |= ENCODE_ARM_REG_LIST(lir->operands[0]); 165 } 166 167 if (flags & REG_USE_LIST1) { 168 lir->use_mask |= ENCODE_ARM_REG_LIST(lir->operands[1]); 169 } 170 171 if (flags & REG_USE_FPCS_LIST0) { 172 lir->use_mask |= ENCODE_ARM_REG_FPCS_LIST(lir->operands[0]); 173 } 174 175 if (flags & REG_USE_FPCS_LIST2) { 176 for (int i = 0; i < lir->operands[2]; i++) { 177 SetupRegMask(&lir->use_mask, lir->operands[1] + i); 178 } 179 } 180 /* Fixup for kThumbPush/lr and kThumbPop/pc */ 181 if (opcode == kThumbPush || opcode == kThumbPop) { 182 uint64_t r8Mask = GetRegMaskCommon(r8); 183 if ((opcode == kThumbPush) && (lir->use_mask & r8Mask)) { 184 lir->use_mask &= ~r8Mask; 185 lir->use_mask |= ENCODE_ARM_REG_LR; 186 } else if ((opcode == kThumbPop) && (lir->def_mask & r8Mask)) { 187 lir->def_mask &= ~r8Mask; 188 lir->def_mask |= ENCODE_ARM_REG_PC; 189 } 190 } 191 if (flags & REG_DEF_LR) { 192 lir->def_mask |= ENCODE_ARM_REG_LR; 193 } 194 } 195 196 ArmConditionCode ArmMir2Lir::ArmConditionEncoding(ConditionCode ccode) { 197 ArmConditionCode res; 198 switch (ccode) { 199 case kCondEq: res = kArmCondEq; break; 200 case kCondNe: res = kArmCondNe; break; 201 case kCondCs: res = kArmCondCs; break; 202 case kCondCc: res = kArmCondCc; break; 203 case kCondMi: res = kArmCondMi; break; 204 case kCondPl: res = kArmCondPl; break; 205 case kCondVs: res = kArmCondVs; break; 206 case kCondVc: res = kArmCondVc; break; 207 case kCondHi: res = kArmCondHi; break; 208 case kCondLs: res = kArmCondLs; break; 209 case kCondGe: res = kArmCondGe; break; 210 case kCondLt: res = kArmCondLt; break; 211 case kCondGt: res = kArmCondGt; break; 212 case kCondLe: res = kArmCondLe; break; 213 case kCondAl: res = kArmCondAl; break; 214 case kCondNv: res = kArmCondNv; break; 215 default: 216 LOG(FATAL) << "Bad condition code " << ccode; 217 res = static_cast<ArmConditionCode>(0); // Quiet gcc 218 } 219 return res; 220 } 221 222 static const char* core_reg_names[16] = { 223 "r0", 224 "r1", 225 "r2", 226 "r3", 227 "r4", 228 "r5", 229 "r6", 230 "r7", 231 "r8", 232 "rSELF", 233 "r10", 234 "r11", 235 "r12", 236 "sp", 237 "lr", 238 "pc", 239 }; 240 241 242 static const char* shift_names[4] = { 243 "lsl", 244 "lsr", 245 "asr", 246 "ror"}; 247 248 /* Decode and print a ARM register name */ 249 static char* DecodeRegList(int opcode, int vector, char* buf) { 250 int i; 251 bool printed = false; 252 buf[0] = 0; 253 for (i = 0; i < 16; i++, vector >>= 1) { 254 if (vector & 0x1) { 255 int reg_id = i; 256 if (opcode == kThumbPush && i == 8) { 257 reg_id = r14lr; 258 } else if (opcode == kThumbPop && i == 8) { 259 reg_id = r15pc; 260 } 261 if (printed) { 262 sprintf(buf + strlen(buf), ", r%d", reg_id); 263 } else { 264 printed = true; 265 sprintf(buf, "r%d", reg_id); 266 } 267 } 268 } 269 return buf; 270 } 271 272 static char* DecodeFPCSRegList(int count, int base, char* buf) { 273 sprintf(buf, "s%d", base); 274 for (int i = 1; i < count; i++) { 275 sprintf(buf + strlen(buf), ", s%d", base + i); 276 } 277 return buf; 278 } 279 280 static int ExpandImmediate(int value) { 281 int mode = (value & 0xf00) >> 8; 282 uint32_t bits = value & 0xff; 283 switch (mode) { 284 case 0: 285 return bits; 286 case 1: 287 return (bits << 16) | bits; 288 case 2: 289 return (bits << 24) | (bits << 8); 290 case 3: 291 return (bits << 24) | (bits << 16) | (bits << 8) | bits; 292 default: 293 break; 294 } 295 bits = (bits | 0x80) << 24; 296 return bits >> (((value & 0xf80) >> 7) - 8); 297 } 298 299 const char* cc_names[] = {"eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc", 300 "hi", "ls", "ge", "lt", "gt", "le", "al", "nv"}; 301 /* 302 * Interpret a format string and build a string no longer than size 303 * See format key in Assemble.c. 304 */ 305 std::string ArmMir2Lir::BuildInsnString(const char* fmt, LIR* lir, unsigned char* base_addr) { 306 std::string buf; 307 int i; 308 const char* fmt_end = &fmt[strlen(fmt)]; 309 char tbuf[256]; 310 const char* name; 311 char nc; 312 while (fmt < fmt_end) { 313 int operand; 314 if (*fmt == '!') { 315 fmt++; 316 DCHECK_LT(fmt, fmt_end); 317 nc = *fmt++; 318 if (nc == '!') { 319 strcpy(tbuf, "!"); 320 } else { 321 DCHECK_LT(fmt, fmt_end); 322 DCHECK_LT(static_cast<unsigned>(nc-'0'), 4U); 323 operand = lir->operands[nc-'0']; 324 switch (*fmt++) { 325 case 'H': 326 if (operand != 0) { 327 sprintf(tbuf, ", %s %d", shift_names[operand & 0x3], operand >> 2); 328 } else { 329 strcpy(tbuf, ""); 330 } 331 break; 332 case 'B': 333 switch (operand) { 334 case kSY: 335 name = "sy"; 336 break; 337 case kST: 338 name = "st"; 339 break; 340 case kISH: 341 name = "ish"; 342 break; 343 case kISHST: 344 name = "ishst"; 345 break; 346 case kNSH: 347 name = "nsh"; 348 break; 349 case kNSHST: 350 name = "shst"; 351 break; 352 default: 353 name = "DecodeError2"; 354 break; 355 } 356 strcpy(tbuf, name); 357 break; 358 case 'b': 359 strcpy(tbuf, "0000"); 360 for (i = 3; i >= 0; i--) { 361 tbuf[i] += operand & 1; 362 operand >>= 1; 363 } 364 break; 365 case 'n': 366 operand = ~ExpandImmediate(operand); 367 sprintf(tbuf, "%d [%#x]", operand, operand); 368 break; 369 case 'm': 370 operand = ExpandImmediate(operand); 371 sprintf(tbuf, "%d [%#x]", operand, operand); 372 break; 373 case 's': 374 sprintf(tbuf, "s%d", operand & ARM_FP_REG_MASK); 375 break; 376 case 'S': 377 sprintf(tbuf, "d%d", (operand & ARM_FP_REG_MASK) >> 1); 378 break; 379 case 'h': 380 sprintf(tbuf, "%04x", operand); 381 break; 382 case 'M': 383 case 'd': 384 sprintf(tbuf, "%d", operand); 385 break; 386 case 'C': 387 DCHECK_LT(operand, static_cast<int>( 388 sizeof(core_reg_names)/sizeof(core_reg_names[0]))); 389 sprintf(tbuf, "%s", core_reg_names[operand]); 390 break; 391 case 'E': 392 sprintf(tbuf, "%d", operand*4); 393 break; 394 case 'F': 395 sprintf(tbuf, "%d", operand*2); 396 break; 397 case 'c': 398 strcpy(tbuf, cc_names[operand]); 399 break; 400 case 't': 401 sprintf(tbuf, "0x%08x (L%p)", 402 reinterpret_cast<uintptr_t>(base_addr) + lir->offset + 4 + 403 (operand << 1), 404 lir->target); 405 break; 406 case 'u': { 407 int offset_1 = lir->operands[0]; 408 int offset_2 = NEXT_LIR(lir)->operands[0]; 409 uintptr_t target = 410 (((reinterpret_cast<uintptr_t>(base_addr) + lir->offset + 4) & 411 ~3) + (offset_1 << 21 >> 9) + (offset_2 << 1)) & 412 0xfffffffc; 413 sprintf(tbuf, "%p", reinterpret_cast<void *>(target)); 414 break; 415 } 416 417 /* Nothing to print for BLX_2 */ 418 case 'v': 419 strcpy(tbuf, "see above"); 420 break; 421 case 'R': 422 DecodeRegList(lir->opcode, operand, tbuf); 423 break; 424 case 'P': 425 DecodeFPCSRegList(operand, 16, tbuf); 426 break; 427 case 'Q': 428 DecodeFPCSRegList(operand, 0, tbuf); 429 break; 430 default: 431 strcpy(tbuf, "DecodeError1"); 432 break; 433 } 434 buf += tbuf; 435 } 436 } else { 437 buf += *fmt++; 438 } 439 } 440 return buf; 441 } 442 443 void ArmMir2Lir::DumpResourceMask(LIR* arm_lir, uint64_t mask, const char* prefix) { 444 char buf[256]; 445 buf[0] = 0; 446 447 if (mask == ENCODE_ALL) { 448 strcpy(buf, "all"); 449 } else { 450 char num[8]; 451 int i; 452 453 for (i = 0; i < kArmRegEnd; i++) { 454 if (mask & (1ULL << i)) { 455 sprintf(num, "%d ", i); 456 strcat(buf, num); 457 } 458 } 459 460 if (mask & ENCODE_CCODE) { 461 strcat(buf, "cc "); 462 } 463 if (mask & ENCODE_FP_STATUS) { 464 strcat(buf, "fpcc "); 465 } 466 467 /* Memory bits */ 468 if (arm_lir && (mask & ENCODE_DALVIK_REG)) { 469 sprintf(buf + strlen(buf), "dr%d%s", arm_lir->alias_info & 0xffff, 470 (arm_lir->alias_info & 0x80000000) ? "(+1)" : ""); 471 } 472 if (mask & ENCODE_LITERAL) { 473 strcat(buf, "lit "); 474 } 475 476 if (mask & ENCODE_HEAP_REF) { 477 strcat(buf, "heap "); 478 } 479 if (mask & ENCODE_MUST_NOT_ALIAS) { 480 strcat(buf, "noalias "); 481 } 482 } 483 if (buf[0]) { 484 LOG(INFO) << prefix << ": " << buf; 485 } 486 } 487 488 bool ArmMir2Lir::IsUnconditionalBranch(LIR* lir) { 489 return ((lir->opcode == kThumbBUncond) || (lir->opcode == kThumb2BUncond)); 490 } 491 492 ArmMir2Lir::ArmMir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena) 493 : Mir2Lir(cu, mir_graph, arena) { 494 // Sanity check - make sure encoding map lines up. 495 for (int i = 0; i < kArmLast; i++) { 496 if (ArmMir2Lir::EncodingMap[i].opcode != i) { 497 LOG(FATAL) << "Encoding order for " << ArmMir2Lir::EncodingMap[i].name 498 << " is wrong: expecting " << i << ", seeing " 499 << static_cast<int>(ArmMir2Lir::EncodingMap[i].opcode); 500 } 501 } 502 } 503 504 Mir2Lir* ArmCodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph, 505 ArenaAllocator* const arena) { 506 return new ArmMir2Lir(cu, mir_graph, arena); 507 } 508 509 /* 510 * Alloc a pair of core registers, or a double. Low reg in low byte, 511 * high reg in next byte. 512 */ 513 int ArmMir2Lir::AllocTypedTempPair(bool fp_hint, int reg_class) { 514 int high_reg; 515 int low_reg; 516 int res = 0; 517 518 if (((reg_class == kAnyReg) && fp_hint) || (reg_class == kFPReg)) { 519 low_reg = AllocTempDouble(); 520 high_reg = low_reg + 1; 521 } else { 522 low_reg = AllocTemp(); 523 high_reg = AllocTemp(); 524 } 525 res = (low_reg & 0xff) | ((high_reg & 0xff) << 8); 526 return res; 527 } 528 529 int ArmMir2Lir::AllocTypedTemp(bool fp_hint, int reg_class) { 530 if (((reg_class == kAnyReg) && fp_hint) || (reg_class == kFPReg)) 531 return AllocTempFloat(); 532 return AllocTemp(); 533 } 534 535 void ArmMir2Lir::CompilerInitializeRegAlloc() { 536 int num_regs = sizeof(core_regs)/sizeof(*core_regs); 537 int num_reserved = sizeof(ReservedRegs)/sizeof(*ReservedRegs); 538 int num_temps = sizeof(core_temps)/sizeof(*core_temps); 539 int num_fp_regs = sizeof(FpRegs)/sizeof(*FpRegs); 540 int num_fp_temps = sizeof(fp_temps)/sizeof(*fp_temps); 541 reg_pool_ = static_cast<RegisterPool*>(arena_->Alloc(sizeof(*reg_pool_), 542 ArenaAllocator::kAllocRegAlloc)); 543 reg_pool_->num_core_regs = num_regs; 544 reg_pool_->core_regs = reinterpret_cast<RegisterInfo*> 545 (arena_->Alloc(num_regs * sizeof(*reg_pool_->core_regs), ArenaAllocator::kAllocRegAlloc)); 546 reg_pool_->num_fp_regs = num_fp_regs; 547 reg_pool_->FPRegs = static_cast<RegisterInfo*> 548 (arena_->Alloc(num_fp_regs * sizeof(*reg_pool_->FPRegs), ArenaAllocator::kAllocRegAlloc)); 549 CompilerInitPool(reg_pool_->core_regs, core_regs, reg_pool_->num_core_regs); 550 CompilerInitPool(reg_pool_->FPRegs, FpRegs, reg_pool_->num_fp_regs); 551 // Keep special registers from being allocated 552 for (int i = 0; i < num_reserved; i++) { 553 if (NO_SUSPEND && (ReservedRegs[i] == rARM_SUSPEND)) { 554 // To measure cost of suspend check 555 continue; 556 } 557 MarkInUse(ReservedRegs[i]); 558 } 559 // Mark temp regs - all others not in use can be used for promotion 560 for (int i = 0; i < num_temps; i++) { 561 MarkTemp(core_temps[i]); 562 } 563 for (int i = 0; i < num_fp_temps; i++) { 564 MarkTemp(fp_temps[i]); 565 } 566 567 // Start allocation at r2 in an attempt to avoid clobbering return values 568 reg_pool_->next_core_reg = r2; 569 } 570 571 void ArmMir2Lir::FreeRegLocTemps(RegLocation rl_keep, 572 RegLocation rl_free) { 573 if ((rl_free.low_reg != rl_keep.low_reg) && (rl_free.low_reg != rl_keep.high_reg) && 574 (rl_free.high_reg != rl_keep.low_reg) && (rl_free.high_reg != rl_keep.high_reg)) { 575 // No overlap, free both 576 FreeTemp(rl_free.low_reg); 577 FreeTemp(rl_free.high_reg); 578 } 579 } 580 /* 581 * TUNING: is true leaf? Can't just use METHOD_IS_LEAF to determine as some 582 * instructions might call out to C/assembly helper functions. Until 583 * machinery is in place, always spill lr. 584 */ 585 586 void ArmMir2Lir::AdjustSpillMask() { 587 core_spill_mask_ |= (1 << rARM_LR); 588 num_core_spills_++; 589 } 590 591 /* 592 * Mark a callee-save fp register as promoted. Note that 593 * vpush/vpop uses contiguous register lists so we must 594 * include any holes in the mask. Associate holes with 595 * Dalvik register INVALID_VREG (0xFFFFU). 596 */ 597 void ArmMir2Lir::MarkPreservedSingle(int v_reg, int reg) { 598 DCHECK_GE(reg, ARM_FP_REG_MASK + ARM_FP_CALLEE_SAVE_BASE); 599 reg = (reg & ARM_FP_REG_MASK) - ARM_FP_CALLEE_SAVE_BASE; 600 // Ensure fp_vmap_table is large enough 601 int table_size = fp_vmap_table_.size(); 602 for (int i = table_size; i < (reg + 1); i++) { 603 fp_vmap_table_.push_back(INVALID_VREG); 604 } 605 // Add the current mapping 606 fp_vmap_table_[reg] = v_reg; 607 // Size of fp_vmap_table is high-water mark, use to set mask 608 num_fp_spills_ = fp_vmap_table_.size(); 609 fp_spill_mask_ = ((1 << num_fp_spills_) - 1) << ARM_FP_CALLEE_SAVE_BASE; 610 } 611 612 void ArmMir2Lir::FlushRegWide(int reg1, int reg2) { 613 RegisterInfo* info1 = GetRegInfo(reg1); 614 RegisterInfo* info2 = GetRegInfo(reg2); 615 DCHECK(info1 && info2 && info1->pair && info2->pair && 616 (info1->partner == info2->reg) && 617 (info2->partner == info1->reg)); 618 if ((info1->live && info1->dirty) || (info2->live && info2->dirty)) { 619 if (!(info1->is_temp && info2->is_temp)) { 620 /* Should not happen. If it does, there's a problem in eval_loc */ 621 LOG(FATAL) << "Long half-temp, half-promoted"; 622 } 623 624 info1->dirty = false; 625 info2->dirty = false; 626 if (mir_graph_->SRegToVReg(info2->s_reg) < 627 mir_graph_->SRegToVReg(info1->s_reg)) 628 info1 = info2; 629 int v_reg = mir_graph_->SRegToVReg(info1->s_reg); 630 StoreBaseDispWide(rARM_SP, VRegOffset(v_reg), info1->reg, info1->partner); 631 } 632 } 633 634 void ArmMir2Lir::FlushReg(int reg) { 635 RegisterInfo* info = GetRegInfo(reg); 636 if (info->live && info->dirty) { 637 info->dirty = false; 638 int v_reg = mir_graph_->SRegToVReg(info->s_reg); 639 StoreBaseDisp(rARM_SP, VRegOffset(v_reg), reg, kWord); 640 } 641 } 642 643 /* Give access to the target-dependent FP register encoding to common code */ 644 bool ArmMir2Lir::IsFpReg(int reg) { 645 return ARM_FPREG(reg); 646 } 647 648 /* Clobber all regs that might be used by an external C call */ 649 void ArmMir2Lir::ClobberCalleeSave() { 650 Clobber(r0); 651 Clobber(r1); 652 Clobber(r2); 653 Clobber(r3); 654 Clobber(r12); 655 Clobber(r14lr); 656 Clobber(fr0); 657 Clobber(fr1); 658 Clobber(fr2); 659 Clobber(fr3); 660 Clobber(fr4); 661 Clobber(fr5); 662 Clobber(fr6); 663 Clobber(fr7); 664 Clobber(fr8); 665 Clobber(fr9); 666 Clobber(fr10); 667 Clobber(fr11); 668 Clobber(fr12); 669 Clobber(fr13); 670 Clobber(fr14); 671 Clobber(fr15); 672 } 673 674 RegLocation ArmMir2Lir::GetReturnWideAlt() { 675 RegLocation res = LocCReturnWide(); 676 res.low_reg = r2; 677 res.high_reg = r3; 678 Clobber(r2); 679 Clobber(r3); 680 MarkInUse(r2); 681 MarkInUse(r3); 682 MarkPair(res.low_reg, res.high_reg); 683 return res; 684 } 685 686 RegLocation ArmMir2Lir::GetReturnAlt() { 687 RegLocation res = LocCReturn(); 688 res.low_reg = r1; 689 Clobber(r1); 690 MarkInUse(r1); 691 return res; 692 } 693 694 ArmMir2Lir::RegisterInfo* ArmMir2Lir::GetRegInfo(int reg) { 695 return ARM_FPREG(reg) ? ®_pool_->FPRegs[reg & ARM_FP_REG_MASK] 696 : ®_pool_->core_regs[reg]; 697 } 698 699 /* To be used when explicitly managing register use */ 700 void ArmMir2Lir::LockCallTemps() { 701 LockTemp(r0); 702 LockTemp(r1); 703 LockTemp(r2); 704 LockTemp(r3); 705 } 706 707 /* To be used when explicitly managing register use */ 708 void ArmMir2Lir::FreeCallTemps() { 709 FreeTemp(r0); 710 FreeTemp(r1); 711 FreeTemp(r2); 712 FreeTemp(r3); 713 } 714 715 int ArmMir2Lir::LoadHelper(ThreadOffset offset) { 716 LoadWordDisp(rARM_SELF, offset.Int32Value(), rARM_LR); 717 return rARM_LR; 718 } 719 720 uint64_t ArmMir2Lir::GetTargetInstFlags(int opcode) { 721 return ArmMir2Lir::EncodingMap[opcode].flags; 722 } 723 724 const char* ArmMir2Lir::GetTargetInstName(int opcode) { 725 return ArmMir2Lir::EncodingMap[opcode].name; 726 } 727 728 const char* ArmMir2Lir::GetTargetInstFmt(int opcode) { 729 return ArmMir2Lir::EncodingMap[opcode].fmt; 730 } 731 732 } // namespace art 733