diff options
Diffstat (limited to 'compiler/dex/quick/x86/target_x86.cc')
-rw-r--r-- | compiler/dex/quick/x86/target_x86.cc | 519 |
1 files changed, 137 insertions, 382 deletions
diff --git a/compiler/dex/quick/x86/target_x86.cc b/compiler/dex/quick/x86/target_x86.cc index 3e3fa72150..05bef52077 100644 --- a/compiler/dex/quick/x86/target_x86.cc +++ b/compiler/dex/quick/x86/target_x86.cc @@ -26,27 +26,53 @@ namespace art { -// FIXME: restore "static" when usage uncovered -/*static*/ int core_regs[] = { - rAX, rCX, rDX, rBX, rX86_SP, rBP, rSI, rDI +static const RegStorage core_regs_arr[] = { + rs_rAX, rs_rCX, rs_rDX, rs_rBX, rs_rX86_SP, rs_rBP, rs_rSI, rs_rDI #ifdef TARGET_REX_SUPPORT - r8, r9, r10, r11, r12, r13, r14, 15 + rs_r8, rs_r9, rs_r10, rs_r11, rs_r12, rs_r13, rs_r14, rs_r15 #endif }; -/*static*/ int ReservedRegs[] = {rX86_SP}; -/*static*/ int core_temps[] = {rAX, rCX, rDX, rBX}; -/*static*/ int FpRegs[] = { - fr0, fr1, fr2, fr3, fr4, fr5, fr6, fr7, +static const RegStorage sp_regs_arr[] = { + rs_fr0, rs_fr1, rs_fr2, rs_fr3, rs_fr4, rs_fr5, rs_fr6, rs_fr7, #ifdef TARGET_REX_SUPPORT - fr8, fr9, fr10, fr11, fr12, fr13, fr14, fr15 + rs_fr8, rs_fr9, rs_fr10, rs_fr11, rs_fr12, rs_fr13, rs_fr14, rs_fr15 #endif }; -/*static*/ int fp_temps[] = { - fr0, fr1, fr2, fr3, fr4, fr5, fr6, fr7, +static const RegStorage dp_regs_arr[] = { + rs_dr0, rs_dr1, rs_dr2, rs_dr3, rs_dr4, rs_dr5, rs_dr6, rs_dr7, #ifdef TARGET_REX_SUPPORT - fr8, fr9, fr10, fr11, fr12, fr13, fr14, fr15 + rs_dr8, rs_dr9, rs_dr10, rs_dr11, rs_dr12, rs_dr13, rs_dr14, rs_dr15 #endif }; +static const RegStorage reserved_regs_arr[] = {rs_rX86_SP}; +static const RegStorage core_temps_arr[] = {rs_rAX, rs_rCX, rs_rDX, rs_rBX}; +static const RegStorage sp_temps_arr[] = { + rs_fr0, rs_fr1, rs_fr2, rs_fr3, rs_fr4, rs_fr5, rs_fr6, rs_fr7, +#ifdef TARGET_REX_SUPPORT + rs_fr8, rs_fr9, rs_fr10, rs_fr11, rs_fr12, rs_fr13, rs_fr14, rs_fr15 +#endif +}; +static const RegStorage dp_temps_arr[] = { + rs_dr0, rs_dr1, rs_dr2, rs_dr3, rs_dr4, rs_dr5, rs_dr6, rs_dr7, +#ifdef TARGET_REX_SUPPORT + rs_dr8, rs_dr9, rs_dr10, rs_dr11, rs_dr12, rs_dr13, rs_dr14, rs_dr15 +#endif +}; + +static const std::vector<RegStorage> core_regs(core_regs_arr, + core_regs_arr + sizeof(core_regs_arr) / sizeof(core_regs_arr[0])); +static const std::vector<RegStorage> sp_regs(sp_regs_arr, + sp_regs_arr + sizeof(sp_regs_arr) / sizeof(sp_regs_arr[0])); +static const std::vector<RegStorage> dp_regs(dp_regs_arr, + dp_regs_arr + sizeof(dp_regs_arr) / sizeof(dp_regs_arr[0])); +static const std::vector<RegStorage> reserved_regs(reserved_regs_arr, + reserved_regs_arr + sizeof(reserved_regs_arr) / sizeof(reserved_regs_arr[0])); +static const std::vector<RegStorage> core_temps(core_temps_arr, + core_temps_arr + sizeof(core_temps_arr) / sizeof(core_temps_arr[0])); +static const std::vector<RegStorage> sp_temps(sp_temps_arr, + sp_temps_arr + sizeof(sp_temps_arr) / sizeof(sp_temps_arr[0])); +static const std::vector<RegStorage> dp_temps(dp_temps_arr, + dp_temps_arr + sizeof(dp_temps_arr) / sizeof(dp_temps_arr[0])); RegLocation X86Mir2Lir::LocCReturn() { return x86_loc_c_return; @@ -66,29 +92,29 @@ RegLocation X86Mir2Lir::LocCReturnDouble() { // Return a target-dependent special register. RegStorage X86Mir2Lir::TargetReg(SpecialTargetRegister reg) { - int res_reg = RegStorage::kInvalidRegVal; + RegStorage res_reg = RegStorage::InvalidReg(); switch (reg) { - case kSelf: res_reg = rX86_SELF; break; - case kSuspend: res_reg = rX86_SUSPEND; break; - case kLr: res_reg = rX86_LR; break; - case kPc: res_reg = rX86_PC; break; - case kSp: res_reg = rX86_SP; break; - case kArg0: res_reg = rX86_ARG0; break; - case kArg1: res_reg = rX86_ARG1; break; - case kArg2: res_reg = rX86_ARG2; break; - case kArg3: res_reg = rX86_ARG3; break; - case kFArg0: res_reg = rX86_FARG0; break; - case kFArg1: res_reg = rX86_FARG1; break; - case kFArg2: res_reg = rX86_FARG2; break; - case kFArg3: res_reg = rX86_FARG3; break; - case kRet0: res_reg = rX86_RET0; break; - case kRet1: res_reg = rX86_RET1; break; - case kInvokeTgt: res_reg = rX86_INVOKE_TGT; break; - case kHiddenArg: res_reg = rAX; break; - case kHiddenFpArg: res_reg = fr0; break; - case kCount: res_reg = rX86_COUNT; break; + case kSelf: res_reg = RegStorage::InvalidReg(); break; + case kSuspend: res_reg = RegStorage::InvalidReg(); break; + case kLr: res_reg = RegStorage::InvalidReg(); break; + case kPc: res_reg = RegStorage::InvalidReg(); break; + case kSp: res_reg = rs_rX86_SP; break; + case kArg0: res_reg = rs_rX86_ARG0; break; + case kArg1: res_reg = rs_rX86_ARG1; break; + case kArg2: res_reg = rs_rX86_ARG2; break; + case kArg3: res_reg = rs_rX86_ARG3; break; + case kFArg0: res_reg = rs_rX86_FARG0; break; + case kFArg1: res_reg = rs_rX86_FARG1; break; + case kFArg2: res_reg = rs_rX86_FARG2; break; + case kFArg3: res_reg = rs_rX86_FARG3; break; + case kRet0: res_reg = rs_rX86_RET0; break; + case kRet1: res_reg = rs_rX86_RET1; break; + case kInvokeTgt: res_reg = rs_rX86_INVOKE_TGT; break; + case kHiddenArg: res_reg = rs_rAX; break; + case kHiddenFpArg: res_reg = rs_fr0; break; + case kCount: res_reg = rs_rX86_COUNT; break; } - return RegStorage::Solo32(res_reg); + return res_reg; } RegStorage X86Mir2Lir::GetArgMappingToPhysicalReg(int arg_num) { @@ -106,34 +132,19 @@ RegStorage X86Mir2Lir::GetArgMappingToPhysicalReg(int arg_num) { } } -// Create a double from a pair of singles. -int X86Mir2Lir::S2d(int low_reg, int high_reg) { - return X86_S2D(low_reg, high_reg); -} - -// Return mask to strip off fp reg flags and bias. -uint32_t X86Mir2Lir::FpRegMask() { - return X86_FP_REG_MASK; -} - -// True if both regs single, both core or both double. -bool X86Mir2Lir::SameRegType(int reg1, int reg2) { - return (X86_REGTYPE(reg1) == X86_REGTYPE(reg2)); -} - /* * Decode the register id. */ -uint64_t X86Mir2Lir::GetRegMaskCommon(int reg) { +uint64_t X86Mir2Lir::GetRegMaskCommon(RegStorage reg) { uint64_t seed; int shift; int reg_id; - reg_id = reg & 0xf; + reg_id = reg.GetRegNum(); /* Double registers in x86 are just a single FP register */ seed = 1; /* FP register starts at bit position 16 */ - shift = X86_FPREG(reg) ? kX86FPReg0 : 0; + shift = reg.IsFloat() ? kX86FPReg0 : 0; /* Expand the double register id into single offset */ shift += reg_id; return (seed << shift); @@ -162,34 +173,34 @@ void X86Mir2Lir::SetupTargetResourceMasks(LIR* lir, uint64_t flags) { } if (flags & REG_DEFA) { - SetupRegMask(&lir->u.m.def_mask, rAX); + SetupRegMask(&lir->u.m.def_mask, rs_rAX.GetReg()); } if (flags & REG_DEFD) { - SetupRegMask(&lir->u.m.def_mask, rDX); + SetupRegMask(&lir->u.m.def_mask, rs_rDX.GetReg()); } if (flags & REG_USEA) { - SetupRegMask(&lir->u.m.use_mask, rAX); + SetupRegMask(&lir->u.m.use_mask, rs_rAX.GetReg()); } if (flags & REG_USEC) { - SetupRegMask(&lir->u.m.use_mask, rCX); + SetupRegMask(&lir->u.m.use_mask, rs_rCX.GetReg()); } if (flags & REG_USED) { - SetupRegMask(&lir->u.m.use_mask, rDX); + SetupRegMask(&lir->u.m.use_mask, rs_rDX.GetReg()); } if (flags & REG_USEB) { - SetupRegMask(&lir->u.m.use_mask, rBX); + SetupRegMask(&lir->u.m.use_mask, rs_rBX.GetReg()); } // Fixup hard to describe instruction: Uses rAX, rCX, rDI; sets rDI. if (lir->opcode == kX86RepneScasw) { - SetupRegMask(&lir->u.m.use_mask, rAX); - SetupRegMask(&lir->u.m.use_mask, rCX); - SetupRegMask(&lir->u.m.use_mask, rDI); - SetupRegMask(&lir->u.m.def_mask, rDI); + SetupRegMask(&lir->u.m.use_mask, rs_rAX.GetReg()); + SetupRegMask(&lir->u.m.use_mask, rs_rCX.GetReg()); + SetupRegMask(&lir->u.m.use_mask, rs_rDI.GetReg()); + SetupRegMask(&lir->u.m.def_mask, rs_rDI.GetReg()); } if (flags & USE_FP_STACK) { @@ -261,12 +272,13 @@ std::string X86Mir2Lir::BuildInsnString(const char *fmt, LIR *lir, unsigned char break; } case 'r': - if (X86_FPREG(operand) || X86_DOUBLEREG(operand)) { - int fp_reg = operand & X86_FP_REG_MASK; + if (RegStorage::IsFloat(operand)) { + int fp_reg = RegStorage::RegNum(operand); buf += StringPrintf("xmm%d", fp_reg); } else { - DCHECK_LT(static_cast<size_t>(operand), sizeof(x86RegName)); - buf += x86RegName[operand]; + int reg_num = RegStorage::RegNum(operand); + DCHECK_LT(static_cast<size_t>(reg_num), sizeof(x86RegName)); + buf += x86RegName[reg_num]; } break; case 't': @@ -329,7 +341,7 @@ void X86Mir2Lir::DumpResourceMask(LIR *x86LIR, uint64_t mask, const char *prefix void X86Mir2Lir::AdjustSpillMask() { // Adjustment for LR spilling, x86 has no LR so nothing to do here - core_spill_mask_ |= (1 << rRET); + core_spill_mask_ |= (1 << rs_rRET.GetRegNum()); num_core_spills_++; } @@ -339,97 +351,56 @@ void X86Mir2Lir::AdjustSpillMask() { * include any holes in the mask. Associate holes with * Dalvik register INVALID_VREG (0xFFFFU). */ -void X86Mir2Lir::MarkPreservedSingle(int v_reg, int reg) { - UNIMPLEMENTED(WARNING) << "MarkPreservedSingle"; -#if 0 - LOG(FATAL) << "No support yet for promoted FP regs"; -#endif -} - -void X86Mir2Lir::FlushRegWide(RegStorage reg) { - RegisterInfo* info1 = GetRegInfo(reg.GetLowReg()); - RegisterInfo* info2 = GetRegInfo(reg.GetHighReg()); - DCHECK(info1 && info2 && info1->pair && info2->pair && - (info1->partner == info2->reg) && - (info2->partner == info1->reg)); - if ((info1->live && info1->dirty) || (info2->live && info2->dirty)) { - if (!(info1->is_temp && info2->is_temp)) { - /* Should not happen. If it does, there's a problem in eval_loc */ - LOG(FATAL) << "Long half-temp, half-promoted"; - } - - info1->dirty = false; - info2->dirty = false; - if (mir_graph_->SRegToVReg(info2->s_reg) < mir_graph_->SRegToVReg(info1->s_reg)) - info1 = info2; - int v_reg = mir_graph_->SRegToVReg(info1->s_reg); - StoreBaseDispWide(rs_rX86_SP, VRegOffset(v_reg), - RegStorage(RegStorage::k64BitPair, info1->reg, info1->partner)); - } +void X86Mir2Lir::MarkPreservedSingle(int v_reg, RegStorage reg) { + UNIMPLEMENTED(FATAL) << "MarkPreservedSingle"; } -void X86Mir2Lir::FlushReg(RegStorage reg) { - // FIXME: need to handle 32 bits in 64-bit register as well as wide values held in single reg. - DCHECK(!reg.IsPair()); - RegisterInfo* info = GetRegInfo(reg.GetReg()); - if (info->live && info->dirty) { - info->dirty = false; - int v_reg = mir_graph_->SRegToVReg(info->s_reg); - StoreBaseDisp(rs_rX86_SP, VRegOffset(v_reg), reg, k32); - } -} - -/* Give access to the target-dependent FP register encoding to common code */ -bool X86Mir2Lir::IsFpReg(int reg) { - return X86_FPREG(reg); -} - -bool X86Mir2Lir::IsFpReg(RegStorage reg) { - return IsFpReg(reg.IsPair() ? reg.GetLowReg() : reg.GetReg()); +void X86Mir2Lir::MarkPreservedDouble(int v_reg, RegStorage reg) { + UNIMPLEMENTED(FATAL) << "MarkPreservedDouble"; } /* Clobber all regs that might be used by an external C call */ void X86Mir2Lir::ClobberCallerSave() { - Clobber(rAX); - Clobber(rCX); - Clobber(rDX); - Clobber(rBX); + Clobber(rs_rAX); + Clobber(rs_rCX); + Clobber(rs_rDX); + Clobber(rs_rBX); } RegLocation X86Mir2Lir::GetReturnWideAlt() { RegLocation res = LocCReturnWide(); - CHECK(res.reg.GetLowReg() == rAX); - CHECK(res.reg.GetHighReg() == rDX); - Clobber(rAX); - Clobber(rDX); - MarkInUse(rAX); - MarkInUse(rDX); - MarkPair(res.reg.GetLowReg(), res.reg.GetHighReg()); + DCHECK(res.reg.GetLowReg() == rs_rAX.GetReg()); + DCHECK(res.reg.GetHighReg() == rs_rDX.GetReg()); + Clobber(rs_rAX); + Clobber(rs_rDX); + MarkInUse(rs_rAX); + MarkInUse(rs_rDX); + MarkWide(res.reg); return res; } RegLocation X86Mir2Lir::GetReturnAlt() { RegLocation res = LocCReturn(); - res.reg.SetReg(rDX); - Clobber(rDX); - MarkInUse(rDX); + res.reg.SetReg(rs_rDX.GetReg()); + Clobber(rs_rDX); + MarkInUse(rs_rDX); return res; } /* To be used when explicitly managing register use */ void X86Mir2Lir::LockCallTemps() { - LockTemp(rX86_ARG0); - LockTemp(rX86_ARG1); - LockTemp(rX86_ARG2); - LockTemp(rX86_ARG3); + LockTemp(rs_rX86_ARG0); + LockTemp(rs_rX86_ARG1); + LockTemp(rs_rX86_ARG2); + LockTemp(rs_rX86_ARG3); } /* To be used when explicitly managing register use */ void X86Mir2Lir::FreeCallTemps() { - FreeTemp(rX86_ARG0); - FreeTemp(rX86_ARG1); - FreeTemp(rX86_ARG2); - FreeTemp(rX86_ARG3); + FreeTemp(rs_rX86_ARG0); + FreeTemp(rs_rX86_ARG1); + FreeTemp(rs_rX86_ARG2); + FreeTemp(rs_rX86_ARG3); } bool X86Mir2Lir::ProvidesFullMemoryBarrier(X86OpCode opcode) { @@ -495,40 +466,35 @@ RegStorage X86Mir2Lir::AllocTypedTempWide(bool fp_hint, int reg_class) { RegStorage X86Mir2Lir::AllocTypedTemp(bool fp_hint, int reg_class) { if (((reg_class == kAnyReg) && fp_hint) || (reg_class == kFPReg)) { - return AllocTempFloat(); + return AllocTempSingle(); } return AllocTemp(); } void X86Mir2Lir::CompilerInitializeRegAlloc() { - int num_regs = sizeof(core_regs)/sizeof(*core_regs); - int num_reserved = sizeof(ReservedRegs)/sizeof(*ReservedRegs); - int num_temps = sizeof(core_temps)/sizeof(*core_temps); - int num_fp_regs = sizeof(FpRegs)/sizeof(*FpRegs); - int num_fp_temps = sizeof(fp_temps)/sizeof(*fp_temps); - reg_pool_ = static_cast<RegisterPool*>(arena_->Alloc(sizeof(*reg_pool_), - kArenaAllocRegAlloc)); - reg_pool_->num_core_regs = num_regs; - reg_pool_->core_regs = - static_cast<RegisterInfo*>(arena_->Alloc(num_regs * sizeof(*reg_pool_->core_regs), - kArenaAllocRegAlloc)); - reg_pool_->num_fp_regs = num_fp_regs; - reg_pool_->FPRegs = - static_cast<RegisterInfo *>(arena_->Alloc(num_fp_regs * sizeof(*reg_pool_->FPRegs), - kArenaAllocRegAlloc)); - CompilerInitPool(reg_pool_->core_regs, core_regs, reg_pool_->num_core_regs); - CompilerInitPool(reg_pool_->FPRegs, FpRegs, reg_pool_->num_fp_regs); - // Keep special registers from being allocated - for (int i = 0; i < num_reserved; i++) { - MarkInUse(ReservedRegs[i]); - } - // Mark temp regs - all others not in use can be used for promotion - for (int i = 0; i < num_temps; i++) { - MarkTemp(core_temps[i]); - } - for (int i = 0; i < num_fp_temps; i++) { - MarkTemp(fp_temps[i]); + reg_pool_ = new (arena_) RegisterPool(this, arena_, core_regs, sp_regs, dp_regs, reserved_regs, + core_temps, sp_temps, dp_temps); + + // Target-specific adjustments. + + // Alias single precision xmm to double xmms. + // TODO: as needed, add larger vector sizes - alias all to the largest. + GrowableArray<RegisterInfo*>::Iterator it(®_pool_->sp_regs_); + for (RegisterInfo* info = it.Next(); info != nullptr; info = it.Next()) { + int sp_reg_num = info->GetReg().GetRegNum(); + RegStorage dp_reg = RegStorage::Solo64(RegStorage::kFloatingPoint | sp_reg_num); + RegisterInfo* dp_reg_info = GetRegInfo(dp_reg); + // 64-bit xmm vector register's master storage should refer to itself. + DCHECK_EQ(dp_reg_info, dp_reg_info->Master()); + // Redirect 32-bit vector's master storage to 64-bit vector. + info->SetMaster(dp_reg_info); } + + // Don't start allocating temps at r0/s0/d0 or you may clobber return regs in early-exit methods. + // TODO: adjust for x86/hard float calling convention. + reg_pool_->next_core_reg_ = 2; + reg_pool_->next_sp_reg_ = 2; + reg_pool_->next_dp_reg_ = 1; } void X86Mir2Lir::FreeRegLocTemps(RegLocation rl_keep, RegLocation rl_free) { @@ -541,8 +507,7 @@ void X86Mir2Lir::FreeRegLocTemps(RegLocation rl_keep, RegLocation rl_free) { if ((free_low != keep_low) && (free_low != keep_high) && (free_high != keep_low) && (free_high != keep_high)) { // No overlap, free both - FreeTemp(free_low); - FreeTemp(free_high); + FreeTemp(rl_free.reg); } } @@ -551,7 +516,7 @@ void X86Mir2Lir::SpillCoreRegs() { return; } // Spill mask not including fake return address register - uint32_t mask = core_spill_mask_ & ~(1 << rRET); + uint32_t mask = core_spill_mask_ & ~(1 << rs_rRET.GetRegNum()); int offset = frame_size_ - (4 * num_core_spills_); for (int reg = 0; mask; mask >>= 1, reg++) { if (mask & 0x1) { @@ -566,7 +531,7 @@ void X86Mir2Lir::UnSpillCoreRegs() { return; } // Spill mask not including fake return address register - uint32_t mask = core_spill_mask_ & ~(1 << rRET); + uint32_t mask = core_spill_mask_ & ~(1 << rs_rRET.GetRegNum()); int offset = frame_size_ - (4 * num_core_spills_); for (int reg = 0; mask; mask >>= 1, reg++) { if (mask & 0x1) { @@ -629,215 +594,6 @@ const char* X86Mir2Lir::GetTargetInstFmt(int opcode) { return X86Mir2Lir::EncodingMap[opcode].fmt; } -/* - * Return an updated location record with current in-register status. - * If the value lives in live temps, reflect that fact. No code - * is generated. If the live value is part of an older pair, - * clobber both low and high. - */ -// TODO: Reunify with common code after 'pair mess' has been fixed -RegLocation X86Mir2Lir::UpdateLocWide(RegLocation loc) { - DCHECK(loc.wide); - DCHECK(CheckCorePoolSanity()); - if (loc.location != kLocPhysReg) { - DCHECK((loc.location == kLocDalvikFrame) || - (loc.location == kLocCompilerTemp)); - // Are the dalvik regs already live in physical registers? - RegisterInfo* info_lo = AllocLive(loc.s_reg_low, kAnyReg); - - // Handle FP registers specially on x86. - if (info_lo && IsFpReg(info_lo->reg)) { - bool match = true; - - // We can't match a FP register with a pair of Core registers. - match = match && (info_lo->pair == 0); - - if (match) { - // We can reuse;update the register usage info. - loc.location = kLocPhysReg; - loc.vec_len = kVectorLength8; - // TODO: use k64BitVector - loc.reg = RegStorage(RegStorage::k64BitPair, info_lo->reg, info_lo->reg); - DCHECK(IsFpReg(loc.reg.GetLowReg())); - return loc; - } - // We can't easily reuse; clobber and free any overlaps. - if (info_lo) { - Clobber(info_lo->reg); - FreeTemp(info_lo->reg); - if (info_lo->pair) - Clobber(info_lo->partner); - } - } else { - RegisterInfo* info_hi = AllocLive(GetSRegHi(loc.s_reg_low), kAnyReg); - bool match = true; - match = match && (info_lo != NULL); - match = match && (info_hi != NULL); - // Are they both core or both FP? - match = match && (IsFpReg(info_lo->reg) == IsFpReg(info_hi->reg)); - // If a pair of floating point singles, are they properly aligned? - if (match && IsFpReg(info_lo->reg)) { - match &= ((info_lo->reg & 0x1) == 0); - match &= ((info_hi->reg - info_lo->reg) == 1); - } - // If previously used as a pair, it is the same pair? - if (match && (info_lo->pair || info_hi->pair)) { - match = (info_lo->pair == info_hi->pair); - match &= ((info_lo->reg == info_hi->partner) && - (info_hi->reg == info_lo->partner)); - } - if (match) { - // Can reuse - update the register usage info - loc.reg = RegStorage(RegStorage::k64BitPair, info_lo->reg, info_hi->reg); - loc.location = kLocPhysReg; - MarkPair(loc.reg.GetLowReg(), loc.reg.GetHighReg()); - DCHECK(!IsFpReg(loc.reg.GetLowReg()) || ((loc.reg.GetLowReg() & 0x1) == 0)); - return loc; - } - // Can't easily reuse - clobber and free any overlaps - if (info_lo) { - Clobber(info_lo->reg); - FreeTemp(info_lo->reg); - if (info_lo->pair) - Clobber(info_lo->partner); - } - if (info_hi) { - Clobber(info_hi->reg); - FreeTemp(info_hi->reg); - if (info_hi->pair) - Clobber(info_hi->partner); - } - } - } - return loc; -} - -// TODO: Reunify with common code after 'pair mess' has been fixed -RegLocation X86Mir2Lir::EvalLocWide(RegLocation loc, int reg_class, bool update) { - DCHECK(loc.wide); - - loc = UpdateLocWide(loc); - - /* If it is already in a register, we can assume proper form. Is it the right reg class? */ - if (loc.location == kLocPhysReg) { - DCHECK_EQ(IsFpReg(loc.reg.GetLowReg()), loc.IsVectorScalar()); - if (!RegClassMatches(reg_class, loc.reg)) { - /* It is the wrong register class. Reallocate and copy. */ - if (!IsFpReg(loc.reg.GetLowReg())) { - // We want this in a FP reg, and it is in core registers. - DCHECK(reg_class != kCoreReg); - // Allocate this into any FP reg, and mark it with the right size. - int32_t low_reg = AllocTypedTemp(true, reg_class).GetReg(); - OpVectorRegCopyWide(low_reg, loc.reg.GetLowReg(), loc.reg.GetHighReg()); - CopyRegInfo(low_reg, loc.reg.GetLowReg()); - Clobber(loc.reg); - loc.reg.SetReg(low_reg); - loc.reg.SetHighReg(low_reg); // Play nice with existing code. - loc.vec_len = kVectorLength8; - } else { - // The value is in a FP register, and we want it in a pair of core registers. - DCHECK_EQ(reg_class, kCoreReg); - DCHECK_EQ(loc.reg.GetLowReg(), loc.reg.GetHighReg()); - RegStorage new_regs = AllocTypedTempWide(false, kCoreReg); // Force to core registers. - OpRegCopyWide(new_regs, loc.reg); - CopyRegInfo(new_regs.GetLowReg(), loc.reg.GetLowReg()); - CopyRegInfo(new_regs.GetHighReg(), loc.reg.GetHighReg()); - Clobber(loc.reg); - loc.reg = new_regs; - MarkPair(loc.reg.GetLowReg(), loc.reg.GetHighReg()); - DCHECK(!IsFpReg(loc.reg.GetLowReg()) || ((loc.reg.GetLowReg() & 0x1) == 0)); - } - } - return loc; - } - - DCHECK_NE(loc.s_reg_low, INVALID_SREG); - DCHECK_NE(GetSRegHi(loc.s_reg_low), INVALID_SREG); - - loc.reg = AllocTypedTempWide(loc.fp, reg_class); - - // FIXME: take advantage of RegStorage notation. - if (loc.reg.GetLowReg() == loc.reg.GetHighReg()) { - DCHECK(IsFpReg(loc.reg.GetLowReg())); - loc.vec_len = kVectorLength8; - } else { - MarkPair(loc.reg.GetLowReg(), loc.reg.GetHighReg()); - } - if (update) { - loc.location = kLocPhysReg; - MarkLive(loc.reg.GetLow(), loc.s_reg_low); - if (loc.reg.GetLowReg() != loc.reg.GetHighReg()) { - MarkLive(loc.reg.GetHigh(), GetSRegHi(loc.s_reg_low)); - } - } - return loc; -} - -// TODO: Reunify with common code after 'pair mess' has been fixed -RegLocation X86Mir2Lir::EvalLoc(RegLocation loc, int reg_class, bool update) { - if (loc.wide) - return EvalLocWide(loc, reg_class, update); - - loc = UpdateLoc(loc); - - if (loc.location == kLocPhysReg) { - if (!RegClassMatches(reg_class, loc.reg)) { - /* Wrong register class. Realloc, copy and transfer ownership. */ - RegStorage new_reg = AllocTypedTemp(loc.fp, reg_class); - OpRegCopy(new_reg, loc.reg); - CopyRegInfo(new_reg, loc.reg); - Clobber(loc.reg); - loc.reg = new_reg; - if (IsFpReg(loc.reg.GetReg()) && reg_class != kCoreReg) - loc.vec_len = kVectorLength4; - } - return loc; - } - - DCHECK_NE(loc.s_reg_low, INVALID_SREG); - - loc.reg = AllocTypedTemp(loc.fp, reg_class); - if (IsFpReg(loc.reg.GetReg()) && reg_class != kCoreReg) - loc.vec_len = kVectorLength4; - - if (update) { - loc.location = kLocPhysReg; - MarkLive(loc.reg, loc.s_reg_low); - } - return loc; -} - -RegStorage X86Mir2Lir::AllocTempDouble() { - // We really don't need a pair of registers. - // FIXME - update to double - int reg = AllocTempFloat().GetReg(); - return RegStorage(RegStorage::k64BitPair, reg, reg); -} - -// TODO: Reunify with common code after 'pair mess' has been fixed -void X86Mir2Lir::ResetDefLocWide(RegLocation rl) { - DCHECK(rl.wide); - RegisterInfo* p_low = IsTemp(rl.reg.GetLowReg()); - if (IsFpReg(rl.reg.GetLowReg())) { - // We are using only the low register. - if (p_low && !(cu_->disable_opt & (1 << kSuppressLoads))) { - NullifyRange(p_low->def_start, p_low->def_end, p_low->s_reg, rl.s_reg_low); - } - ResetDef(rl.reg.GetLowReg()); - } else { - RegisterInfo* p_high = IsTemp(rl.reg.GetHighReg()); - if (p_low && !(cu_->disable_opt & (1 << kSuppressLoads))) { - DCHECK(p_low->pair); - NullifyRange(p_low->def_start, p_low->def_end, p_low->s_reg, rl.s_reg_low); - } - if (p_high && !(cu_->disable_opt & (1 << kSuppressLoads))) { - DCHECK(p_high->pair); - } - ResetDef(rl.reg.GetLowReg()); - ResetDef(rl.reg.GetHighReg()); - } -} - void X86Mir2Lir::GenConstWide(RegLocation rl_dest, int64_t value) { // Can we do this directly to memory? rl_dest = UpdateLocWide(rl_dest); @@ -872,7 +628,6 @@ void X86Mir2Lir::DumpRegLocation(RegLocation loc) { << (loc.ref ? " r" : " ") << (loc.high_word ? " h" : " ") << (loc.home ? " H" : " ") - << " vec_len: " << loc.vec_len << ", low: " << static_cast<int>(loc.reg.GetLowReg()) << ", high: " << static_cast<int>(loc.reg.GetHighReg()) << ", s_reg: " << loc.s_reg_low @@ -1059,7 +814,7 @@ bool X86Mir2Lir::GenInlinedIndexOf(CallInfo* info, bool zero_based) { // We need to preserve EDI, but have no spare registers, so push it on the stack. // We have to remember that all stack addresses after this are offset by sizeof(EDI). - NewLIR1(kX86Push32R, rDI); + NewLIR1(kX86Push32R, rs_rDI.GetReg()); // Compute the number of words to search in to rCX. Load32Disp(rs_rDX, count_offset, rs_rCX); @@ -1096,7 +851,7 @@ bool X86Mir2Lir::GenInlinedIndexOf(CallInfo* info, bool zero_based) { OpRegReg(kOpSub, rs_rCX, rl_start.reg); if (rl_start.reg == rs_rDI) { // The special case. We will use EDI further, so lets put start index to stack. - NewLIR1(kX86Push32R, rDI); + NewLIR1(kX86Push32R, rs_rDI.GetReg()); is_index_on_stack = true; } } else { @@ -1110,7 +865,7 @@ bool X86Mir2Lir::GenInlinedIndexOf(CallInfo* info, bool zero_based) { length_compare = OpCmpBranch(kCondLe, rs_rCX, rs_rBX, nullptr); OpRegReg(kOpSub, rs_rCX, rs_rBX); // Put the start index to stack. - NewLIR1(kX86Push32R, rBX); + NewLIR1(kX86Push32R, rs_rBX.GetReg()); is_index_on_stack = true; } } @@ -1130,12 +885,12 @@ bool X86Mir2Lir::GenInlinedIndexOf(CallInfo* info, bool zero_based) { if (start_value == 0) { OpRegCopy(rs_rDI, rs_rBX); } else { - NewLIR3(kX86Lea32RM, rDI, rBX, 2 * start_value); + NewLIR3(kX86Lea32RM, rs_rDI.GetReg(), rs_rBX.GetReg(), 2 * start_value); } } else { if (is_index_on_stack == true) { // Load the start index from stack. - NewLIR1(kX86Pop32R, rDX); + NewLIR1(kX86Pop32R, rs_rDX.GetReg()); OpLea(rs_rDI, rs_rBX, rs_rDX, 1, 0); } else { OpLea(rs_rDI, rs_rBX, rl_start.reg, 1, 0); @@ -1153,7 +908,7 @@ bool X86Mir2Lir::GenInlinedIndexOf(CallInfo* info, bool zero_based) { // index = ((curr_ptr - orig_ptr) / 2) - 1. OpRegReg(kOpSub, rs_rDI, rs_rBX); OpRegImm(kOpAsr, rs_rDI, 1); - NewLIR3(kX86Lea32RM, rl_return.reg.GetReg(), rDI, -1); + NewLIR3(kX86Lea32RM, rl_return.reg.GetReg(), rs_rDI.GetReg(), -1); LIR *all_done = NewLIR1(kX86Jmp8, 0); // Failed to match; return -1. @@ -1165,7 +920,7 @@ bool X86Mir2Lir::GenInlinedIndexOf(CallInfo* info, bool zero_based) { // And join up at the end. all_done->target = NewLIR0(kPseudoTargetLabel); // Restore EDI from the stack. - NewLIR1(kX86Pop32R, rDI); + NewLIR1(kX86Pop32R, rs_rDI.GetReg()); // Out of line code returns here. if (slowpath_branch != nullptr) { |