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