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 "codegen_arm.h" 18 19#include <inttypes.h> 20 21#include <string> 22#include <sstream> 23 24#include "backend_arm.h" 25#include "base/logging.h" 26#include "dex/mir_graph.h" 27#include "dex/quick/mir_to_lir-inl.h" 28 29namespace art { 30 31#ifdef ARM_R4_SUSPEND_FLAG 32static constexpr RegStorage core_regs_arr[] = 33 {rs_r0, rs_r1, rs_r2, rs_r3, rs_rARM_SUSPEND, rs_r5, rs_r6, rs_r7, rs_r8, rs_rARM_SELF, 34 rs_r10, rs_r11, rs_r12, rs_rARM_SP, rs_rARM_LR, rs_rARM_PC}; 35#else 36static constexpr RegStorage core_regs_arr[] = 37 {rs_r0, rs_r1, rs_r2, rs_r3, rs_r4, rs_r5, rs_r6, rs_r7, rs_r8, rs_rARM_SELF, 38 rs_r10, rs_r11, rs_r12, rs_rARM_SP, rs_rARM_LR, rs_rARM_PC}; 39#endif 40static constexpr RegStorage sp_regs_arr[] = 41 {rs_fr0, rs_fr1, rs_fr2, rs_fr3, rs_fr4, rs_fr5, rs_fr6, rs_fr7, rs_fr8, rs_fr9, rs_fr10, 42 rs_fr11, rs_fr12, rs_fr13, rs_fr14, rs_fr15, rs_fr16, rs_fr17, rs_fr18, rs_fr19, rs_fr20, 43 rs_fr21, rs_fr22, rs_fr23, rs_fr24, rs_fr25, rs_fr26, rs_fr27, rs_fr28, rs_fr29, rs_fr30, 44 rs_fr31}; 45static constexpr RegStorage dp_regs_arr[] = 46 {rs_dr0, rs_dr1, rs_dr2, rs_dr3, rs_dr4, rs_dr5, rs_dr6, rs_dr7, rs_dr8, rs_dr9, rs_dr10, 47 rs_dr11, rs_dr12, rs_dr13, rs_dr14, rs_dr15}; 48#ifdef ARM_R4_SUSPEND_FLAG 49static constexpr RegStorage reserved_regs_arr[] = 50 {rs_rARM_SUSPEND, rs_rARM_SELF, rs_rARM_SP, rs_rARM_LR, rs_rARM_PC}; 51static constexpr RegStorage core_temps_arr[] = {rs_r0, rs_r1, rs_r2, rs_r3, rs_r12}; 52#else 53static constexpr RegStorage reserved_regs_arr[] = 54 {rs_rARM_SELF, rs_rARM_SP, rs_rARM_LR, rs_rARM_PC}; 55static constexpr RegStorage core_temps_arr[] = {rs_r0, rs_r1, rs_r2, rs_r3, rs_r4, rs_r12}; 56#endif 57static constexpr RegStorage sp_temps_arr[] = 58 {rs_fr0, rs_fr1, rs_fr2, rs_fr3, rs_fr4, rs_fr5, rs_fr6, rs_fr7, rs_fr8, rs_fr9, rs_fr10, 59 rs_fr11, rs_fr12, rs_fr13, rs_fr14, rs_fr15}; 60static constexpr RegStorage dp_temps_arr[] = 61 {rs_dr0, rs_dr1, rs_dr2, rs_dr3, rs_dr4, rs_dr5, rs_dr6, rs_dr7}; 62 63static constexpr ArrayRef<const RegStorage> empty_pool; 64static constexpr ArrayRef<const RegStorage> core_regs(core_regs_arr); 65static constexpr ArrayRef<const RegStorage> sp_regs(sp_regs_arr); 66static constexpr ArrayRef<const RegStorage> dp_regs(dp_regs_arr); 67static constexpr ArrayRef<const RegStorage> reserved_regs(reserved_regs_arr); 68static constexpr ArrayRef<const RegStorage> core_temps(core_temps_arr); 69static constexpr ArrayRef<const RegStorage> sp_temps(sp_temps_arr); 70static constexpr ArrayRef<const RegStorage> dp_temps(dp_temps_arr); 71 72RegLocation ArmMir2Lir::LocCReturn() { 73 return arm_loc_c_return; 74} 75 76RegLocation ArmMir2Lir::LocCReturnRef() { 77 return arm_loc_c_return; 78} 79 80RegLocation ArmMir2Lir::LocCReturnWide() { 81 return arm_loc_c_return_wide; 82} 83 84RegLocation ArmMir2Lir::LocCReturnFloat() { 85 return arm_loc_c_return_float; 86} 87 88RegLocation ArmMir2Lir::LocCReturnDouble() { 89 return arm_loc_c_return_double; 90} 91 92// Return a target-dependent special register. 93RegStorage ArmMir2Lir::TargetReg(SpecialTargetRegister reg) { 94 RegStorage res_reg; 95 switch (reg) { 96 case kSelf: res_reg = rs_rARM_SELF; break; 97#ifdef ARM_R4_SUSPEND_FLAG 98 case kSuspend: res_reg = rs_rARM_SUSPEND; break; 99#else 100 case kSuspend: res_reg = RegStorage::InvalidReg(); break; 101#endif 102 case kLr: res_reg = rs_rARM_LR; break; 103 case kPc: res_reg = rs_rARM_PC; break; 104 case kSp: res_reg = rs_rARM_SP; break; 105 case kArg0: res_reg = rs_r0; break; 106 case kArg1: res_reg = rs_r1; break; 107 case kArg2: res_reg = rs_r2; break; 108 case kArg3: res_reg = rs_r3; break; 109 case kFArg0: res_reg = kArm32QuickCodeUseSoftFloat ? rs_r0 : rs_fr0; break; 110 case kFArg1: res_reg = kArm32QuickCodeUseSoftFloat ? rs_r1 : rs_fr1; break; 111 case kFArg2: res_reg = kArm32QuickCodeUseSoftFloat ? rs_r2 : rs_fr2; break; 112 case kFArg3: res_reg = kArm32QuickCodeUseSoftFloat ? rs_r3 : rs_fr3; break; 113 case kFArg4: res_reg = kArm32QuickCodeUseSoftFloat ? RegStorage::InvalidReg() : rs_fr4; break; 114 case kFArg5: res_reg = kArm32QuickCodeUseSoftFloat ? RegStorage::InvalidReg() : rs_fr5; break; 115 case kFArg6: res_reg = kArm32QuickCodeUseSoftFloat ? RegStorage::InvalidReg() : rs_fr6; break; 116 case kFArg7: res_reg = kArm32QuickCodeUseSoftFloat ? RegStorage::InvalidReg() : rs_fr7; break; 117 case kFArg8: res_reg = kArm32QuickCodeUseSoftFloat ? RegStorage::InvalidReg() : rs_fr8; break; 118 case kFArg9: res_reg = kArm32QuickCodeUseSoftFloat ? RegStorage::InvalidReg() : rs_fr9; break; 119 case kFArg10: res_reg = kArm32QuickCodeUseSoftFloat ? RegStorage::InvalidReg() : rs_fr10; break; 120 case kFArg11: res_reg = kArm32QuickCodeUseSoftFloat ? RegStorage::InvalidReg() : rs_fr11; break; 121 case kFArg12: res_reg = kArm32QuickCodeUseSoftFloat ? RegStorage::InvalidReg() : rs_fr12; break; 122 case kFArg13: res_reg = kArm32QuickCodeUseSoftFloat ? RegStorage::InvalidReg() : rs_fr13; break; 123 case kFArg14: res_reg = kArm32QuickCodeUseSoftFloat ? RegStorage::InvalidReg() : rs_fr14; break; 124 case kFArg15: res_reg = kArm32QuickCodeUseSoftFloat ? RegStorage::InvalidReg() : rs_fr15; break; 125 case kRet0: res_reg = rs_r0; break; 126 case kRet1: res_reg = rs_r1; break; 127 case kInvokeTgt: res_reg = rs_rARM_LR; break; 128 case kHiddenArg: res_reg = rs_r12; break; 129 case kHiddenFpArg: res_reg = RegStorage::InvalidReg(); break; 130 case kCount: res_reg = RegStorage::InvalidReg(); break; 131 default: res_reg = RegStorage::InvalidReg(); 132 } 133 return res_reg; 134} 135 136/* 137 * Decode the register id. 138 */ 139ResourceMask ArmMir2Lir::GetRegMaskCommon(const RegStorage& reg) const { 140 return GetRegMaskArm(reg); 141} 142 143constexpr ResourceMask ArmMir2Lir::GetRegMaskArm(RegStorage reg) { 144 return reg.IsDouble() 145 /* Each double register is equal to a pair of single-precision FP registers */ 146 ? ResourceMask::TwoBits(reg.GetRegNum() * 2 + kArmFPReg0) 147 : ResourceMask::Bit(reg.IsSingle() ? reg.GetRegNum() + kArmFPReg0 : reg.GetRegNum()); 148} 149 150constexpr ResourceMask ArmMir2Lir::EncodeArmRegList(int reg_list) { 151 return ResourceMask::RawMask(static_cast<uint64_t >(reg_list), 0u); 152} 153 154constexpr ResourceMask ArmMir2Lir::EncodeArmRegFpcsList(int reg_list) { 155 return ResourceMask::RawMask(static_cast<uint64_t >(reg_list) << kArmFPReg16, 0u); 156} 157 158ResourceMask ArmMir2Lir::GetPCUseDefEncoding() const { 159 return ResourceMask::Bit(kArmRegPC); 160} 161 162// Thumb2 specific setup. TODO: inline?: 163void ArmMir2Lir::SetupTargetResourceMasks(LIR* lir, uint64_t flags, 164 ResourceMask* use_mask, ResourceMask* def_mask) { 165 DCHECK_EQ(cu_->instruction_set, kThumb2); 166 DCHECK(!lir->flags.use_def_invalid); 167 168 int opcode = lir->opcode; 169 170 // These flags are somewhat uncommon - bypass if we can. 171 if ((flags & (REG_DEF_SP | REG_USE_SP | REG_DEF_LIST0 | REG_DEF_LIST1 | 172 REG_DEF_FPCS_LIST0 | REG_DEF_FPCS_LIST2 | REG_USE_PC | IS_IT | REG_USE_LIST0 | 173 REG_USE_LIST1 | REG_USE_FPCS_LIST0 | REG_USE_FPCS_LIST2 | REG_DEF_LR)) != 0) { 174 if (flags & REG_DEF_SP) { 175 def_mask->SetBit(kArmRegSP); 176 } 177 178 if (flags & REG_USE_SP) { 179 use_mask->SetBit(kArmRegSP); 180 } 181 182 if (flags & REG_DEF_LIST0) { 183 def_mask->SetBits(EncodeArmRegList(lir->operands[0])); 184 } 185 186 if (flags & REG_DEF_LIST1) { 187 def_mask->SetBits(EncodeArmRegList(lir->operands[1])); 188 } 189 190 if (flags & REG_DEF_FPCS_LIST0) { 191 def_mask->SetBits(EncodeArmRegList(lir->operands[0])); 192 } 193 194 if (flags & REG_DEF_FPCS_LIST2) { 195 for (int i = 0; i < lir->operands[2]; i++) { 196 SetupRegMask(def_mask, lir->operands[1] + i); 197 } 198 } 199 200 if (flags & REG_USE_PC) { 201 use_mask->SetBit(kArmRegPC); 202 } 203 204 /* Conservatively treat the IT block */ 205 if (flags & IS_IT) { 206 *def_mask = kEncodeAll; 207 } 208 209 if (flags & REG_USE_LIST0) { 210 use_mask->SetBits(EncodeArmRegList(lir->operands[0])); 211 } 212 213 if (flags & REG_USE_LIST1) { 214 use_mask->SetBits(EncodeArmRegList(lir->operands[1])); 215 } 216 217 if (flags & REG_USE_FPCS_LIST0) { 218 use_mask->SetBits(EncodeArmRegList(lir->operands[0])); 219 } 220 221 if (flags & REG_USE_FPCS_LIST2) { 222 for (int i = 0; i < lir->operands[2]; i++) { 223 SetupRegMask(use_mask, lir->operands[1] + i); 224 } 225 } 226 /* Fixup for kThumbPush/lr and kThumbPop/pc */ 227 if (opcode == kThumbPush || opcode == kThumbPop) { 228 constexpr ResourceMask r8Mask = GetRegMaskArm(rs_r8); 229 if ((opcode == kThumbPush) && (use_mask->Intersects(r8Mask))) { 230 use_mask->ClearBits(r8Mask); 231 use_mask->SetBit(kArmRegLR); 232 } else if ((opcode == kThumbPop) && (def_mask->Intersects(r8Mask))) { 233 def_mask->ClearBits(r8Mask); 234 def_mask->SetBit(kArmRegPC);; 235 } 236 } 237 if (flags & REG_DEF_LR) { 238 def_mask->SetBit(kArmRegLR); 239 } 240 } 241} 242 243ArmConditionCode ArmMir2Lir::ArmConditionEncoding(ConditionCode ccode) { 244 ArmConditionCode res; 245 switch (ccode) { 246 case kCondEq: res = kArmCondEq; break; 247 case kCondNe: res = kArmCondNe; break; 248 case kCondCs: res = kArmCondCs; break; 249 case kCondCc: res = kArmCondCc; break; 250 case kCondUlt: res = kArmCondCc; break; 251 case kCondUge: res = kArmCondCs; break; 252 case kCondMi: res = kArmCondMi; break; 253 case kCondPl: res = kArmCondPl; break; 254 case kCondVs: res = kArmCondVs; break; 255 case kCondVc: res = kArmCondVc; break; 256 case kCondHi: res = kArmCondHi; break; 257 case kCondLs: res = kArmCondLs; break; 258 case kCondGe: res = kArmCondGe; break; 259 case kCondLt: res = kArmCondLt; break; 260 case kCondGt: res = kArmCondGt; break; 261 case kCondLe: res = kArmCondLe; break; 262 case kCondAl: res = kArmCondAl; break; 263 case kCondNv: res = kArmCondNv; break; 264 default: 265 LOG(FATAL) << "Bad condition code " << ccode; 266 res = static_cast<ArmConditionCode>(0); // Quiet gcc 267 } 268 return res; 269} 270 271static const char* core_reg_names[16] = { 272 "r0", 273 "r1", 274 "r2", 275 "r3", 276 "r4", 277 "r5", 278 "r6", 279 "r7", 280 "r8", 281 "rSELF", 282 "r10", 283 "r11", 284 "r12", 285 "sp", 286 "lr", 287 "pc", 288}; 289 290 291static const char* shift_names[4] = { 292 "lsl", 293 "lsr", 294 "asr", 295 "ror"}; 296 297/* Decode and print a ARM register name */ 298static char* DecodeRegList(int opcode, int vector, char* buf, size_t buf_size) { 299 int i; 300 bool printed = false; 301 buf[0] = 0; 302 for (i = 0; i < 16; i++, vector >>= 1) { 303 if (vector & 0x1) { 304 int reg_id = i; 305 if (opcode == kThumbPush && i == 8) { 306 reg_id = rs_rARM_LR.GetRegNum(); 307 } else if (opcode == kThumbPop && i == 8) { 308 reg_id = rs_rARM_PC.GetRegNum(); 309 } 310 if (printed) { 311 snprintf(buf + strlen(buf), buf_size - strlen(buf), ", r%d", reg_id); 312 } else { 313 printed = true; 314 snprintf(buf, buf_size, "r%d", reg_id); 315 } 316 } 317 } 318 return buf; 319} 320 321static char* DecodeFPCSRegList(int count, int base, char* buf, size_t buf_size) { 322 snprintf(buf, buf_size, "s%d", base); 323 for (int i = 1; i < count; i++) { 324 snprintf(buf + strlen(buf), buf_size - strlen(buf), ", s%d", base + i); 325 } 326 return buf; 327} 328 329static int32_t ExpandImmediate(int value) { 330 int32_t mode = (value & 0xf00) >> 8; 331 uint32_t bits = value & 0xff; 332 switch (mode) { 333 case 0: 334 return bits; 335 case 1: 336 return (bits << 16) | bits; 337 case 2: 338 return (bits << 24) | (bits << 8); 339 case 3: 340 return (bits << 24) | (bits << 16) | (bits << 8) | bits; 341 default: 342 break; 343 } 344 bits = (bits | 0x80) << 24; 345 return bits >> (((value & 0xf80) >> 7) - 8); 346} 347 348const char* cc_names[] = {"eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc", 349 "hi", "ls", "ge", "lt", "gt", "le", "al", "nv"}; 350/* 351 * Interpret a format string and build a string no longer than size 352 * See format key in Assemble.c. 353 */ 354std::string ArmMir2Lir::BuildInsnString(const char* fmt, LIR* lir, unsigned char* base_addr) { 355 std::string buf; 356 int i; 357 const char* fmt_end = &fmt[strlen(fmt)]; 358 char tbuf[256]; 359 const char* name; 360 char nc; 361 while (fmt < fmt_end) { 362 int operand; 363 if (*fmt == '!') { 364 fmt++; 365 DCHECK_LT(fmt, fmt_end); 366 nc = *fmt++; 367 if (nc == '!') { 368 strcpy(tbuf, "!"); 369 } else { 370 DCHECK_LT(fmt, fmt_end); 371 DCHECK_LT(static_cast<unsigned>(nc-'0'), 4U); 372 operand = lir->operands[nc-'0']; 373 switch (*fmt++) { 374 case 'H': 375 if (operand != 0) { 376 snprintf(tbuf, arraysize(tbuf), ", %s %d", shift_names[operand & 0x3], operand >> 2); 377 } else { 378 strcpy(tbuf, ""); 379 } 380 break; 381 case 'B': 382 switch (operand) { 383 case kSY: 384 name = "sy"; 385 break; 386 case kST: 387 name = "st"; 388 break; 389 case kISH: 390 name = "ish"; 391 break; 392 case kISHST: 393 name = "ishst"; 394 break; 395 case kNSH: 396 name = "nsh"; 397 break; 398 case kNSHST: 399 name = "shst"; 400 break; 401 default: 402 name = "DecodeError2"; 403 break; 404 } 405 strcpy(tbuf, name); 406 break; 407 case 'b': 408 strcpy(tbuf, "0000"); 409 for (i = 3; i >= 0; i--) { 410 tbuf[i] += operand & 1; 411 operand >>= 1; 412 } 413 break; 414 case 'n': 415 operand = ~ExpandImmediate(operand); 416 snprintf(tbuf, arraysize(tbuf), "%d [%#x]", operand, operand); 417 break; 418 case 'm': 419 operand = ExpandImmediate(operand); 420 snprintf(tbuf, arraysize(tbuf), "%d [%#x]", operand, operand); 421 break; 422 case 's': 423 snprintf(tbuf, arraysize(tbuf), "s%d", RegStorage::RegNum(operand)); 424 break; 425 case 'S': 426 snprintf(tbuf, arraysize(tbuf), "d%d", RegStorage::RegNum(operand)); 427 break; 428 case 'h': 429 snprintf(tbuf, arraysize(tbuf), "%04x", operand); 430 break; 431 case 'M': 432 case 'd': 433 snprintf(tbuf, arraysize(tbuf), "%d", operand); 434 break; 435 case 'C': 436 operand = RegStorage::RegNum(operand); 437 DCHECK_LT(operand, static_cast<int>( 438 sizeof(core_reg_names)/sizeof(core_reg_names[0]))); 439 snprintf(tbuf, arraysize(tbuf), "%s", core_reg_names[operand]); 440 break; 441 case 'E': 442 snprintf(tbuf, arraysize(tbuf), "%d", operand*4); 443 break; 444 case 'F': 445 snprintf(tbuf, arraysize(tbuf), "%d", operand*2); 446 break; 447 case 'c': 448 strcpy(tbuf, cc_names[operand]); 449 break; 450 case 't': 451 snprintf(tbuf, arraysize(tbuf), "0x%08" PRIxPTR " (L%p)", 452 reinterpret_cast<uintptr_t>(base_addr) + lir->offset + 4 + (operand << 1), 453 lir->target); 454 break; 455 case 'T': 456 snprintf(tbuf, arraysize(tbuf), "%s", PrettyMethod( 457 static_cast<uint32_t>(lir->operands[1]), 458 *UnwrapPointer<DexFile>(lir->operands[2])).c_str()); 459 break; 460 case 'u': { 461 int offset_1 = lir->operands[0]; 462 int offset_2 = NEXT_LIR(lir)->operands[0]; 463 uintptr_t target = 464 (((reinterpret_cast<uintptr_t>(base_addr) + lir->offset + 4) & 465 ~3) + (offset_1 << 21 >> 9) + (offset_2 << 1)) & 466 0xfffffffc; 467 snprintf(tbuf, arraysize(tbuf), "%p", reinterpret_cast<void *>(target)); 468 break; 469 } 470 471 /* Nothing to print for BLX_2 */ 472 case 'v': 473 strcpy(tbuf, "see above"); 474 break; 475 case 'R': 476 DecodeRegList(lir->opcode, operand, tbuf, arraysize(tbuf)); 477 break; 478 case 'P': 479 DecodeFPCSRegList(operand, 16, tbuf, arraysize(tbuf)); 480 break; 481 case 'Q': 482 DecodeFPCSRegList(operand, 0, tbuf, arraysize(tbuf)); 483 break; 484 default: 485 strcpy(tbuf, "DecodeError1"); 486 break; 487 } 488 buf += tbuf; 489 } 490 } else { 491 buf += *fmt++; 492 } 493 } 494 // Dump thread offset. 495 std::string fmt_str = GetTargetInstFmt(lir->opcode); 496 if (std::string::npos != fmt_str.find(", [!1C, #!2") && rARM_SELF == lir->operands[1] && 497 std::string::npos != buf.find(", [")) { 498 int offset = lir->operands[2]; 499 if (std::string::npos != fmt_str.find("#!2d")) { 500 } else if (std::string::npos != fmt_str.find("#!2E")) { 501 offset *= 4; 502 } else if (std::string::npos != fmt_str.find("#!2F")) { 503 offset *= 2; 504 } else { 505 LOG(FATAL) << "Should not reach here"; 506 } 507 std::ostringstream tmp_stream; 508 Thread::DumpThreadOffset<4>(tmp_stream, offset); 509 buf += " ; "; 510 buf += tmp_stream.str(); 511 } 512 return buf; 513} 514 515void ArmMir2Lir::DumpResourceMask(LIR* arm_lir, const ResourceMask& mask, const char* prefix) { 516 char buf[256]; 517 buf[0] = 0; 518 519 if (mask.Equals(kEncodeAll)) { 520 strcpy(buf, "all"); 521 } else { 522 char num[8]; 523 int i; 524 525 for (i = 0; i < kArmRegEnd; i++) { 526 if (mask.HasBit(i)) { 527 snprintf(num, arraysize(num), "%d ", i); 528 strcat(buf, num); 529 } 530 } 531 532 if (mask.HasBit(ResourceMask::kCCode)) { 533 strcat(buf, "cc "); 534 } 535 if (mask.HasBit(ResourceMask::kFPStatus)) { 536 strcat(buf, "fpcc "); 537 } 538 539 /* Memory bits */ 540 if (arm_lir && (mask.HasBit(ResourceMask::kDalvikReg))) { 541 snprintf(buf + strlen(buf), arraysize(buf) - strlen(buf), "dr%d%s", 542 DECODE_ALIAS_INFO_REG(arm_lir->flags.alias_info), 543 DECODE_ALIAS_INFO_WIDE(arm_lir->flags.alias_info) ? "(+1)" : ""); 544 } 545 if (mask.HasBit(ResourceMask::kLiteral)) { 546 strcat(buf, "lit "); 547 } 548 549 if (mask.HasBit(ResourceMask::kHeapRef)) { 550 strcat(buf, "heap "); 551 } 552 if (mask.HasBit(ResourceMask::kMustNotAlias)) { 553 strcat(buf, "noalias "); 554 } 555 } 556 if (buf[0]) { 557 LOG(INFO) << prefix << ": " << buf; 558 } 559} 560 561bool ArmMir2Lir::IsUnconditionalBranch(LIR* lir) { 562 return ((lir->opcode == kThumbBUncond) || (lir->opcode == kThumb2BUncond)); 563} 564 565RegisterClass ArmMir2Lir::RegClassForFieldLoadStore(OpSize size, bool is_volatile) { 566 if (UNLIKELY(is_volatile)) { 567 // On arm, atomic 64-bit load/store requires a core register pair. 568 // Smaller aligned load/store is atomic for both core and fp registers. 569 if (size == k64 || size == kDouble) { 570 return kCoreReg; 571 } 572 } 573 return RegClassBySize(size); 574} 575 576ArmMir2Lir::ArmMir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena) 577 : Mir2Lir(cu, mir_graph, arena), 578 call_method_insns_(arena->Adapter()), 579 dex_cache_access_insns_(arena->Adapter()), 580 dex_cache_arrays_base_reg_(RegStorage::InvalidReg()) { 581 call_method_insns_.reserve(100); 582 // Sanity check - make sure encoding map lines up. 583 for (int i = 0; i < kArmLast; i++) { 584 DCHECK_EQ(ArmMir2Lir::EncodingMap[i].opcode, i) 585 << "Encoding order for " << ArmMir2Lir::EncodingMap[i].name 586 << " is wrong: expecting " << i << ", seeing " 587 << static_cast<int>(ArmMir2Lir::EncodingMap[i].opcode); 588 } 589} 590 591Mir2Lir* ArmCodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph, 592 ArenaAllocator* const arena) { 593 return new ArmMir2Lir(cu, mir_graph, arena); 594} 595 596void ArmMir2Lir::CompilerInitializeRegAlloc() { 597 reg_pool_.reset(new (arena_) RegisterPool(this, arena_, core_regs, empty_pool /* core64 */, 598 sp_regs, dp_regs, 599 reserved_regs, empty_pool /* reserved64 */, 600 core_temps, empty_pool /* core64_temps */, 601 sp_temps, dp_temps)); 602 603 // Target-specific adjustments. 604 605 // Alias single precision floats to appropriate half of overlapping double. 606 for (RegisterInfo* info : reg_pool_->sp_regs_) { 607 int sp_reg_num = info->GetReg().GetRegNum(); 608 int dp_reg_num = sp_reg_num >> 1; 609 RegStorage dp_reg = RegStorage::Solo64(RegStorage::kFloatingPoint | dp_reg_num); 610 RegisterInfo* dp_reg_info = GetRegInfo(dp_reg); 611 // Double precision register's master storage should refer to itself. 612 DCHECK_EQ(dp_reg_info, dp_reg_info->Master()); 613 // Redirect single precision's master storage to master. 614 info->SetMaster(dp_reg_info); 615 // Singles should show a single 32-bit mask bit, at first referring to the low half. 616 DCHECK_EQ(info->StorageMask(), RegisterInfo::kLowSingleStorageMask); 617 if (sp_reg_num & 1) { 618 // For odd singles, change to use the high word of the backing double. 619 info->SetStorageMask(RegisterInfo::kHighSingleStorageMask); 620 } 621 } 622 623#ifdef ARM_R4_SUSPEND_FLAG 624 // TODO: re-enable this when we can safely save r4 over the suspension code path. 625 bool no_suspend = NO_SUSPEND; // || !Runtime::Current()->ExplicitSuspendChecks(); 626 if (no_suspend) { 627 GetRegInfo(rs_rARM_SUSPEND)->MarkFree(); 628 } 629#endif 630 631 // Don't start allocating temps at r0/s0/d0 or you may clobber return regs in early-exit methods. 632 // TODO: adjust when we roll to hard float calling convention. 633 reg_pool_->next_core_reg_ = 2; 634 reg_pool_->next_sp_reg_ = 0; 635 reg_pool_->next_dp_reg_ = 0; 636} 637 638/* 639 * TUNING: is true leaf? Can't just use METHOD_IS_LEAF to determine as some 640 * instructions might call out to C/assembly helper functions. Until 641 * machinery is in place, always spill lr. 642 */ 643 644void ArmMir2Lir::AdjustSpillMask() { 645 core_spill_mask_ |= (1 << rs_rARM_LR.GetRegNum()); 646 num_core_spills_++; 647} 648 649/* 650 * Mark a callee-save fp register as promoted. Note that 651 * vpush/vpop uses contiguous register lists so we must 652 * include any holes in the mask. Associate holes with 653 * Dalvik register INVALID_VREG (0xFFFFU). 654 */ 655void ArmMir2Lir::MarkPreservedSingle(int v_reg, RegStorage reg) { 656 DCHECK_GE(reg.GetRegNum(), ARM_FP_CALLEE_SAVE_BASE); 657 int adjusted_reg_num = reg.GetRegNum() - ARM_FP_CALLEE_SAVE_BASE; 658 // Ensure fp_vmap_table is large enough 659 int table_size = fp_vmap_table_.size(); 660 for (int i = table_size; i < (adjusted_reg_num + 1); i++) { 661 fp_vmap_table_.push_back(INVALID_VREG); 662 } 663 // Add the current mapping 664 fp_vmap_table_[adjusted_reg_num] = v_reg; 665 // Size of fp_vmap_table is high-water mark, use to set mask 666 num_fp_spills_ = fp_vmap_table_.size(); 667 fp_spill_mask_ = ((1 << num_fp_spills_) - 1) << ARM_FP_CALLEE_SAVE_BASE; 668} 669 670void ArmMir2Lir::MarkPreservedDouble(int v_reg, RegStorage reg) { 671 // TEMP: perform as 2 singles. 672 int reg_num = reg.GetRegNum() << 1; 673 RegStorage lo = RegStorage::Solo32(RegStorage::kFloatingPoint | reg_num); 674 RegStorage hi = RegStorage::Solo32(RegStorage::kFloatingPoint | reg_num | 1); 675 MarkPreservedSingle(v_reg, lo); 676 MarkPreservedSingle(v_reg + 1, hi); 677} 678 679/* Clobber all regs that might be used by an external C call */ 680void ArmMir2Lir::ClobberCallerSave() { 681 // TODO: rework this - it's gotten even more ugly. 682 Clobber(rs_r0); 683 Clobber(rs_r1); 684 Clobber(rs_r2); 685 Clobber(rs_r3); 686 Clobber(rs_r12); 687 Clobber(rs_r14lr); 688 Clobber(rs_fr0); 689 Clobber(rs_fr1); 690 Clobber(rs_fr2); 691 Clobber(rs_fr3); 692 Clobber(rs_fr4); 693 Clobber(rs_fr5); 694 Clobber(rs_fr6); 695 Clobber(rs_fr7); 696 Clobber(rs_fr8); 697 Clobber(rs_fr9); 698 Clobber(rs_fr10); 699 Clobber(rs_fr11); 700 Clobber(rs_fr12); 701 Clobber(rs_fr13); 702 Clobber(rs_fr14); 703 Clobber(rs_fr15); 704 Clobber(rs_dr0); 705 Clobber(rs_dr1); 706 Clobber(rs_dr2); 707 Clobber(rs_dr3); 708 Clobber(rs_dr4); 709 Clobber(rs_dr5); 710 Clobber(rs_dr6); 711 Clobber(rs_dr7); 712} 713 714RegLocation ArmMir2Lir::GetReturnWideAlt() { 715 RegLocation res = LocCReturnWide(); 716 res.reg.SetLowReg(rs_r2.GetReg()); 717 res.reg.SetHighReg(rs_r3.GetReg()); 718 Clobber(rs_r2); 719 Clobber(rs_r3); 720 MarkInUse(rs_r2); 721 MarkInUse(rs_r3); 722 MarkWide(res.reg); 723 return res; 724} 725 726RegLocation ArmMir2Lir::GetReturnAlt() { 727 RegLocation res = LocCReturn(); 728 res.reg.SetReg(rs_r1.GetReg()); 729 Clobber(rs_r1); 730 MarkInUse(rs_r1); 731 return res; 732} 733 734/* To be used when explicitly managing register use */ 735void ArmMir2Lir::LockCallTemps() { 736 LockTemp(rs_r0); 737 LockTemp(rs_r1); 738 LockTemp(rs_r2); 739 LockTemp(rs_r3); 740 if (!kArm32QuickCodeUseSoftFloat) { 741 LockTemp(rs_fr0); 742 LockTemp(rs_fr1); 743 LockTemp(rs_fr2); 744 LockTemp(rs_fr3); 745 LockTemp(rs_fr4); 746 LockTemp(rs_fr5); 747 LockTemp(rs_fr6); 748 LockTemp(rs_fr7); 749 LockTemp(rs_fr8); 750 LockTemp(rs_fr9); 751 LockTemp(rs_fr10); 752 LockTemp(rs_fr11); 753 LockTemp(rs_fr12); 754 LockTemp(rs_fr13); 755 LockTemp(rs_fr14); 756 LockTemp(rs_fr15); 757 LockTemp(rs_dr0); 758 LockTemp(rs_dr1); 759 LockTemp(rs_dr2); 760 LockTemp(rs_dr3); 761 LockTemp(rs_dr4); 762 LockTemp(rs_dr5); 763 LockTemp(rs_dr6); 764 LockTemp(rs_dr7); 765 } 766} 767 768/* To be used when explicitly managing register use */ 769void ArmMir2Lir::FreeCallTemps() { 770 FreeTemp(rs_r0); 771 FreeTemp(rs_r1); 772 FreeTemp(rs_r2); 773 FreeTemp(rs_r3); 774 FreeTemp(TargetReg(kHiddenArg)); 775 if (!kArm32QuickCodeUseSoftFloat) { 776 FreeTemp(rs_fr0); 777 FreeTemp(rs_fr1); 778 FreeTemp(rs_fr2); 779 FreeTemp(rs_fr3); 780 FreeTemp(rs_fr4); 781 FreeTemp(rs_fr5); 782 FreeTemp(rs_fr6); 783 FreeTemp(rs_fr7); 784 FreeTemp(rs_fr8); 785 FreeTemp(rs_fr9); 786 FreeTemp(rs_fr10); 787 FreeTemp(rs_fr11); 788 FreeTemp(rs_fr12); 789 FreeTemp(rs_fr13); 790 FreeTemp(rs_fr14); 791 FreeTemp(rs_fr15); 792 FreeTemp(rs_dr0); 793 FreeTemp(rs_dr1); 794 FreeTemp(rs_dr2); 795 FreeTemp(rs_dr3); 796 FreeTemp(rs_dr4); 797 FreeTemp(rs_dr5); 798 FreeTemp(rs_dr6); 799 FreeTemp(rs_dr7); 800 } 801} 802 803RegStorage ArmMir2Lir::LoadHelper(QuickEntrypointEnum trampoline) { 804 LoadWordDisp(rs_rARM_SELF, GetThreadOffset<4>(trampoline).Int32Value(), rs_rARM_LR); 805 return rs_rARM_LR; 806} 807 808LIR* ArmMir2Lir::CheckSuspendUsingLoad() { 809 RegStorage tmp = rs_r0; 810 Load32Disp(rs_rARM_SELF, Thread::ThreadSuspendTriggerOffset<4>().Int32Value(), tmp); 811 LIR* load2 = Load32Disp(tmp, 0, tmp); 812 return load2; 813} 814 815uint64_t ArmMir2Lir::GetTargetInstFlags(int opcode) { 816 DCHECK(!IsPseudoLirOp(opcode)); 817 return ArmMir2Lir::EncodingMap[opcode].flags; 818} 819 820const char* ArmMir2Lir::GetTargetInstName(int opcode) { 821 DCHECK(!IsPseudoLirOp(opcode)); 822 return ArmMir2Lir::EncodingMap[opcode].name; 823} 824 825const char* ArmMir2Lir::GetTargetInstFmt(int opcode) { 826 DCHECK(!IsPseudoLirOp(opcode)); 827 return ArmMir2Lir::EncodingMap[opcode].fmt; 828} 829 830/* 831 * Somewhat messy code here. We want to allocate a pair of contiguous 832 * physical single-precision floating point registers starting with 833 * an even numbered reg. It is possible that the paired s_reg (s_reg+1) 834 * has already been allocated - try to fit if possible. Fail to 835 * allocate if we can't meet the requirements for the pair of 836 * s_reg<=sX[even] & (s_reg+1)<= sX+1. 837 */ 838// TODO: needs rewrite to support non-backed 64-bit float regs. 839RegStorage ArmMir2Lir::AllocPreservedDouble(int s_reg) { 840 RegStorage res; 841 int v_reg = mir_graph_->SRegToVReg(s_reg); 842 int p_map_idx = SRegToPMap(s_reg); 843 if (promotion_map_[p_map_idx+1].fp_location == kLocPhysReg) { 844 // Upper reg is already allocated. Can we fit? 845 int high_reg = promotion_map_[p_map_idx+1].fp_reg; 846 if ((high_reg & 1) == 0) { 847 // High reg is even - fail. 848 return res; // Invalid. 849 } 850 // Is the low reg of the pair free? 851 // FIXME: rework. 852 RegisterInfo* p = GetRegInfo(RegStorage::FloatSolo32(high_reg - 1)); 853 if (p->InUse() || p->IsTemp()) { 854 // Already allocated or not preserved - fail. 855 return res; // Invalid. 856 } 857 // OK - good to go. 858 res = RegStorage::FloatSolo64(p->GetReg().GetRegNum() >> 1); 859 p->MarkInUse(); 860 MarkPreservedSingle(v_reg, p->GetReg()); 861 } else { 862 /* 863 * TODO: until runtime support is in, make sure we avoid promoting the same vreg to 864 * different underlying physical registers. 865 */ 866 for (RegisterInfo* info : reg_pool_->dp_regs_) { 867 if (!info->IsTemp() && !info->InUse()) { 868 res = info->GetReg(); 869 info->MarkInUse(); 870 MarkPreservedDouble(v_reg, info->GetReg()); 871 break; 872 } 873 } 874 } 875 if (res.Valid()) { 876 RegisterInfo* info = GetRegInfo(res); 877 promotion_map_[p_map_idx].fp_location = kLocPhysReg; 878 promotion_map_[p_map_idx].fp_reg = 879 info->FindMatchingView(RegisterInfo::kLowSingleStorageMask)->GetReg().GetReg(); 880 promotion_map_[p_map_idx+1].fp_location = kLocPhysReg; 881 promotion_map_[p_map_idx+1].fp_reg = 882 info->FindMatchingView(RegisterInfo::kHighSingleStorageMask)->GetReg().GetReg(); 883 } 884 return res; 885} 886 887// Reserve a callee-save sp single register. 888RegStorage ArmMir2Lir::AllocPreservedSingle(int s_reg) { 889 RegStorage res; 890 for (RegisterInfo* info : reg_pool_->sp_regs_) { 891 if (!info->IsTemp() && !info->InUse()) { 892 res = info->GetReg(); 893 int p_map_idx = SRegToPMap(s_reg); 894 int v_reg = mir_graph_->SRegToVReg(s_reg); 895 GetRegInfo(res)->MarkInUse(); 896 MarkPreservedSingle(v_reg, res); 897 promotion_map_[p_map_idx].fp_location = kLocPhysReg; 898 promotion_map_[p_map_idx].fp_reg = res.GetReg(); 899 break; 900 } 901 } 902 return res; 903} 904 905void ArmMir2Lir::InstallLiteralPools() { 906 patches_.reserve(call_method_insns_.size() + dex_cache_access_insns_.size()); 907 908 // PC-relative calls to methods. 909 for (LIR* p : call_method_insns_) { 910 DCHECK_EQ(p->opcode, kThumb2Bl); 911 uint32_t target_method_idx = p->operands[1]; 912 const DexFile* target_dex_file = UnwrapPointer<DexFile>(p->operands[2]); 913 patches_.push_back(LinkerPatch::RelativeCodePatch(p->offset, 914 target_dex_file, target_method_idx)); 915 } 916 917 // PC-relative dex cache array accesses. 918 for (LIR* p : dex_cache_access_insns_) { 919 DCHECK(p->opcode = kThumb2MovImm16 || p->opcode == kThumb2MovImm16H); 920 const LIR* add_pc = UnwrapPointer<LIR>(p->operands[4]); 921 DCHECK(add_pc->opcode == kThumbAddRRLH || add_pc->opcode == kThumbAddRRHH); 922 const DexFile* dex_file = UnwrapPointer<DexFile>(p->operands[2]); 923 uint32_t offset = p->operands[3]; 924 DCHECK(!p->flags.is_nop); 925 DCHECK(!add_pc->flags.is_nop); 926 patches_.push_back(LinkerPatch::DexCacheArrayPatch(p->offset, 927 dex_file, add_pc->offset, offset)); 928 } 929 930 // And do the normal processing. 931 Mir2Lir::InstallLiteralPools(); 932} 933 934RegStorage ArmMir2Lir::InToRegStorageArmMapper::GetNextReg(ShortyArg arg) { 935 const RegStorage coreArgMappingToPhysicalReg[] = 936 {rs_r1, rs_r2, rs_r3}; 937 const int coreArgMappingToPhysicalRegSize = arraysize(coreArgMappingToPhysicalReg); 938 const RegStorage fpArgMappingToPhysicalReg[] = 939 {rs_fr0, rs_fr1, rs_fr2, rs_fr3, rs_fr4, rs_fr5, rs_fr6, rs_fr7, 940 rs_fr8, rs_fr9, rs_fr10, rs_fr11, rs_fr12, rs_fr13, rs_fr14, rs_fr15}; 941 constexpr uint32_t fpArgMappingToPhysicalRegSize = arraysize(fpArgMappingToPhysicalReg); 942 static_assert(fpArgMappingToPhysicalRegSize % 2 == 0, "Number of FP Arg regs is not even"); 943 944 RegStorage result = RegStorage::InvalidReg(); 945 // Regard double as long, float as int for kArm32QuickCodeUseSoftFloat. 946 if (arg.IsFP() && !kArm32QuickCodeUseSoftFloat) { 947 if (arg.IsWide()) { 948 cur_fp_double_reg_ = std::max(cur_fp_double_reg_, RoundUp(cur_fp_reg_, 2)); 949 if (cur_fp_double_reg_ < fpArgMappingToPhysicalRegSize) { 950 result = RegStorage::MakeRegPair(fpArgMappingToPhysicalReg[cur_fp_double_reg_], 951 fpArgMappingToPhysicalReg[cur_fp_double_reg_ + 1]); 952 result = As64BitFloatReg(result); 953 cur_fp_double_reg_ += 2; 954 } 955 } else { 956 if (cur_fp_reg_ % 2 == 0) { 957 cur_fp_reg_ = std::max(cur_fp_double_reg_, cur_fp_reg_); 958 } 959 if (cur_fp_reg_ < fpArgMappingToPhysicalRegSize) { 960 result = fpArgMappingToPhysicalReg[cur_fp_reg_]; 961 cur_fp_reg_++; 962 } 963 } 964 } else { 965 if (cur_core_reg_ < coreArgMappingToPhysicalRegSize) { 966 if (!kArm32QuickCodeUseSoftFloat && arg.IsWide() && cur_core_reg_ == 0) { 967 // Skip r1, and use r2-r3 for the register pair. 968 cur_core_reg_++; 969 } 970 result = coreArgMappingToPhysicalReg[cur_core_reg_++]; 971 if (arg.IsWide() && cur_core_reg_ < coreArgMappingToPhysicalRegSize) { 972 result = RegStorage::MakeRegPair(result, coreArgMappingToPhysicalReg[cur_core_reg_++]); 973 } 974 } 975 } 976 return result; 977} 978 979int ArmMir2Lir::GenDalvikArgsBulkCopy(CallInfo* info, int first, int count) { 980 if (kArm32QuickCodeUseSoftFloat) { 981 return Mir2Lir::GenDalvikArgsBulkCopy(info, first, count); 982 } 983 /* 984 * TODO: Improve by adding block copy for large number of arguments. For now, just 985 * copy a Dalvik vreg at a time. 986 */ 987 return count; 988} 989 990void ArmMir2Lir::GenMachineSpecificExtendedMethodMIR(BasicBlock* bb, MIR* mir) { 991 UNUSED(bb); 992 DCHECK(MIR::DecodedInstruction::IsPseudoMirOp(mir->dalvikInsn.opcode)); 993 RegLocation rl_src[3]; 994 RegLocation rl_dest = mir_graph_->GetBadLoc(); 995 rl_src[0] = rl_src[1] = rl_src[2] = mir_graph_->GetBadLoc(); 996 switch (static_cast<ExtendedMIROpcode>(mir->dalvikInsn.opcode)) { 997 case kMirOpMaddInt: 998 rl_dest = mir_graph_->GetDest(mir); 999 rl_src[0] = mir_graph_->GetSrc(mir, 0); 1000 rl_src[1] = mir_graph_->GetSrc(mir, 1); 1001 rl_src[2]= mir_graph_->GetSrc(mir, 2); 1002 GenMaddMsubInt(rl_dest, rl_src[0], rl_src[1], rl_src[2], false); 1003 break; 1004 case kMirOpMsubInt: 1005 rl_dest = mir_graph_->GetDest(mir); 1006 rl_src[0] = mir_graph_->GetSrc(mir, 0); 1007 rl_src[1] = mir_graph_->GetSrc(mir, 1); 1008 rl_src[2]= mir_graph_->GetSrc(mir, 2); 1009 GenMaddMsubInt(rl_dest, rl_src[0], rl_src[1], rl_src[2], true); 1010 break; 1011 default: 1012 LOG(FATAL) << "Unexpected opcode: " << mir->dalvikInsn.opcode; 1013 } 1014} 1015 1016} // namespace art 1017