x86_64: TargetReg update for x86
Also includes changes in common code. Elimination of use of TargetReg
with one parameter and direct access to special target registers.
Change-Id: Ied2c1f87d4d1e4345248afe74bca40487a46a371
Signed-off-by: Serguei Katkov <serguei.i.katkov@intel.com>
Signed-off-by: Chao-ying Fu <chao-ying.fu@intel.com>
diff --git a/compiler/dex/quick/x86/int_x86.cc b/compiler/dex/quick/x86/int_x86.cc
index 14a18e5..7a4ea26 100644
--- a/compiler/dex/quick/x86/int_x86.cc
+++ b/compiler/dex/quick/x86/int_x86.cc
@@ -93,7 +93,7 @@
}
LIR* X86Mir2Lir::OpCmpBranch(ConditionCode cond, RegStorage src1, RegStorage src2, LIR* target) {
- NewLIR2(kX86Cmp32RR, src1.GetReg(), src2.GetReg());
+ NewLIR2(src1.Is64Bit() ? kX86Cmp64RR : kX86Cmp32RR, src1.GetReg(), src2.GetReg());
X86ConditionCode cc = X86ConditionEncoding(cond);
LIR* branch = NewLIR2(kX86Jcc8, 0 /* lir operand for Jcc offset */ ,
cc);
@@ -105,9 +105,13 @@
int check_value, LIR* target) {
if ((check_value == 0) && (cond == kCondEq || cond == kCondNe)) {
// TODO: when check_value == 0 and reg is rCX, use the jcxz/nz opcode
- NewLIR2(kX86Test32RR, reg.GetReg(), reg.GetReg());
+ NewLIR2(reg.Is64Bit() ? kX86Test64RR: kX86Test32RR, reg.GetReg(), reg.GetReg());
} else {
- NewLIR2(IS_SIMM8(check_value) ? kX86Cmp32RI8 : kX86Cmp32RI, reg.GetReg(), check_value);
+ if (reg.Is64Bit()) {
+ NewLIR2(IS_SIMM8(check_value) ? kX86Cmp64RI8 : kX86Cmp64RI, reg.GetReg(), check_value);
+ } else {
+ NewLIR2(IS_SIMM8(check_value) ? kX86Cmp32RI8 : kX86Cmp32RI, reg.GetReg(), check_value);
+ }
}
X86ConditionCode cc = X86ConditionEncoding(cond);
LIR* branch = NewLIR2(kX86Jcc8, 0 /* lir operand for Jcc offset */ , cc);
@@ -241,7 +245,7 @@
// FIXME: depending on how you use registers you could get a false != mismatch when dealing
// with different views of the same underlying physical resource (i.e. solo32 vs. solo64).
const bool result_reg_same_as_src =
- (rl_src.location == kLocPhysReg && rl_src.reg.GetReg() == rl_result.reg.GetReg());
+ (rl_src.location == kLocPhysReg && rl_src.reg.GetRegNum() == rl_result.reg.GetRegNum());
const bool true_zero_case = (true_val == 0 && false_val != 0 && !result_reg_same_as_src);
const bool false_zero_case = (false_val == 0 && true_val != 0 && !result_reg_same_as_src);
const bool catch_all_case = !(true_zero_case || false_zero_case);
@@ -846,14 +850,14 @@
ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
const size_t push_offset = (push_si ? 4u : 0u) + (push_di ? 4u : 0u);
if (!obj_in_si && !obj_in_di) {
- LoadWordDisp(TargetReg(kSp), SRegOffset(rl_src_obj.s_reg_low) + push_offset, rs_obj);
+ LoadWordDisp(rs_rX86_SP, SRegOffset(rl_src_obj.s_reg_low) + push_offset, rs_obj);
// Dalvik register annotation in LoadBaseIndexedDisp() used wrong offset. Fix it.
DCHECK(!DECODE_ALIAS_INFO_WIDE(last_lir_insn_->flags.alias_info));
int reg_id = DECODE_ALIAS_INFO_REG(last_lir_insn_->flags.alias_info) - push_offset / 4u;
AnnotateDalvikRegAccess(last_lir_insn_, reg_id, true, false);
}
if (!off_in_si && !off_in_di) {
- LoadWordDisp(TargetReg(kSp), SRegOffset(rl_src_offset.s_reg_low) + push_offset, rs_off);
+ LoadWordDisp(rs_rX86_SP, SRegOffset(rl_src_offset.s_reg_low) + push_offset, rs_off);
// Dalvik register annotation in LoadBaseIndexedDisp() used wrong offset. Fix it.
DCHECK(!DECODE_ALIAS_INFO_WIDE(last_lir_insn_->flags.alias_info));
int reg_id = DECODE_ALIAS_INFO_REG(last_lir_insn_->flags.alias_info) - push_offset / 4u;
@@ -1008,23 +1012,23 @@
RegStorage new_index = index_;
// Move index out of kArg1, either directly to kArg0, or to kArg2.
// TODO: clean-up to check not a number but with type
- if (index_.GetRegNum() == m2l_->TargetReg(kArg1).GetRegNum()) {
- if (array_base_.GetRegNum() == m2l_->TargetReg(kArg0).GetRegNum()) {
- m2l_->OpRegCopy(m2l_->TargetReg(kArg2), index_);
- new_index = m2l_->TargetReg(kArg2);
+ if (index_ == m2l_->TargetReg(kArg1, false)) {
+ if (array_base_ == m2l_->TargetRefReg(kArg0)) {
+ m2l_->OpRegCopy(m2l_->TargetReg(kArg2, false), index_);
+ new_index = m2l_->TargetReg(kArg2, false);
} else {
- m2l_->OpRegCopy(m2l_->TargetReg(kArg0), index_);
- new_index = m2l_->TargetReg(kArg0);
+ m2l_->OpRegCopy(m2l_->TargetReg(kArg0, false), index_);
+ new_index = m2l_->TargetReg(kArg0, false);
}
}
// Load array length to kArg1.
- m2l_->OpRegMem(kOpMov, m2l_->TargetReg(kArg1), array_base_, len_offset_);
+ m2l_->OpRegMem(kOpMov, m2l_->TargetReg(kArg1, false), array_base_, len_offset_);
if (cu_->target64) {
m2l_->CallRuntimeHelperRegReg(QUICK_ENTRYPOINT_OFFSET(8, pThrowArrayBounds),
- new_index, m2l_->TargetReg(kArg1), true);
+ new_index, m2l_->TargetReg(kArg1, false), true);
} else {
m2l_->CallRuntimeHelperRegReg(QUICK_ENTRYPOINT_OFFSET(4, pThrowArrayBounds),
- new_index, m2l_->TargetReg(kArg1), true);
+ new_index, m2l_->TargetReg(kArg1, false), true);
}
}
@@ -1057,14 +1061,14 @@
GenerateTargetLabel(kPseudoThrowTarget);
// Load array length to kArg1.
- m2l_->OpRegMem(kOpMov, m2l_->TargetReg(kArg1), array_base_, len_offset_);
- m2l_->LoadConstant(m2l_->TargetReg(kArg0), index_);
+ m2l_->OpRegMem(kOpMov, m2l_->TargetReg(kArg1, false), array_base_, len_offset_);
+ m2l_->LoadConstant(m2l_->TargetReg(kArg0, false), index_);
if (cu_->target64) {
m2l_->CallRuntimeHelperRegReg(QUICK_ENTRYPOINT_OFFSET(8, pThrowArrayBounds),
- m2l_->TargetReg(kArg0), m2l_->TargetReg(kArg1), true);
+ m2l_->TargetReg(kArg0, false), m2l_->TargetReg(kArg1, false), true);
} else {
m2l_->CallRuntimeHelperRegReg(QUICK_ENTRYPOINT_OFFSET(4, pThrowArrayBounds),
- m2l_->TargetReg(kArg0), m2l_->TargetReg(kArg1), true);
+ m2l_->TargetReg(kArg0, false), m2l_->TargetReg(kArg1, false), true);
}
}
@@ -1406,7 +1410,7 @@
// RHS is in memory.
DCHECK((rl_src.location == kLocDalvikFrame) ||
(rl_src.location == kLocCompilerTemp));
- int r_base = TargetReg(kSp).GetReg();
+ int r_base = rs_rX86_SP.GetReg();
int displacement = SRegOffset(rl_src.s_reg_low);
ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
@@ -1440,7 +1444,7 @@
// Operate directly into memory.
X86OpCode x86op = GetOpcode(op, rl_dest, rl_src, false);
- int r_base = TargetReg(kSp).GetReg();
+ int r_base = rs_rX86_SP.GetReg();
int displacement = SRegOffset(rl_dest.s_reg_low);
ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
@@ -2122,7 +2126,7 @@
if ((rl_dest.location == kLocDalvikFrame) ||
(rl_dest.location == kLocCompilerTemp)) {
- int r_base = TargetReg(kSp).GetReg();
+ int r_base = rs_rX86_SP.GetReg();
int displacement = SRegOffset(rl_dest.s_reg_low);
ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
@@ -2153,7 +2157,7 @@
// Can we just do this into memory?
if ((rl_dest.location == kLocDalvikFrame) ||
(rl_dest.location == kLocCompilerTemp)) {
- int r_base = TargetReg(kSp).GetReg();
+ int r_base = rs_rX86_SP.GetReg();
int displacement = SRegOffset(rl_dest.s_reg_low);
ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
@@ -2271,7 +2275,8 @@
RegStorage result_reg = rl_result.reg;
// For 32-bit, SETcc only works with EAX..EDX.
- if (result_reg == object.reg || !IsByteRegister(result_reg)) {
+ RegStorage object_32reg = object.reg.Is64Bit() ? As32BitReg(object.reg) : object.reg;
+ if (result_reg == object_32reg || !IsByteRegister(result_reg)) {
result_reg = AllocateByteRegister();
}
@@ -2337,8 +2342,10 @@
FlushAllRegs();
// May generate a call - use explicit registers.
LockCallTemps();
- LoadCurrMethodDirect(TargetReg(kArg1)); // kArg1 gets current Method*.
- RegStorage class_reg = TargetReg(kArg2); // kArg2 will hold the Class*.
+ RegStorage method_reg = TargetRefReg(kArg1); // kArg1 gets current Method*.
+ LoadCurrMethodDirect(method_reg);
+ RegStorage class_reg = TargetRefReg(kArg2); // kArg2 will hold the Class*.
+ RegStorage ref_reg = TargetRefReg(kArg0); // kArg2 will hold the ref.
// Reference must end up in kArg0.
if (needs_access_check) {
// Check we have access to type_idx and if not throw IllegalAccessError,
@@ -2350,16 +2357,16 @@
CallRuntimeHelperImm(QUICK_ENTRYPOINT_OFFSET(4, pInitializeTypeAndVerifyAccess),
type_idx, true);
}
- OpRegCopy(class_reg, TargetReg(kRet0));
- LoadValueDirectFixed(rl_src, TargetReg(kArg0));
+ OpRegCopy(class_reg, TargetRefReg(kRet0));
+ LoadValueDirectFixed(rl_src, ref_reg);
} else if (use_declaring_class) {
- LoadValueDirectFixed(rl_src, TargetReg(kArg0));
- LoadRefDisp(TargetReg(kArg1), mirror::ArtMethod::DeclaringClassOffset().Int32Value(),
+ LoadValueDirectFixed(rl_src, ref_reg);
+ LoadRefDisp(method_reg, mirror::ArtMethod::DeclaringClassOffset().Int32Value(),
class_reg, kNotVolatile);
} else {
// Load dex cache entry into class_reg (kArg2).
- LoadValueDirectFixed(rl_src, TargetReg(kArg0));
- LoadRefDisp(TargetReg(kArg1), mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value(),
+ LoadValueDirectFixed(rl_src, ref_reg);
+ LoadRefDisp(method_reg, mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value(),
class_reg, kNotVolatile);
int32_t offset_of_type =
mirror::Array::DataOffset(sizeof(mirror::HeapReference<mirror::Class*>)).Int32Value() +
@@ -2374,8 +2381,8 @@
} else {
CallRuntimeHelperImm(QUICK_ENTRYPOINT_OFFSET(4, pInitializeType), type_idx, true);
}
- OpRegCopy(TargetReg(kArg2), TargetReg(kRet0)); // Align usage with fast path.
- LoadValueDirectFixed(rl_src, TargetReg(kArg0)); /* Reload Ref. */
+ OpRegCopy(class_reg, TargetRefReg(kRet0)); // Align usage with fast path.
+ LoadValueDirectFixed(rl_src, ref_reg); /* Reload Ref. */
// Rejoin code paths
LIR* hop_target = NewLIR0(kPseudoTargetLabel);
hop_branch->target = hop_target;
@@ -2386,33 +2393,34 @@
// On x86-64 kArg0 is not EAX, so we have to copy ref from kArg0 to EAX.
if (cu_->target64) {
- OpRegCopy(rl_result.reg, TargetReg(kArg0));
+ OpRegCopy(rl_result.reg, ref_reg);
}
// For 32-bit, SETcc only works with EAX..EDX.
DCHECK_LT(rl_result.reg.GetRegNum(), 4);
// Is the class NULL?
- LIR* branch1 = OpCmpImmBranch(kCondEq, TargetReg(kArg0), 0, NULL);
+ LIR* branch1 = OpCmpImmBranch(kCondEq, ref_reg, 0, NULL);
+ RegStorage ref_class_reg = TargetRefReg(kArg1); // kArg2 will hold the Class*.
/* Load object->klass_. */
DCHECK_EQ(mirror::Object::ClassOffset().Int32Value(), 0);
- LoadRefDisp(TargetReg(kArg0), mirror::Object::ClassOffset().Int32Value(), TargetReg(kArg1),
+ LoadRefDisp(ref_reg, mirror::Object::ClassOffset().Int32Value(), ref_class_reg,
kNotVolatile);
/* kArg0 is ref, kArg1 is ref->klass_, kArg2 is class. */
LIR* branchover = nullptr;
if (type_known_final) {
// Ensure top 3 bytes of result are 0.
LoadConstant(rl_result.reg, 0);
- OpRegReg(kOpCmp, TargetReg(kArg1), TargetReg(kArg2));
+ OpRegReg(kOpCmp, ref_class_reg, class_reg);
// Set the low byte of the result to 0 or 1 from the compare condition code.
NewLIR2(kX86Set8R, rl_result.reg.GetReg(), kX86CondEq);
} else {
if (!type_known_abstract) {
LoadConstant(rl_result.reg, 1); // Assume result succeeds.
- branchover = OpCmpBranch(kCondEq, TargetReg(kArg1), TargetReg(kArg2), NULL);
+ branchover = OpCmpBranch(kCondEq, ref_class_reg, class_reg, NULL);
}
- OpRegCopy(TargetReg(kArg0), TargetReg(kArg2));
+ OpRegCopy(TargetRefReg(kArg0), class_reg);
if (cu_->target64) {
OpThreadMem(kOpBlx, QUICK_ENTRYPOINT_OFFSET(8, pInstanceofNonTrivial));
} else {
@@ -2552,7 +2560,7 @@
} else {
if (shift_op) {
// X86 doesn't require masking and must use ECX.
- RegStorage t_reg = TargetReg(kCount); // rCX
+ RegStorage t_reg = TargetReg(kCount, false); // rCX
LoadValueDirectFixed(rl_rhs, t_reg);
if (is_two_addr) {
// Can we do this directly into memory?
@@ -2740,7 +2748,7 @@
}
// X86 doesn't require masking and must use ECX.
- RegStorage t_reg = TargetReg(kCount); // rCX
+ RegStorage t_reg = TargetReg(kCount, false); // rCX
LoadValueDirectFixed(rl_shift, t_reg);
if (is_two_addr) {
// Can we do this directly into memory?