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