target_x86.cc revision fe94578b63380f464c3abd5c156b7b31d068db6c
1/* 2 * Copyright (C) 2012 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#include <inttypes.h> 19 20#include "codegen_x86.h" 21#include "dex/compiler_internals.h" 22#include "dex/quick/mir_to_lir-inl.h" 23#include "mirror/array.h" 24#include "mirror/string.h" 25#include "x86_lir.h" 26 27namespace art { 28 29static const RegStorage core_regs_arr_32[] = { 30 rs_rAX, rs_rCX, rs_rDX, rs_rBX, rs_rX86_SP_32, rs_rBP, rs_rSI, rs_rDI, 31}; 32static const RegStorage core_regs_arr_64[] = { 33 rs_rAX, rs_rCX, rs_rDX, rs_rBX, rs_rX86_SP_64, rs_rBP, rs_rSI, rs_rDI, 34#ifdef TARGET_REX_SUPPORT 35 rs_r8, rs_r9, rs_r10, rs_r11, rs_r12, rs_r13, rs_r14, rs_r15 36#endif 37}; 38static const RegStorage sp_regs_arr_32[] = { 39 rs_fr0, rs_fr1, rs_fr2, rs_fr3, rs_fr4, rs_fr5, rs_fr6, rs_fr7, 40}; 41static const RegStorage sp_regs_arr_64[] = { 42 rs_fr0, rs_fr1, rs_fr2, rs_fr3, rs_fr4, rs_fr5, rs_fr6, rs_fr7, 43#ifdef TARGET_REX_SUPPORT 44 rs_fr8, rs_fr9, rs_fr10, rs_fr11, rs_fr12, rs_fr13, rs_fr14, rs_fr15 45#endif 46}; 47static const RegStorage dp_regs_arr_32[] = { 48 rs_dr0, rs_dr1, rs_dr2, rs_dr3, rs_dr4, rs_dr5, rs_dr6, rs_dr7, 49}; 50static const RegStorage dp_regs_arr_64[] = { 51 rs_dr0, rs_dr1, rs_dr2, rs_dr3, rs_dr4, rs_dr5, rs_dr6, rs_dr7, 52#ifdef TARGET_REX_SUPPORT 53 rs_dr8, rs_dr9, rs_dr10, rs_dr11, rs_dr12, rs_dr13, rs_dr14, rs_dr15 54#endif 55}; 56static const RegStorage reserved_regs_arr_32[] = {rs_rX86_SP_32}; 57static const RegStorage reserved_regs_arr_64[] = {rs_rX86_SP_64}; 58static const RegStorage core_temps_arr_32[] = {rs_rAX, rs_rCX, rs_rDX, rs_rBX}; 59static const RegStorage core_temps_arr_64[] = { 60 rs_rAX, rs_rCX, rs_rDX, rs_rSI, rs_rDI, 61#ifdef TARGET_REX_SUPPORT 62 rs_r8, rs_r9, rs_r10, rs_r11 63#endif 64}; 65static const RegStorage sp_temps_arr_32[] = { 66 rs_fr0, rs_fr1, rs_fr2, rs_fr3, rs_fr4, rs_fr5, rs_fr6, rs_fr7, 67}; 68static const RegStorage sp_temps_arr_64[] = { 69 rs_fr0, rs_fr1, rs_fr2, rs_fr3, rs_fr4, rs_fr5, rs_fr6, rs_fr7, 70#ifdef TARGET_REX_SUPPORT 71 rs_fr8, rs_fr9, rs_fr10, rs_fr11, rs_fr12, rs_fr13, rs_fr14, rs_fr15 72#endif 73}; 74static const RegStorage dp_temps_arr_32[] = { 75 rs_dr0, rs_dr1, rs_dr2, rs_dr3, rs_dr4, rs_dr5, rs_dr6, rs_dr7, 76}; 77static const RegStorage dp_temps_arr_64[] = { 78 rs_dr0, rs_dr1, rs_dr2, rs_dr3, rs_dr4, rs_dr5, rs_dr6, rs_dr7, 79#ifdef TARGET_REX_SUPPORT 80 rs_dr8, rs_dr9, rs_dr10, rs_dr11, rs_dr12, rs_dr13, rs_dr14, rs_dr15 81#endif 82}; 83 84static const RegStorage xp_temps_arr_32[] = { 85 rs_xr0, rs_xr1, rs_xr2, rs_xr3, rs_xr4, rs_xr5, rs_xr6, rs_xr7, 86}; 87static const RegStorage xp_temps_arr_64[] = { 88 rs_xr0, rs_xr1, rs_xr2, rs_xr3, rs_xr4, rs_xr5, rs_xr6, rs_xr7, 89#ifdef TARGET_REX_SUPPORT 90 rs_xr8, rs_xr9, rs_xr10, rs_xr11, rs_xr12, rs_xr13, rs_xr14, rs_xr15 91#endif 92}; 93 94static const std::vector<RegStorage> empty_pool; 95static const std::vector<RegStorage> core_regs_32(core_regs_arr_32, 96 core_regs_arr_32 + sizeof(core_regs_arr_32) / sizeof(core_regs_arr_32[0])); 97static const std::vector<RegStorage> core_regs_64(core_regs_arr_64, 98 core_regs_arr_64 + sizeof(core_regs_arr_64) / sizeof(core_regs_arr_64[0])); 99static const std::vector<RegStorage> sp_regs_32(sp_regs_arr_32, 100 sp_regs_arr_32 + sizeof(sp_regs_arr_32) / sizeof(sp_regs_arr_32[0])); 101static const std::vector<RegStorage> sp_regs_64(sp_regs_arr_64, 102 sp_regs_arr_64 + sizeof(sp_regs_arr_64) / sizeof(sp_regs_arr_64[0])); 103static const std::vector<RegStorage> dp_regs_32(dp_regs_arr_32, 104 dp_regs_arr_32 + sizeof(dp_regs_arr_32) / sizeof(dp_regs_arr_32[0])); 105static const std::vector<RegStorage> dp_regs_64(dp_regs_arr_64, 106 dp_regs_arr_64 + sizeof(dp_regs_arr_64) / sizeof(dp_regs_arr_64[0])); 107static const std::vector<RegStorage> reserved_regs_32(reserved_regs_arr_32, 108 reserved_regs_arr_32 + sizeof(reserved_regs_arr_32) / sizeof(reserved_regs_arr_32[0])); 109static const std::vector<RegStorage> reserved_regs_64(reserved_regs_arr_64, 110 reserved_regs_arr_64 + sizeof(reserved_regs_arr_64) / sizeof(reserved_regs_arr_64[0])); 111static const std::vector<RegStorage> core_temps_32(core_temps_arr_32, 112 core_temps_arr_32 + sizeof(core_temps_arr_32) / sizeof(core_temps_arr_32[0])); 113static const std::vector<RegStorage> core_temps_64(core_temps_arr_64, 114 core_temps_arr_64 + sizeof(core_temps_arr_64) / sizeof(core_temps_arr_64[0])); 115static const std::vector<RegStorage> sp_temps_32(sp_temps_arr_32, 116 sp_temps_arr_32 + sizeof(sp_temps_arr_32) / sizeof(sp_temps_arr_32[0])); 117static const std::vector<RegStorage> sp_temps_64(sp_temps_arr_64, 118 sp_temps_arr_64 + sizeof(sp_temps_arr_64) / sizeof(sp_temps_arr_64[0])); 119static const std::vector<RegStorage> dp_temps_32(dp_temps_arr_32, 120 dp_temps_arr_32 + sizeof(dp_temps_arr_32) / sizeof(dp_temps_arr_32[0])); 121static const std::vector<RegStorage> dp_temps_64(dp_temps_arr_64, 122 dp_temps_arr_64 + sizeof(dp_temps_arr_64) / sizeof(dp_temps_arr_64[0])); 123 124static const std::vector<RegStorage> xp_temps_32(xp_temps_arr_32, 125 xp_temps_arr_32 + sizeof(xp_temps_arr_32) / sizeof(xp_temps_arr_32[0])); 126static const std::vector<RegStorage> xp_temps_64(xp_temps_arr_64, 127 xp_temps_arr_64 + sizeof(xp_temps_arr_64) / sizeof(xp_temps_arr_64[0])); 128 129RegStorage rs_rX86_SP; 130 131X86NativeRegisterPool rX86_ARG0; 132X86NativeRegisterPool rX86_ARG1; 133X86NativeRegisterPool rX86_ARG2; 134X86NativeRegisterPool rX86_ARG3; 135X86NativeRegisterPool rX86_FARG0; 136X86NativeRegisterPool rX86_FARG1; 137X86NativeRegisterPool rX86_FARG2; 138X86NativeRegisterPool rX86_FARG3; 139X86NativeRegisterPool rX86_RET0; 140X86NativeRegisterPool rX86_RET1; 141X86NativeRegisterPool rX86_INVOKE_TGT; 142X86NativeRegisterPool rX86_COUNT; 143 144RegStorage rs_rX86_ARG0; 145RegStorage rs_rX86_ARG1; 146RegStorage rs_rX86_ARG2; 147RegStorage rs_rX86_ARG3; 148RegStorage rs_rX86_FARG0; 149RegStorage rs_rX86_FARG1; 150RegStorage rs_rX86_FARG2; 151RegStorage rs_rX86_FARG3; 152RegStorage rs_rX86_RET0; 153RegStorage rs_rX86_RET1; 154RegStorage rs_rX86_INVOKE_TGT; 155RegStorage rs_rX86_COUNT; 156 157RegLocation X86Mir2Lir::LocCReturn() { 158 return x86_loc_c_return; 159} 160 161RegLocation X86Mir2Lir::LocCReturnWide() { 162 return x86_loc_c_return_wide; 163} 164 165RegLocation X86Mir2Lir::LocCReturnFloat() { 166 return x86_loc_c_return_float; 167} 168 169RegLocation X86Mir2Lir::LocCReturnDouble() { 170 return x86_loc_c_return_double; 171} 172 173// Return a target-dependent special register. 174RegStorage X86Mir2Lir::TargetReg(SpecialTargetRegister reg) { 175 RegStorage res_reg = RegStorage::InvalidReg(); 176 switch (reg) { 177 case kSelf: res_reg = RegStorage::InvalidReg(); break; 178 case kSuspend: res_reg = RegStorage::InvalidReg(); break; 179 case kLr: res_reg = RegStorage::InvalidReg(); break; 180 case kPc: res_reg = RegStorage::InvalidReg(); break; 181 case kSp: res_reg = rs_rX86_SP; break; 182 case kArg0: res_reg = rs_rX86_ARG0; break; 183 case kArg1: res_reg = rs_rX86_ARG1; break; 184 case kArg2: res_reg = rs_rX86_ARG2; break; 185 case kArg3: res_reg = rs_rX86_ARG3; break; 186 case kFArg0: res_reg = rs_rX86_FARG0; break; 187 case kFArg1: res_reg = rs_rX86_FARG1; break; 188 case kFArg2: res_reg = rs_rX86_FARG2; break; 189 case kFArg3: res_reg = rs_rX86_FARG3; break; 190 case kRet0: res_reg = rs_rX86_RET0; break; 191 case kRet1: res_reg = rs_rX86_RET1; break; 192 case kInvokeTgt: res_reg = rs_rX86_INVOKE_TGT; break; 193 case kHiddenArg: res_reg = rs_rAX; break; 194 case kHiddenFpArg: res_reg = rs_fr0; break; 195 case kCount: res_reg = rs_rX86_COUNT; break; 196 } 197 return res_reg; 198} 199 200RegStorage X86Mir2Lir::GetArgMappingToPhysicalReg(int arg_num) { 201 // For the 32-bit internal ABI, the first 3 arguments are passed in registers. 202 // TODO: This is not 64-bit compliant and depends on new internal ABI. 203 switch (arg_num) { 204 case 0: 205 return rs_rX86_ARG1; 206 case 1: 207 return rs_rX86_ARG2; 208 case 2: 209 return rs_rX86_ARG3; 210 default: 211 return RegStorage::InvalidReg(); 212 } 213} 214 215/* 216 * Decode the register id. 217 */ 218uint64_t X86Mir2Lir::GetRegMaskCommon(RegStorage reg) { 219 uint64_t seed; 220 int shift; 221 int reg_id; 222 223 reg_id = reg.GetRegNum(); 224 /* Double registers in x86 are just a single FP register */ 225 seed = 1; 226 /* FP register starts at bit position 16 */ 227 shift = (reg.IsFloat() || reg.StorageSize() > 8) ? kX86FPReg0 : 0; 228 /* Expand the double register id into single offset */ 229 shift += reg_id; 230 return (seed << shift); 231} 232 233uint64_t X86Mir2Lir::GetPCUseDefEncoding() { 234 /* 235 * FIXME: might make sense to use a virtual resource encoding bit for pc. Might be 236 * able to clean up some of the x86/Arm_Mips differences 237 */ 238 LOG(FATAL) << "Unexpected call to GetPCUseDefEncoding for x86"; 239 return 0ULL; 240} 241 242void X86Mir2Lir::SetupTargetResourceMasks(LIR* lir, uint64_t flags) { 243 DCHECK(cu_->instruction_set == kX86 || cu_->instruction_set == kX86_64); 244 DCHECK(!lir->flags.use_def_invalid); 245 246 // X86-specific resource map setup here. 247 if (flags & REG_USE_SP) { 248 lir->u.m.use_mask |= ENCODE_X86_REG_SP; 249 } 250 251 if (flags & REG_DEF_SP) { 252 lir->u.m.def_mask |= ENCODE_X86_REG_SP; 253 } 254 255 if (flags & REG_DEFA) { 256 SetupRegMask(&lir->u.m.def_mask, rs_rAX.GetReg()); 257 } 258 259 if (flags & REG_DEFD) { 260 SetupRegMask(&lir->u.m.def_mask, rs_rDX.GetReg()); 261 } 262 if (flags & REG_USEA) { 263 SetupRegMask(&lir->u.m.use_mask, rs_rAX.GetReg()); 264 } 265 266 if (flags & REG_USEC) { 267 SetupRegMask(&lir->u.m.use_mask, rs_rCX.GetReg()); 268 } 269 270 if (flags & REG_USED) { 271 SetupRegMask(&lir->u.m.use_mask, rs_rDX.GetReg()); 272 } 273 274 if (flags & REG_USEB) { 275 SetupRegMask(&lir->u.m.use_mask, rs_rBX.GetReg()); 276 } 277 278 // Fixup hard to describe instruction: Uses rAX, rCX, rDI; sets rDI. 279 if (lir->opcode == kX86RepneScasw) { 280 SetupRegMask(&lir->u.m.use_mask, rs_rAX.GetReg()); 281 SetupRegMask(&lir->u.m.use_mask, rs_rCX.GetReg()); 282 SetupRegMask(&lir->u.m.use_mask, rs_rDI.GetReg()); 283 SetupRegMask(&lir->u.m.def_mask, rs_rDI.GetReg()); 284 } 285 286 if (flags & USE_FP_STACK) { 287 lir->u.m.use_mask |= ENCODE_X86_FP_STACK; 288 lir->u.m.def_mask |= ENCODE_X86_FP_STACK; 289 } 290} 291 292/* For dumping instructions */ 293static const char* x86RegName[] = { 294 "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", 295 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" 296}; 297 298static const char* x86CondName[] = { 299 "O", 300 "NO", 301 "B/NAE/C", 302 "NB/AE/NC", 303 "Z/EQ", 304 "NZ/NE", 305 "BE/NA", 306 "NBE/A", 307 "S", 308 "NS", 309 "P/PE", 310 "NP/PO", 311 "L/NGE", 312 "NL/GE", 313 "LE/NG", 314 "NLE/G" 315}; 316 317/* 318 * Interpret a format string and build a string no longer than size 319 * See format key in Assemble.cc. 320 */ 321std::string X86Mir2Lir::BuildInsnString(const char *fmt, LIR *lir, unsigned char* base_addr) { 322 std::string buf; 323 size_t i = 0; 324 size_t fmt_len = strlen(fmt); 325 while (i < fmt_len) { 326 if (fmt[i] != '!') { 327 buf += fmt[i]; 328 i++; 329 } else { 330 i++; 331 DCHECK_LT(i, fmt_len); 332 char operand_number_ch = fmt[i]; 333 i++; 334 if (operand_number_ch == '!') { 335 buf += "!"; 336 } else { 337 int operand_number = operand_number_ch - '0'; 338 DCHECK_LT(operand_number, 6); // Expect upto 6 LIR operands. 339 DCHECK_LT(i, fmt_len); 340 int operand = lir->operands[operand_number]; 341 switch (fmt[i]) { 342 case 'c': 343 DCHECK_LT(static_cast<size_t>(operand), sizeof(x86CondName)); 344 buf += x86CondName[operand]; 345 break; 346 case 'd': 347 buf += StringPrintf("%d", operand); 348 break; 349 case 'p': { 350 EmbeddedData *tab_rec = reinterpret_cast<EmbeddedData*>(UnwrapPointer(operand)); 351 buf += StringPrintf("0x%08x", tab_rec->offset); 352 break; 353 } 354 case 'r': 355 if (RegStorage::IsFloat(operand)) { 356 int fp_reg = RegStorage::RegNum(operand); 357 buf += StringPrintf("xmm%d", fp_reg); 358 } else { 359 int reg_num = RegStorage::RegNum(operand); 360 DCHECK_LT(static_cast<size_t>(reg_num), sizeof(x86RegName)); 361 buf += x86RegName[reg_num]; 362 } 363 break; 364 case 't': 365 buf += StringPrintf("0x%08" PRIxPTR " (L%p)", 366 reinterpret_cast<uintptr_t>(base_addr) + lir->offset + operand, 367 lir->target); 368 break; 369 default: 370 buf += StringPrintf("DecodeError '%c'", fmt[i]); 371 break; 372 } 373 i++; 374 } 375 } 376 } 377 return buf; 378} 379 380void X86Mir2Lir::DumpResourceMask(LIR *x86LIR, uint64_t mask, const char *prefix) { 381 char buf[256]; 382 buf[0] = 0; 383 384 if (mask == ENCODE_ALL) { 385 strcpy(buf, "all"); 386 } else { 387 char num[8]; 388 int i; 389 390 for (i = 0; i < kX86RegEnd; i++) { 391 if (mask & (1ULL << i)) { 392 snprintf(num, arraysize(num), "%d ", i); 393 strcat(buf, num); 394 } 395 } 396 397 if (mask & ENCODE_CCODE) { 398 strcat(buf, "cc "); 399 } 400 /* Memory bits */ 401 if (x86LIR && (mask & ENCODE_DALVIK_REG)) { 402 snprintf(buf + strlen(buf), arraysize(buf) - strlen(buf), "dr%d%s", 403 DECODE_ALIAS_INFO_REG(x86LIR->flags.alias_info), 404 (DECODE_ALIAS_INFO_WIDE(x86LIR->flags.alias_info)) ? "(+1)" : ""); 405 } 406 if (mask & ENCODE_LITERAL) { 407 strcat(buf, "lit "); 408 } 409 410 if (mask & ENCODE_HEAP_REF) { 411 strcat(buf, "heap "); 412 } 413 if (mask & ENCODE_MUST_NOT_ALIAS) { 414 strcat(buf, "noalias "); 415 } 416 } 417 if (buf[0]) { 418 LOG(INFO) << prefix << ": " << buf; 419 } 420} 421 422void X86Mir2Lir::AdjustSpillMask() { 423 // Adjustment for LR spilling, x86 has no LR so nothing to do here 424 core_spill_mask_ |= (1 << rs_rRET.GetRegNum()); 425 num_core_spills_++; 426} 427 428/* 429 * Mark a callee-save fp register as promoted. Note that 430 * vpush/vpop uses contiguous register lists so we must 431 * include any holes in the mask. Associate holes with 432 * Dalvik register INVALID_VREG (0xFFFFU). 433 */ 434void X86Mir2Lir::MarkPreservedSingle(int v_reg, RegStorage reg) { 435 UNIMPLEMENTED(FATAL) << "MarkPreservedSingle"; 436} 437 438void X86Mir2Lir::MarkPreservedDouble(int v_reg, RegStorage reg) { 439 UNIMPLEMENTED(FATAL) << "MarkPreservedDouble"; 440} 441 442RegStorage X86Mir2Lir::AllocateByteRegister() { 443 return AllocTypedTemp(false, kCoreReg); 444} 445 446/* Clobber all regs that might be used by an external C call */ 447void X86Mir2Lir::ClobberCallerSave() { 448 Clobber(rs_rAX); 449 Clobber(rs_rCX); 450 Clobber(rs_rDX); 451 Clobber(rs_rBX); 452} 453 454RegLocation X86Mir2Lir::GetReturnWideAlt() { 455 RegLocation res = LocCReturnWide(); 456 DCHECK(res.reg.GetLowReg() == rs_rAX.GetReg()); 457 DCHECK(res.reg.GetHighReg() == rs_rDX.GetReg()); 458 Clobber(rs_rAX); 459 Clobber(rs_rDX); 460 MarkInUse(rs_rAX); 461 MarkInUse(rs_rDX); 462 MarkWide(res.reg); 463 return res; 464} 465 466RegLocation X86Mir2Lir::GetReturnAlt() { 467 RegLocation res = LocCReturn(); 468 res.reg.SetReg(rs_rDX.GetReg()); 469 Clobber(rs_rDX); 470 MarkInUse(rs_rDX); 471 return res; 472} 473 474/* To be used when explicitly managing register use */ 475void X86Mir2Lir::LockCallTemps() { 476 LockTemp(rs_rX86_ARG0); 477 LockTemp(rs_rX86_ARG1); 478 LockTemp(rs_rX86_ARG2); 479 LockTemp(rs_rX86_ARG3); 480} 481 482/* To be used when explicitly managing register use */ 483void X86Mir2Lir::FreeCallTemps() { 484 FreeTemp(rs_rX86_ARG0); 485 FreeTemp(rs_rX86_ARG1); 486 FreeTemp(rs_rX86_ARG2); 487 FreeTemp(rs_rX86_ARG3); 488} 489 490bool X86Mir2Lir::ProvidesFullMemoryBarrier(X86OpCode opcode) { 491 switch (opcode) { 492 case kX86LockCmpxchgMR: 493 case kX86LockCmpxchgAR: 494 case kX86LockCmpxchg8bM: 495 case kX86LockCmpxchg8bA: 496 case kX86XchgMR: 497 case kX86Mfence: 498 // Atomic memory instructions provide full barrier. 499 return true; 500 default: 501 break; 502 } 503 504 // Conservative if cannot prove it provides full barrier. 505 return false; 506} 507 508bool X86Mir2Lir::GenMemBarrier(MemBarrierKind barrier_kind) { 509#if ANDROID_SMP != 0 510 // Start off with using the last LIR as the barrier. If it is not enough, then we will update it. 511 LIR* mem_barrier = last_lir_insn_; 512 513 bool ret = false; 514 /* 515 * According to the JSR-133 Cookbook, for x86 only StoreLoad barriers need memory fence. All other barriers 516 * (LoadLoad, LoadStore, StoreStore) are nops due to the x86 memory model. For those cases, all we need 517 * to ensure is that there is a scheduling barrier in place. 518 */ 519 if (barrier_kind == kStoreLoad) { 520 // If no LIR exists already that can be used a barrier, then generate an mfence. 521 if (mem_barrier == nullptr) { 522 mem_barrier = NewLIR0(kX86Mfence); 523 ret = true; 524 } 525 526 // If last instruction does not provide full barrier, then insert an mfence. 527 if (ProvidesFullMemoryBarrier(static_cast<X86OpCode>(mem_barrier->opcode)) == false) { 528 mem_barrier = NewLIR0(kX86Mfence); 529 ret = true; 530 } 531 } 532 533 // Now ensure that a scheduling barrier is in place. 534 if (mem_barrier == nullptr) { 535 GenBarrier(); 536 } else { 537 // Mark as a scheduling barrier. 538 DCHECK(!mem_barrier->flags.use_def_invalid); 539 mem_barrier->u.m.def_mask = ENCODE_ALL; 540 } 541 return ret; 542#else 543 return false; 544#endif 545} 546 547void X86Mir2Lir::CompilerInitializeRegAlloc() { 548 if (Gen64Bit()) { 549 reg_pool_ = new (arena_) RegisterPool(this, arena_, empty_pool, core_regs_64, sp_regs_64, 550 dp_regs_64, empty_pool, reserved_regs_64, 551 empty_pool, core_temps_64, sp_temps_64, dp_temps_64); 552 } else { 553 reg_pool_ = new (arena_) RegisterPool(this, arena_, core_regs_32, empty_pool, sp_regs_32, 554 dp_regs_32, reserved_regs_32, empty_pool, 555 core_temps_32, empty_pool, sp_temps_32, dp_temps_32); 556 } 557 558 // Target-specific adjustments. 559 560 // Add in XMM registers. 561 const std::vector<RegStorage> *xp_temps = Gen64Bit() ? &xp_temps_64 : &xp_temps_32; 562 for (RegStorage reg : *xp_temps) { 563 RegisterInfo* info = new (arena_) RegisterInfo(reg, GetRegMaskCommon(reg)); 564 reginfo_map_.Put(reg.GetReg(), info); 565 info->SetIsTemp(true); 566 } 567 568 // Alias single precision xmm to double xmms. 569 // TODO: as needed, add larger vector sizes - alias all to the largest. 570 GrowableArray<RegisterInfo*>::Iterator it(®_pool_->sp_regs_); 571 for (RegisterInfo* info = it.Next(); info != nullptr; info = it.Next()) { 572 int sp_reg_num = info->GetReg().GetRegNum(); 573 RegStorage xp_reg = RegStorage::Solo128(sp_reg_num); 574 RegisterInfo* xp_reg_info = GetRegInfo(xp_reg); 575 // 128-bit xmm vector register's master storage should refer to itself. 576 DCHECK_EQ(xp_reg_info, xp_reg_info->Master()); 577 578 // Redirect 32-bit vector's master storage to 128-bit vector. 579 info->SetMaster(xp_reg_info); 580 581 RegStorage dp_reg = RegStorage::Solo64(RegStorage::kFloatingPoint | sp_reg_num); 582 RegisterInfo* dp_reg_info = GetRegInfo(dp_reg); 583 // Redirect 64-bit vector's master storage to 128-bit vector. 584 dp_reg_info->SetMaster(xp_reg_info); 585 } 586 587 // Don't start allocating temps at r0/s0/d0 or you may clobber return regs in early-exit methods. 588 // TODO: adjust for x86/hard float calling convention. 589 reg_pool_->next_core_reg_ = 2; 590 reg_pool_->next_sp_reg_ = 2; 591 reg_pool_->next_dp_reg_ = 1; 592} 593 594void X86Mir2Lir::SpillCoreRegs() { 595 if (num_core_spills_ == 0) { 596 return; 597 } 598 // Spill mask not including fake return address register 599 uint32_t mask = core_spill_mask_ & ~(1 << rs_rRET.GetRegNum()); 600 int offset = frame_size_ - (GetInstructionSetPointerSize(cu_->instruction_set) * num_core_spills_); 601 for (int reg = 0; mask; mask >>= 1, reg++) { 602 if (mask & 0x1) { 603 StoreWordDisp(rs_rX86_SP, offset, RegStorage::Solo32(reg)); 604 offset += GetInstructionSetPointerSize(cu_->instruction_set); 605 } 606 } 607} 608 609void X86Mir2Lir::UnSpillCoreRegs() { 610 if (num_core_spills_ == 0) { 611 return; 612 } 613 // Spill mask not including fake return address register 614 uint32_t mask = core_spill_mask_ & ~(1 << rs_rRET.GetRegNum()); 615 int offset = frame_size_ - (GetInstructionSetPointerSize(cu_->instruction_set) * num_core_spills_); 616 for (int reg = 0; mask; mask >>= 1, reg++) { 617 if (mask & 0x1) { 618 LoadWordDisp(rs_rX86_SP, offset, RegStorage::Solo32(reg)); 619 offset += GetInstructionSetPointerSize(cu_->instruction_set); 620 } 621 } 622} 623 624bool X86Mir2Lir::IsUnconditionalBranch(LIR* lir) { 625 return (lir->opcode == kX86Jmp8 || lir->opcode == kX86Jmp32); 626} 627 628bool X86Mir2Lir::SupportsVolatileLoadStore(OpSize size) { 629 return true; 630} 631 632RegisterClass X86Mir2Lir::RegClassForFieldLoadStore(OpSize size, bool is_volatile) { 633 if (UNLIKELY(is_volatile)) { 634 // On x86, atomic 64-bit load/store requires an fp register. 635 // Smaller aligned load/store is atomic for both core and fp registers. 636 if (size == k64 || size == kDouble) { 637 return kFPReg; 638 } 639 } 640 return RegClassBySize(size); 641} 642 643X86Mir2Lir::X86Mir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena, bool gen64bit) 644 : Mir2Lir(cu, mir_graph, arena), 645 base_of_code_(nullptr), store_method_addr_(false), store_method_addr_used_(false), 646 method_address_insns_(arena, 100, kGrowableArrayMisc), 647 class_type_address_insns_(arena, 100, kGrowableArrayMisc), 648 call_method_insns_(arena, 100, kGrowableArrayMisc), 649 stack_decrement_(nullptr), stack_increment_(nullptr), gen64bit_(gen64bit), 650 const_vectors_(nullptr) { 651 store_method_addr_used_ = false; 652 if (kIsDebugBuild) { 653 for (int i = 0; i < kX86Last; i++) { 654 if (X86Mir2Lir::EncodingMap[i].opcode != i) { 655 LOG(FATAL) << "Encoding order for " << X86Mir2Lir::EncodingMap[i].name 656 << " is wrong: expecting " << i << ", seeing " 657 << static_cast<int>(X86Mir2Lir::EncodingMap[i].opcode); 658 } 659 } 660 } 661 if (Gen64Bit()) { 662 rs_rX86_SP = rs_rX86_SP_64; 663 664 rs_rX86_ARG0 = rs_rDI; 665 rs_rX86_ARG1 = rs_rSI; 666 rs_rX86_ARG2 = rs_rDX; 667 rs_rX86_ARG3 = rs_rCX; 668 rX86_ARG0 = rDI; 669 rX86_ARG1 = rSI; 670 rX86_ARG2 = rDX; 671 rX86_ARG3 = rCX; 672 // TODO: ARG4(r8), ARG5(r9), floating point args. 673 } else { 674 rs_rX86_SP = rs_rX86_SP_32; 675 676 rs_rX86_ARG0 = rs_rAX; 677 rs_rX86_ARG1 = rs_rCX; 678 rs_rX86_ARG2 = rs_rDX; 679 rs_rX86_ARG3 = rs_rBX; 680 rX86_ARG0 = rAX; 681 rX86_ARG1 = rCX; 682 rX86_ARG2 = rDX; 683 rX86_ARG3 = rBX; 684 } 685 rs_rX86_FARG0 = rs_rAX; 686 rs_rX86_FARG1 = rs_rCX; 687 rs_rX86_FARG2 = rs_rDX; 688 rs_rX86_FARG3 = rs_rBX; 689 rs_rX86_RET0 = rs_rAX; 690 rs_rX86_RET1 = rs_rDX; 691 rs_rX86_INVOKE_TGT = rs_rAX; 692 rs_rX86_COUNT = rs_rCX; 693 rX86_FARG0 = rAX; 694 rX86_FARG1 = rCX; 695 rX86_FARG2 = rDX; 696 rX86_FARG3 = rBX; 697 rX86_RET0 = rAX; 698 rX86_RET1 = rDX; 699 rX86_INVOKE_TGT = rAX; 700 rX86_COUNT = rCX; 701} 702 703Mir2Lir* X86CodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph, 704 ArenaAllocator* const arena) { 705 return new X86Mir2Lir(cu, mir_graph, arena, false); 706} 707 708Mir2Lir* X86_64CodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph, 709 ArenaAllocator* const arena) { 710 return new X86Mir2Lir(cu, mir_graph, arena, true); 711} 712 713// Not used in x86 714RegStorage X86Mir2Lir::LoadHelper(ThreadOffset<4> offset) { 715 LOG(FATAL) << "Unexpected use of LoadHelper in x86"; 716 return RegStorage::InvalidReg(); 717} 718 719// Not used in x86 720RegStorage X86Mir2Lir::LoadHelper(ThreadOffset<8> offset) { 721 LOG(FATAL) << "Unexpected use of LoadHelper in x86"; 722 return RegStorage::InvalidReg(); 723} 724 725LIR* X86Mir2Lir::CheckSuspendUsingLoad() { 726 LOG(FATAL) << "Unexpected use of CheckSuspendUsingLoad in x86"; 727 return nullptr; 728} 729 730uint64_t X86Mir2Lir::GetTargetInstFlags(int opcode) { 731 DCHECK(!IsPseudoLirOp(opcode)); 732 return X86Mir2Lir::EncodingMap[opcode].flags; 733} 734 735const char* X86Mir2Lir::GetTargetInstName(int opcode) { 736 DCHECK(!IsPseudoLirOp(opcode)); 737 return X86Mir2Lir::EncodingMap[opcode].name; 738} 739 740const char* X86Mir2Lir::GetTargetInstFmt(int opcode) { 741 DCHECK(!IsPseudoLirOp(opcode)); 742 return X86Mir2Lir::EncodingMap[opcode].fmt; 743} 744 745void X86Mir2Lir::GenConstWide(RegLocation rl_dest, int64_t value) { 746 // Can we do this directly to memory? 747 rl_dest = UpdateLocWide(rl_dest); 748 if ((rl_dest.location == kLocDalvikFrame) || 749 (rl_dest.location == kLocCompilerTemp)) { 750 int32_t val_lo = Low32Bits(value); 751 int32_t val_hi = High32Bits(value); 752 int r_base = TargetReg(kSp).GetReg(); 753 int displacement = SRegOffset(rl_dest.s_reg_low); 754 755 LIR * store = NewLIR3(kX86Mov32MI, r_base, displacement + LOWORD_OFFSET, val_lo); 756 AnnotateDalvikRegAccess(store, (displacement + LOWORD_OFFSET) >> 2, 757 false /* is_load */, true /* is64bit */); 758 store = NewLIR3(kX86Mov32MI, r_base, displacement + HIWORD_OFFSET, val_hi); 759 AnnotateDalvikRegAccess(store, (displacement + HIWORD_OFFSET) >> 2, 760 false /* is_load */, true /* is64bit */); 761 return; 762 } 763 764 // Just use the standard code to do the generation. 765 Mir2Lir::GenConstWide(rl_dest, value); 766} 767 768// TODO: Merge with existing RegLocation dumper in vreg_analysis.cc 769void X86Mir2Lir::DumpRegLocation(RegLocation loc) { 770 LOG(INFO) << "location: " << loc.location << ',' 771 << (loc.wide ? " w" : " ") 772 << (loc.defined ? " D" : " ") 773 << (loc.is_const ? " c" : " ") 774 << (loc.fp ? " F" : " ") 775 << (loc.core ? " C" : " ") 776 << (loc.ref ? " r" : " ") 777 << (loc.high_word ? " h" : " ") 778 << (loc.home ? " H" : " ") 779 << ", low: " << static_cast<int>(loc.reg.GetLowReg()) 780 << ", high: " << static_cast<int>(loc.reg.GetHighReg()) 781 << ", s_reg: " << loc.s_reg_low 782 << ", orig: " << loc.orig_sreg; 783} 784 785void X86Mir2Lir::Materialize() { 786 // A good place to put the analysis before starting. 787 AnalyzeMIR(); 788 789 // Now continue with regular code generation. 790 Mir2Lir::Materialize(); 791} 792 793void X86Mir2Lir::LoadMethodAddress(const MethodReference& target_method, InvokeType type, 794 SpecialTargetRegister symbolic_reg) { 795 /* 796 * For x86, just generate a 32 bit move immediate instruction, that will be filled 797 * in at 'link time'. For now, put a unique value based on target to ensure that 798 * code deduplication works. 799 */ 800 int target_method_idx = target_method.dex_method_index; 801 const DexFile* target_dex_file = target_method.dex_file; 802 const DexFile::MethodId& target_method_id = target_dex_file->GetMethodId(target_method_idx); 803 uintptr_t target_method_id_ptr = reinterpret_cast<uintptr_t>(&target_method_id); 804 805 // Generate the move instruction with the unique pointer and save index, dex_file, and type. 806 LIR *move = RawLIR(current_dalvik_offset_, kX86Mov32RI, TargetReg(symbolic_reg).GetReg(), 807 static_cast<int>(target_method_id_ptr), target_method_idx, 808 WrapPointer(const_cast<DexFile*>(target_dex_file)), type); 809 AppendLIR(move); 810 method_address_insns_.Insert(move); 811} 812 813void X86Mir2Lir::LoadClassType(uint32_t type_idx, SpecialTargetRegister symbolic_reg) { 814 /* 815 * For x86, just generate a 32 bit move immediate instruction, that will be filled 816 * in at 'link time'. For now, put a unique value based on target to ensure that 817 * code deduplication works. 818 */ 819 const DexFile::TypeId& id = cu_->dex_file->GetTypeId(type_idx); 820 uintptr_t ptr = reinterpret_cast<uintptr_t>(&id); 821 822 // Generate the move instruction with the unique pointer and save index and type. 823 LIR *move = RawLIR(current_dalvik_offset_, kX86Mov32RI, TargetReg(symbolic_reg).GetReg(), 824 static_cast<int>(ptr), type_idx); 825 AppendLIR(move); 826 class_type_address_insns_.Insert(move); 827} 828 829LIR *X86Mir2Lir::CallWithLinkerFixup(const MethodReference& target_method, InvokeType type) { 830 /* 831 * For x86, just generate a 32 bit call relative instruction, that will be filled 832 * in at 'link time'. For now, put a unique value based on target to ensure that 833 * code deduplication works. 834 */ 835 int target_method_idx = target_method.dex_method_index; 836 const DexFile* target_dex_file = target_method.dex_file; 837 const DexFile::MethodId& target_method_id = target_dex_file->GetMethodId(target_method_idx); 838 uintptr_t target_method_id_ptr = reinterpret_cast<uintptr_t>(&target_method_id); 839 840 // Generate the call instruction with the unique pointer and save index, dex_file, and type. 841 LIR *call = RawLIR(current_dalvik_offset_, kX86CallI, static_cast<int>(target_method_id_ptr), 842 target_method_idx, WrapPointer(const_cast<DexFile*>(target_dex_file)), type); 843 AppendLIR(call); 844 call_method_insns_.Insert(call); 845 return call; 846} 847 848/* 849 * @brief Enter a 32 bit quantity into a buffer 850 * @param buf buffer. 851 * @param data Data value. 852 */ 853 854static void PushWord(std::vector<uint8_t>&buf, int32_t data) { 855 buf.push_back(data & 0xff); 856 buf.push_back((data >> 8) & 0xff); 857 buf.push_back((data >> 16) & 0xff); 858 buf.push_back((data >> 24) & 0xff); 859} 860 861void X86Mir2Lir::InstallLiteralPools() { 862 // These are handled differently for x86. 863 DCHECK(code_literal_list_ == nullptr); 864 DCHECK(method_literal_list_ == nullptr); 865 DCHECK(class_literal_list_ == nullptr); 866 867 // Align to 16 byte boundary. We have implicit knowledge that the start of the method is 868 // on a 4 byte boundary. How can I check this if it changes (other than aligned loads 869 // will fail at runtime)? 870 if (const_vectors_ != nullptr) { 871 int align_size = (16-4) - (code_buffer_.size() & 0xF); 872 if (align_size < 0) { 873 align_size += 16; 874 } 875 876 while (align_size > 0) { 877 code_buffer_.push_back(0); 878 align_size--; 879 } 880 for (LIR *p = const_vectors_; p != nullptr; p = p->next) { 881 PushWord(code_buffer_, p->operands[0]); 882 PushWord(code_buffer_, p->operands[1]); 883 PushWord(code_buffer_, p->operands[2]); 884 PushWord(code_buffer_, p->operands[3]); 885 } 886 } 887 888 // Handle the fixups for methods. 889 for (uint32_t i = 0; i < method_address_insns_.Size(); i++) { 890 LIR* p = method_address_insns_.Get(i); 891 DCHECK_EQ(p->opcode, kX86Mov32RI); 892 uint32_t target_method_idx = p->operands[2]; 893 const DexFile* target_dex_file = 894 reinterpret_cast<const DexFile*>(UnwrapPointer(p->operands[3])); 895 896 // The offset to patch is the last 4 bytes of the instruction. 897 int patch_offset = p->offset + p->flags.size - 4; 898 cu_->compiler_driver->AddMethodPatch(cu_->dex_file, cu_->class_def_idx, 899 cu_->method_idx, cu_->invoke_type, 900 target_method_idx, target_dex_file, 901 static_cast<InvokeType>(p->operands[4]), 902 patch_offset); 903 } 904 905 // Handle the fixups for class types. 906 for (uint32_t i = 0; i < class_type_address_insns_.Size(); i++) { 907 LIR* p = class_type_address_insns_.Get(i); 908 DCHECK_EQ(p->opcode, kX86Mov32RI); 909 uint32_t target_method_idx = p->operands[2]; 910 911 // The offset to patch is the last 4 bytes of the instruction. 912 int patch_offset = p->offset + p->flags.size - 4; 913 cu_->compiler_driver->AddClassPatch(cu_->dex_file, cu_->class_def_idx, 914 cu_->method_idx, target_method_idx, patch_offset); 915 } 916 917 // And now the PC-relative calls to methods. 918 for (uint32_t i = 0; i < call_method_insns_.Size(); i++) { 919 LIR* p = call_method_insns_.Get(i); 920 DCHECK_EQ(p->opcode, kX86CallI); 921 uint32_t target_method_idx = p->operands[1]; 922 const DexFile* target_dex_file = 923 reinterpret_cast<const DexFile*>(UnwrapPointer(p->operands[2])); 924 925 // The offset to patch is the last 4 bytes of the instruction. 926 int patch_offset = p->offset + p->flags.size - 4; 927 cu_->compiler_driver->AddRelativeCodePatch(cu_->dex_file, cu_->class_def_idx, 928 cu_->method_idx, cu_->invoke_type, 929 target_method_idx, target_dex_file, 930 static_cast<InvokeType>(p->operands[3]), 931 patch_offset, -4 /* offset */); 932 } 933 934 // And do the normal processing. 935 Mir2Lir::InstallLiteralPools(); 936} 937 938/* 939 * Fast string.index_of(I) & (II). Inline check for simple case of char <= 0xffff, 940 * otherwise bails to standard library code. 941 */ 942bool X86Mir2Lir::GenInlinedIndexOf(CallInfo* info, bool zero_based) { 943 ClobberCallerSave(); 944 LockCallTemps(); // Using fixed registers 945 946 // EAX: 16 bit character being searched. 947 // ECX: count: number of words to be searched. 948 // EDI: String being searched. 949 // EDX: temporary during execution. 950 // EBX: temporary during execution. 951 952 RegLocation rl_obj = info->args[0]; 953 RegLocation rl_char = info->args[1]; 954 RegLocation rl_start; // Note: only present in III flavor or IndexOf. 955 956 uint32_t char_value = 957 rl_char.is_const ? mir_graph_->ConstantValue(rl_char.orig_sreg) : 0; 958 959 if (char_value > 0xFFFF) { 960 // We have to punt to the real String.indexOf. 961 return false; 962 } 963 964 // Okay, we are commited to inlining this. 965 RegLocation rl_return = GetReturn(false); 966 RegLocation rl_dest = InlineTarget(info); 967 968 // Is the string non-NULL? 969 LoadValueDirectFixed(rl_obj, rs_rDX); 970 GenNullCheck(rs_rDX, info->opt_flags); 971 info->opt_flags |= MIR_IGNORE_NULL_CHECK; // Record that we've null checked. 972 973 // Does the character fit in 16 bits? 974 LIR* slowpath_branch = nullptr; 975 if (rl_char.is_const) { 976 // We need the value in EAX. 977 LoadConstantNoClobber(rs_rAX, char_value); 978 } else { 979 // Character is not a constant; compare at runtime. 980 LoadValueDirectFixed(rl_char, rs_rAX); 981 slowpath_branch = OpCmpImmBranch(kCondGt, rs_rAX, 0xFFFF, nullptr); 982 } 983 984 // From here down, we know that we are looking for a char that fits in 16 bits. 985 // Location of reference to data array within the String object. 986 int value_offset = mirror::String::ValueOffset().Int32Value(); 987 // Location of count within the String object. 988 int count_offset = mirror::String::CountOffset().Int32Value(); 989 // Starting offset within data array. 990 int offset_offset = mirror::String::OffsetOffset().Int32Value(); 991 // Start of char data with array_. 992 int data_offset = mirror::Array::DataOffset(sizeof(uint16_t)).Int32Value(); 993 994 // Character is in EAX. 995 // Object pointer is in EDX. 996 997 // We need to preserve EDI, but have no spare registers, so push it on the stack. 998 // We have to remember that all stack addresses after this are offset by sizeof(EDI). 999 NewLIR1(kX86Push32R, rs_rDI.GetReg()); 1000 1001 // Compute the number of words to search in to rCX. 1002 Load32Disp(rs_rDX, count_offset, rs_rCX); 1003 LIR *length_compare = nullptr; 1004 int start_value = 0; 1005 bool is_index_on_stack = false; 1006 if (zero_based) { 1007 // We have to handle an empty string. Use special instruction JECXZ. 1008 length_compare = NewLIR0(kX86Jecxz8); 1009 } else { 1010 rl_start = info->args[2]; 1011 // We have to offset by the start index. 1012 if (rl_start.is_const) { 1013 start_value = mir_graph_->ConstantValue(rl_start.orig_sreg); 1014 start_value = std::max(start_value, 0); 1015 1016 // Is the start > count? 1017 length_compare = OpCmpImmBranch(kCondLe, rs_rCX, start_value, nullptr); 1018 1019 if (start_value != 0) { 1020 OpRegImm(kOpSub, rs_rCX, start_value); 1021 } 1022 } else { 1023 // Runtime start index. 1024 rl_start = UpdateLocTyped(rl_start, kCoreReg); 1025 if (rl_start.location == kLocPhysReg) { 1026 // Handle "start index < 0" case. 1027 OpRegReg(kOpXor, rs_rBX, rs_rBX); 1028 OpRegReg(kOpCmp, rl_start.reg, rs_rBX); 1029 OpCondRegReg(kOpCmov, kCondLt, rl_start.reg, rs_rBX); 1030 1031 // The length of the string should be greater than the start index. 1032 length_compare = OpCmpBranch(kCondLe, rs_rCX, rl_start.reg, nullptr); 1033 OpRegReg(kOpSub, rs_rCX, rl_start.reg); 1034 if (rl_start.reg == rs_rDI) { 1035 // The special case. We will use EDI further, so lets put start index to stack. 1036 NewLIR1(kX86Push32R, rs_rDI.GetReg()); 1037 is_index_on_stack = true; 1038 } 1039 } else { 1040 // Load the start index from stack, remembering that we pushed EDI. 1041 int displacement = SRegOffset(rl_start.s_reg_low) + sizeof(uint32_t); 1042 Load32Disp(rs_rX86_SP, displacement, rs_rBX); 1043 OpRegReg(kOpXor, rs_rDI, rs_rDI); 1044 OpRegReg(kOpCmp, rs_rBX, rs_rDI); 1045 OpCondRegReg(kOpCmov, kCondLt, rs_rBX, rs_rDI); 1046 1047 length_compare = OpCmpBranch(kCondLe, rs_rCX, rs_rBX, nullptr); 1048 OpRegReg(kOpSub, rs_rCX, rs_rBX); 1049 // Put the start index to stack. 1050 NewLIR1(kX86Push32R, rs_rBX.GetReg()); 1051 is_index_on_stack = true; 1052 } 1053 } 1054 } 1055 DCHECK(length_compare != nullptr); 1056 1057 // ECX now contains the count in words to be searched. 1058 1059 // Load the address of the string into EBX. 1060 // The string starts at VALUE(String) + 2 * OFFSET(String) + DATA_OFFSET. 1061 Load32Disp(rs_rDX, value_offset, rs_rDI); 1062 Load32Disp(rs_rDX, offset_offset, rs_rBX); 1063 OpLea(rs_rBX, rs_rDI, rs_rBX, 1, data_offset); 1064 1065 // Now compute into EDI where the search will start. 1066 if (zero_based || rl_start.is_const) { 1067 if (start_value == 0) { 1068 OpRegCopy(rs_rDI, rs_rBX); 1069 } else { 1070 NewLIR3(kX86Lea32RM, rs_rDI.GetReg(), rs_rBX.GetReg(), 2 * start_value); 1071 } 1072 } else { 1073 if (is_index_on_stack == true) { 1074 // Load the start index from stack. 1075 NewLIR1(kX86Pop32R, rs_rDX.GetReg()); 1076 OpLea(rs_rDI, rs_rBX, rs_rDX, 1, 0); 1077 } else { 1078 OpLea(rs_rDI, rs_rBX, rl_start.reg, 1, 0); 1079 } 1080 } 1081 1082 // EDI now contains the start of the string to be searched. 1083 // We are all prepared to do the search for the character. 1084 NewLIR0(kX86RepneScasw); 1085 1086 // Did we find a match? 1087 LIR* failed_branch = OpCondBranch(kCondNe, nullptr); 1088 1089 // yes, we matched. Compute the index of the result. 1090 // index = ((curr_ptr - orig_ptr) / 2) - 1. 1091 OpRegReg(kOpSub, rs_rDI, rs_rBX); 1092 OpRegImm(kOpAsr, rs_rDI, 1); 1093 NewLIR3(kX86Lea32RM, rl_return.reg.GetReg(), rs_rDI.GetReg(), -1); 1094 LIR *all_done = NewLIR1(kX86Jmp8, 0); 1095 1096 // Failed to match; return -1. 1097 LIR *not_found = NewLIR0(kPseudoTargetLabel); 1098 length_compare->target = not_found; 1099 failed_branch->target = not_found; 1100 LoadConstantNoClobber(rl_return.reg, -1); 1101 1102 // And join up at the end. 1103 all_done->target = NewLIR0(kPseudoTargetLabel); 1104 // Restore EDI from the stack. 1105 NewLIR1(kX86Pop32R, rs_rDI.GetReg()); 1106 1107 // Out of line code returns here. 1108 if (slowpath_branch != nullptr) { 1109 LIR *return_point = NewLIR0(kPseudoTargetLabel); 1110 AddIntrinsicSlowPath(info, slowpath_branch, return_point); 1111 } 1112 1113 StoreValue(rl_dest, rl_return); 1114 return true; 1115} 1116 1117/* 1118 * @brief Enter an 'advance LOC' into the FDE buffer 1119 * @param buf FDE buffer. 1120 * @param increment Amount by which to increase the current location. 1121 */ 1122static void AdvanceLoc(std::vector<uint8_t>&buf, uint32_t increment) { 1123 if (increment < 64) { 1124 // Encoding in opcode. 1125 buf.push_back(0x1 << 6 | increment); 1126 } else if (increment < 256) { 1127 // Single byte delta. 1128 buf.push_back(0x02); 1129 buf.push_back(increment); 1130 } else if (increment < 256 * 256) { 1131 // Two byte delta. 1132 buf.push_back(0x03); 1133 buf.push_back(increment & 0xff); 1134 buf.push_back((increment >> 8) & 0xff); 1135 } else { 1136 // Four byte delta. 1137 buf.push_back(0x04); 1138 PushWord(buf, increment); 1139 } 1140} 1141 1142 1143std::vector<uint8_t>* X86CFIInitialization() { 1144 return X86Mir2Lir::ReturnCommonCallFrameInformation(); 1145} 1146 1147std::vector<uint8_t>* X86Mir2Lir::ReturnCommonCallFrameInformation() { 1148 std::vector<uint8_t>*cfi_info = new std::vector<uint8_t>; 1149 1150 // Length of the CIE (except for this field). 1151 PushWord(*cfi_info, 16); 1152 1153 // CIE id. 1154 PushWord(*cfi_info, 0xFFFFFFFFU); 1155 1156 // Version: 3. 1157 cfi_info->push_back(0x03); 1158 1159 // Augmentation: empty string. 1160 cfi_info->push_back(0x0); 1161 1162 // Code alignment: 1. 1163 cfi_info->push_back(0x01); 1164 1165 // Data alignment: -4. 1166 cfi_info->push_back(0x7C); 1167 1168 // Return address register (R8). 1169 cfi_info->push_back(0x08); 1170 1171 // Initial return PC is 4(ESP): DW_CFA_def_cfa R4 4. 1172 cfi_info->push_back(0x0C); 1173 cfi_info->push_back(0x04); 1174 cfi_info->push_back(0x04); 1175 1176 // Return address location: 0(SP): DW_CFA_offset R8 1 (* -4);. 1177 cfi_info->push_back(0x2 << 6 | 0x08); 1178 cfi_info->push_back(0x01); 1179 1180 // And 2 Noops to align to 4 byte boundary. 1181 cfi_info->push_back(0x0); 1182 cfi_info->push_back(0x0); 1183 1184 DCHECK_EQ(cfi_info->size() & 3, 0U); 1185 return cfi_info; 1186} 1187 1188static void EncodeUnsignedLeb128(std::vector<uint8_t>& buf, uint32_t value) { 1189 uint8_t buffer[12]; 1190 uint8_t *ptr = EncodeUnsignedLeb128(buffer, value); 1191 for (uint8_t *p = buffer; p < ptr; p++) { 1192 buf.push_back(*p); 1193 } 1194} 1195 1196std::vector<uint8_t>* X86Mir2Lir::ReturnCallFrameInformation() { 1197 std::vector<uint8_t>*cfi_info = new std::vector<uint8_t>; 1198 1199 // Generate the FDE for the method. 1200 DCHECK_NE(data_offset_, 0U); 1201 1202 // Length (will be filled in later in this routine). 1203 PushWord(*cfi_info, 0); 1204 1205 // CIE_pointer (can be filled in by linker); might be left at 0 if there is only 1206 // one CIE for the whole debug_frame section. 1207 PushWord(*cfi_info, 0); 1208 1209 // 'initial_location' (filled in by linker). 1210 PushWord(*cfi_info, 0); 1211 1212 // 'address_range' (number of bytes in the method). 1213 PushWord(*cfi_info, data_offset_); 1214 1215 // The instructions in the FDE. 1216 if (stack_decrement_ != nullptr) { 1217 // Advance LOC to just past the stack decrement. 1218 uint32_t pc = NEXT_LIR(stack_decrement_)->offset; 1219 AdvanceLoc(*cfi_info, pc); 1220 1221 // Now update the offset to the call frame: DW_CFA_def_cfa_offset frame_size. 1222 cfi_info->push_back(0x0e); 1223 EncodeUnsignedLeb128(*cfi_info, frame_size_); 1224 1225 // We continue with that stack until the epilogue. 1226 if (stack_increment_ != nullptr) { 1227 uint32_t new_pc = NEXT_LIR(stack_increment_)->offset; 1228 AdvanceLoc(*cfi_info, new_pc - pc); 1229 1230 // We probably have code snippets after the epilogue, so save the 1231 // current state: DW_CFA_remember_state. 1232 cfi_info->push_back(0x0a); 1233 1234 // We have now popped the stack: DW_CFA_def_cfa_offset 4. There is only the return 1235 // PC on the stack now. 1236 cfi_info->push_back(0x0e); 1237 EncodeUnsignedLeb128(*cfi_info, 4); 1238 1239 // Everything after that is the same as before the epilogue. 1240 // Stack bump was followed by RET instruction. 1241 LIR *post_ret_insn = NEXT_LIR(NEXT_LIR(stack_increment_)); 1242 if (post_ret_insn != nullptr) { 1243 pc = new_pc; 1244 new_pc = post_ret_insn->offset; 1245 AdvanceLoc(*cfi_info, new_pc - pc); 1246 // Restore the state: DW_CFA_restore_state. 1247 cfi_info->push_back(0x0b); 1248 } 1249 } 1250 } 1251 1252 // Padding to a multiple of 4 1253 while ((cfi_info->size() & 3) != 0) { 1254 // DW_CFA_nop is encoded as 0. 1255 cfi_info->push_back(0); 1256 } 1257 1258 // Set the length of the FDE inside the generated bytes. 1259 uint32_t length = cfi_info->size() - 4; 1260 (*cfi_info)[0] = length; 1261 (*cfi_info)[1] = length >> 8; 1262 (*cfi_info)[2] = length >> 16; 1263 (*cfi_info)[3] = length >> 24; 1264 return cfi_info; 1265} 1266 1267void X86Mir2Lir::GenMachineSpecificExtendedMethodMIR(BasicBlock* bb, MIR* mir) { 1268 switch (static_cast<ExtendedMIROpcode>(mir->dalvikInsn.opcode)) { 1269 case kMirOpConstVector: 1270 GenConst128(bb, mir); 1271 break; 1272 case kMirOpMoveVector: 1273 GenMoveVector(bb, mir); 1274 break; 1275 case kMirOpPackedMultiply: 1276 GenMultiplyVector(bb, mir); 1277 break; 1278 case kMirOpPackedAddition: 1279 GenAddVector(bb, mir); 1280 break; 1281 case kMirOpPackedSubtract: 1282 GenSubtractVector(bb, mir); 1283 break; 1284 case kMirOpPackedShiftLeft: 1285 GenShiftLeftVector(bb, mir); 1286 break; 1287 case kMirOpPackedSignedShiftRight: 1288 GenSignedShiftRightVector(bb, mir); 1289 break; 1290 case kMirOpPackedUnsignedShiftRight: 1291 GenUnsignedShiftRightVector(bb, mir); 1292 break; 1293 case kMirOpPackedAnd: 1294 GenAndVector(bb, mir); 1295 break; 1296 case kMirOpPackedOr: 1297 GenOrVector(bb, mir); 1298 break; 1299 case kMirOpPackedXor: 1300 GenXorVector(bb, mir); 1301 break; 1302 case kMirOpPackedAddReduce: 1303 GenAddReduceVector(bb, mir); 1304 break; 1305 case kMirOpPackedReduce: 1306 GenReduceVector(bb, mir); 1307 break; 1308 case kMirOpPackedSet: 1309 GenSetVector(bb, mir); 1310 break; 1311 default: 1312 break; 1313 } 1314} 1315 1316void X86Mir2Lir::GenConst128(BasicBlock* bb, MIR* mir) { 1317 int type_size = mir->dalvikInsn.vA; 1318 // We support 128 bit vectors. 1319 DCHECK_EQ(type_size & 0xFFFF, 128); 1320 RegStorage rs_dest = RegStorage::Solo128(mir->dalvikInsn.vB); 1321 uint32_t *args = mir->dalvikInsn.arg; 1322 int reg = rs_dest.GetReg(); 1323 // Check for all 0 case. 1324 if (args[0] == 0 && args[1] == 0 && args[2] == 0 && args[3] == 0) { 1325 NewLIR2(kX86XorpsRR, reg, reg); 1326 return; 1327 } 1328 // Okay, load it from the constant vector area. 1329 LIR *data_target = ScanVectorLiteral(mir); 1330 if (data_target == nullptr) { 1331 data_target = AddVectorLiteral(mir); 1332 } 1333 1334 // Address the start of the method. 1335 RegLocation rl_method = mir_graph_->GetRegLocation(base_of_code_->s_reg_low); 1336 rl_method = LoadValue(rl_method, kCoreReg); 1337 1338 // Load the proper value from the literal area. 1339 // We don't know the proper offset for the value, so pick one that will force 1340 // 4 byte offset. We will fix this up in the assembler later to have the right 1341 // value. 1342 LIR *load = NewLIR3(kX86Mova128RM, reg, rl_method.reg.GetReg(), 256 /* bogus */); 1343 load->flags.fixup = kFixupLoad; 1344 load->target = data_target; 1345 SetMemRefType(load, true, kLiteral); 1346} 1347 1348void X86Mir2Lir::GenMoveVector(BasicBlock *bb, MIR *mir) { 1349 // We only support 128 bit registers. 1350 DCHECK_EQ(mir->dalvikInsn.vA & 0xFFFF, 128U); 1351 RegStorage rs_dest = RegStorage::Solo128(mir->dalvikInsn.vB); 1352 RegStorage rs_src = RegStorage::Solo128(mir->dalvikInsn.vC); 1353 NewLIR2(kX86Mova128RR, rs_dest.GetReg(), rs_src.GetReg()); 1354} 1355 1356void X86Mir2Lir::GenMultiplyVector(BasicBlock *bb, MIR *mir) { 1357 DCHECK_EQ(mir->dalvikInsn.vA & 0xFFFF, 128U); 1358 OpSize opsize = static_cast<OpSize>(mir->dalvikInsn.vA >> 16); 1359 RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vB); 1360 RegStorage rs_src2 = RegStorage::Solo128(mir->dalvikInsn.vC); 1361 int opcode = 0; 1362 switch (opsize) { 1363 case k32: 1364 opcode = kX86PmulldRR; 1365 break; 1366 case kSignedHalf: 1367 opcode = kX86PmullwRR; 1368 break; 1369 case kSingle: 1370 opcode = kX86MulpsRR; 1371 break; 1372 case kDouble: 1373 opcode = kX86MulpdRR; 1374 break; 1375 default: 1376 LOG(FATAL) << "Unsupported vector multiply " << opsize; 1377 break; 1378 } 1379 NewLIR2(opcode, rs_dest_src1.GetReg(), rs_src2.GetReg()); 1380} 1381 1382void X86Mir2Lir::GenAddVector(BasicBlock *bb, MIR *mir) { 1383 DCHECK_EQ(mir->dalvikInsn.vA & 0xFFFF, 128U); 1384 OpSize opsize = static_cast<OpSize>(mir->dalvikInsn.vA >> 16); 1385 RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vB); 1386 RegStorage rs_src2 = RegStorage::Solo128(mir->dalvikInsn.vC); 1387 int opcode = 0; 1388 switch (opsize) { 1389 case k32: 1390 opcode = kX86PadddRR; 1391 break; 1392 case kSignedHalf: 1393 case kUnsignedHalf: 1394 opcode = kX86PaddwRR; 1395 break; 1396 case kUnsignedByte: 1397 case kSignedByte: 1398 opcode = kX86PaddbRR; 1399 break; 1400 case kSingle: 1401 opcode = kX86AddpsRR; 1402 break; 1403 case kDouble: 1404 opcode = kX86AddpdRR; 1405 break; 1406 default: 1407 LOG(FATAL) << "Unsupported vector addition " << opsize; 1408 break; 1409 } 1410 NewLIR2(opcode, rs_dest_src1.GetReg(), rs_src2.GetReg()); 1411} 1412 1413void X86Mir2Lir::GenSubtractVector(BasicBlock *bb, MIR *mir) { 1414 DCHECK_EQ(mir->dalvikInsn.vA & 0xFFFF, 128U); 1415 OpSize opsize = static_cast<OpSize>(mir->dalvikInsn.vA >> 16); 1416 RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vB); 1417 RegStorage rs_src2 = RegStorage::Solo128(mir->dalvikInsn.vC); 1418 int opcode = 0; 1419 switch (opsize) { 1420 case k32: 1421 opcode = kX86PsubdRR; 1422 break; 1423 case kSignedHalf: 1424 case kUnsignedHalf: 1425 opcode = kX86PsubwRR; 1426 break; 1427 case kUnsignedByte: 1428 case kSignedByte: 1429 opcode = kX86PsubbRR; 1430 break; 1431 case kSingle: 1432 opcode = kX86SubpsRR; 1433 break; 1434 case kDouble: 1435 opcode = kX86SubpdRR; 1436 break; 1437 default: 1438 LOG(FATAL) << "Unsupported vector subtraction " << opsize; 1439 break; 1440 } 1441 NewLIR2(opcode, rs_dest_src1.GetReg(), rs_src2.GetReg()); 1442} 1443 1444void X86Mir2Lir::GenShiftLeftVector(BasicBlock *bb, MIR *mir) { 1445 DCHECK_EQ(mir->dalvikInsn.vA & 0xFFFF, 128U); 1446 OpSize opsize = static_cast<OpSize>(mir->dalvikInsn.vA >> 16); 1447 RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vB); 1448 int imm = mir->dalvikInsn.vC; 1449 int opcode = 0; 1450 switch (opsize) { 1451 case k32: 1452 opcode = kX86PslldRI; 1453 break; 1454 case k64: 1455 opcode = kX86PsllqRI; 1456 break; 1457 case kSignedHalf: 1458 case kUnsignedHalf: 1459 opcode = kX86PsllwRI; 1460 break; 1461 default: 1462 LOG(FATAL) << "Unsupported vector shift left " << opsize; 1463 break; 1464 } 1465 NewLIR2(opcode, rs_dest_src1.GetReg(), imm); 1466} 1467 1468void X86Mir2Lir::GenSignedShiftRightVector(BasicBlock *bb, MIR *mir) { 1469 DCHECK_EQ(mir->dalvikInsn.vA & 0xFFFF, 128U); 1470 OpSize opsize = static_cast<OpSize>(mir->dalvikInsn.vA >> 16); 1471 RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vB); 1472 int imm = mir->dalvikInsn.vC; 1473 int opcode = 0; 1474 switch (opsize) { 1475 case k32: 1476 opcode = kX86PsradRI; 1477 break; 1478 case kSignedHalf: 1479 case kUnsignedHalf: 1480 opcode = kX86PsrawRI; 1481 break; 1482 default: 1483 LOG(FATAL) << "Unsupported vector signed shift right " << opsize; 1484 break; 1485 } 1486 NewLIR2(opcode, rs_dest_src1.GetReg(), imm); 1487} 1488 1489void X86Mir2Lir::GenUnsignedShiftRightVector(BasicBlock *bb, MIR *mir) { 1490 DCHECK_EQ(mir->dalvikInsn.vA & 0xFFFF, 128U); 1491 OpSize opsize = static_cast<OpSize>(mir->dalvikInsn.vA >> 16); 1492 RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vB); 1493 int imm = mir->dalvikInsn.vC; 1494 int opcode = 0; 1495 switch (opsize) { 1496 case k32: 1497 opcode = kX86PsrldRI; 1498 break; 1499 case k64: 1500 opcode = kX86PsrlqRI; 1501 break; 1502 case kSignedHalf: 1503 case kUnsignedHalf: 1504 opcode = kX86PsrlwRI; 1505 break; 1506 default: 1507 LOG(FATAL) << "Unsupported vector unsigned shift right " << opsize; 1508 break; 1509 } 1510 NewLIR2(opcode, rs_dest_src1.GetReg(), imm); 1511} 1512 1513void X86Mir2Lir::GenAndVector(BasicBlock *bb, MIR *mir) { 1514 // We only support 128 bit registers. 1515 DCHECK_EQ(mir->dalvikInsn.vA & 0xFFFF, 128U); 1516 RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vB); 1517 RegStorage rs_src2 = RegStorage::Solo128(mir->dalvikInsn.vC); 1518 NewLIR2(kX86PandRR, rs_dest_src1.GetReg(), rs_src2.GetReg()); 1519} 1520 1521void X86Mir2Lir::GenOrVector(BasicBlock *bb, MIR *mir) { 1522 // We only support 128 bit registers. 1523 DCHECK_EQ(mir->dalvikInsn.vA & 0xFFFF, 128U); 1524 RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vB); 1525 RegStorage rs_src2 = RegStorage::Solo128(mir->dalvikInsn.vC); 1526 NewLIR2(kX86PorRR, rs_dest_src1.GetReg(), rs_src2.GetReg()); 1527} 1528 1529void X86Mir2Lir::GenXorVector(BasicBlock *bb, MIR *mir) { 1530 // We only support 128 bit registers. 1531 DCHECK_EQ(mir->dalvikInsn.vA & 0xFFFF, 128U); 1532 RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vB); 1533 RegStorage rs_src2 = RegStorage::Solo128(mir->dalvikInsn.vC); 1534 NewLIR2(kX86PxorRR, rs_dest_src1.GetReg(), rs_src2.GetReg()); 1535} 1536 1537void X86Mir2Lir::GenAddReduceVector(BasicBlock *bb, MIR *mir) { 1538 DCHECK_EQ(mir->dalvikInsn.vA & 0xFFFF, 128U); 1539 OpSize opsize = static_cast<OpSize>(mir->dalvikInsn.vA >> 16); 1540 RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vB); 1541 int imm = mir->dalvikInsn.vC; 1542 int opcode = 0; 1543 switch (opsize) { 1544 case k32: 1545 opcode = kX86PhadddRR; 1546 break; 1547 case kSignedHalf: 1548 case kUnsignedHalf: 1549 opcode = kX86PhaddwRR; 1550 break; 1551 default: 1552 LOG(FATAL) << "Unsupported vector add reduce " << opsize; 1553 break; 1554 } 1555 NewLIR2(opcode, rs_dest_src1.GetReg(), imm); 1556} 1557 1558void X86Mir2Lir::GenReduceVector(BasicBlock *bb, MIR *mir) { 1559 DCHECK_EQ(mir->dalvikInsn.vA & 0xFFFF, 128U); 1560 OpSize opsize = static_cast<OpSize>(mir->dalvikInsn.vA >> 16); 1561 RegStorage rs_src = RegStorage::Solo128(mir->dalvikInsn.vB); 1562 int index = mir->dalvikInsn.arg[0]; 1563 int opcode = 0; 1564 switch (opsize) { 1565 case k32: 1566 opcode = kX86PextrdRRI; 1567 break; 1568 case kSignedHalf: 1569 case kUnsignedHalf: 1570 opcode = kX86PextrwRRI; 1571 break; 1572 case kUnsignedByte: 1573 case kSignedByte: 1574 opcode = kX86PextrbRRI; 1575 break; 1576 default: 1577 LOG(FATAL) << "Unsupported vector reduce " << opsize; 1578 break; 1579 } 1580 // We need to extract to a GPR. 1581 RegStorage temp = AllocTemp(); 1582 NewLIR3(opcode, temp.GetReg(), rs_src.GetReg(), index); 1583 1584 // Assume that the destination VR is in the def for the mir. 1585 RegLocation rl_dest = mir_graph_->GetDest(mir); 1586 RegLocation rl_temp = 1587 {kLocPhysReg, 0, 0, 0, 0, 0, 0, 0, 1, temp, INVALID_SREG, INVALID_SREG}; 1588 StoreValue(rl_dest, rl_temp); 1589} 1590 1591void X86Mir2Lir::GenSetVector(BasicBlock *bb, MIR *mir) { 1592 DCHECK_EQ(mir->dalvikInsn.vA & 0xFFFF, 128U); 1593 OpSize opsize = static_cast<OpSize>(mir->dalvikInsn.vA >> 16); 1594 RegStorage rs_dest = RegStorage::Solo128(mir->dalvikInsn.vB); 1595 int op_low = 0, op_high = 0; 1596 switch (opsize) { 1597 case k32: 1598 op_low = kX86PshufdRRI; 1599 break; 1600 case kSignedHalf: 1601 case kUnsignedHalf: 1602 // Handles low quadword. 1603 op_low = kX86PshuflwRRI; 1604 // Handles upper quadword. 1605 op_high = kX86PshufdRRI; 1606 break; 1607 default: 1608 LOG(FATAL) << "Unsupported vector set " << opsize; 1609 break; 1610 } 1611 1612 // Load the value from the VR into a GPR. 1613 RegLocation rl_src = mir_graph_->GetSrc(mir, 0); 1614 rl_src = LoadValue(rl_src, kCoreReg); 1615 1616 // Load the value into the XMM register. 1617 NewLIR2(kX86MovdxrRR, rs_dest.GetReg(), rl_src.reg.GetReg()); 1618 1619 // Now shuffle the value across the destination. 1620 NewLIR3(op_low, rs_dest.GetReg(), rs_dest.GetReg(), 0); 1621 1622 // And then repeat as needed. 1623 if (op_high != 0) { 1624 NewLIR3(op_high, rs_dest.GetReg(), rs_dest.GetReg(), 0); 1625 } 1626} 1627 1628 1629LIR *X86Mir2Lir::ScanVectorLiteral(MIR *mir) { 1630 int *args = reinterpret_cast<int*>(mir->dalvikInsn.arg); 1631 for (LIR *p = const_vectors_; p != nullptr; p = p->next) { 1632 if (args[0] == p->operands[0] && args[1] == p->operands[1] && 1633 args[2] == p->operands[2] && args[3] == p->operands[3]) { 1634 return p; 1635 } 1636 } 1637 return nullptr; 1638} 1639 1640LIR *X86Mir2Lir::AddVectorLiteral(MIR *mir) { 1641 LIR* new_value = static_cast<LIR*>(arena_->Alloc(sizeof(LIR), kArenaAllocData)); 1642 int *args = reinterpret_cast<int*>(mir->dalvikInsn.arg); 1643 new_value->operands[0] = args[0]; 1644 new_value->operands[1] = args[1]; 1645 new_value->operands[2] = args[2]; 1646 new_value->operands[3] = args[3]; 1647 new_value->next = const_vectors_; 1648 if (const_vectors_ == nullptr) { 1649 estimated_native_code_size_ += 12; // Amount needed to align to 16 byte boundary. 1650 } 1651 estimated_native_code_size_ += 16; // Space for one vector. 1652 const_vectors_ = new_value; 1653 return new_value; 1654} 1655 1656} // namespace art 1657