summaryrefslogtreecommitdiffstats
path: root/compiler/dex/quick/mir_to_lir.cc
diff options
context:
space:
mode:
authorDmitry Petrochenko <dmitry.petrochenko@intel.com>2014-05-17 01:02:18 +0700
committerDmitry Petrochenko <dmitry.petrochenko@intel.com>2014-06-07 01:28:05 +0000
commit58994cdb00b323339bd83828eddc53976048006f (patch)
treea1ec67c5b04cf99439619bf972a58b6d46dd2823 /compiler/dex/quick/mir_to_lir.cc
parent9529d6273777ee297a8aa7513e8172775f0496df (diff)
downloadart-58994cdb00b323339bd83828eddc53976048006f.tar.gz
art-58994cdb00b323339bd83828eddc53976048006f.tar.bz2
art-58994cdb00b323339bd83828eddc53976048006f.zip
x86_64: Hard Float ABI support in QCG
This patch shows our efforts on resolving the ART limitations: - passing "float"/"double" arguments via FPR - passing "long" arguments via single GPR, not pair - passing more than 3 agruments via GPR. Work done: - Extended SpecialTargetRegister enum with kARG4, kARG5, fARG4..fARG7. - Created initial LoadArgRegs/GenDalvikX/FlushIns version in X86Mir2Lir. - Unlimited number of long/double/float arguments support - Refactored (v2) Change-Id: I5deadd320b4341d5b2f50ba6fa4a98031abc3902 Signed-off-by: Serguei Katkov <serguei.i.katkov@intel.com> Signed-off-by: Dmitry Petrochenko <dmitry.petrochenko@intel.com> Signed-off-by: Chao-ying Fu <chao-ying.fu@intel.com> Signed-off-by: Mark Mendell <mark.p.mendell@intel.com>
Diffstat (limited to 'compiler/dex/quick/mir_to_lir.cc')
-rw-r--r--compiler/dex/quick/mir_to_lir.cc64
1 files changed, 56 insertions, 8 deletions
diff --git a/compiler/dex/quick/mir_to_lir.cc b/compiler/dex/quick/mir_to_lir.cc
index 1f12b6fe69..a85be5e90c 100644
--- a/compiler/dex/quick/mir_to_lir.cc
+++ b/compiler/dex/quick/mir_to_lir.cc
@@ -68,20 +68,51 @@ void Mir2Lir::LockArg(int in_position, bool wide) {
// TODO: needs revisit for 64-bit.
RegStorage Mir2Lir::LoadArg(int in_position, RegisterClass reg_class, bool wide) {
- RegStorage reg_arg_low = GetArgMappingToPhysicalReg(in_position);
- RegStorage reg_arg_high = wide ? GetArgMappingToPhysicalReg(in_position + 1) :
- RegStorage::InvalidReg();
-
int offset = StackVisitor::GetOutVROffset(in_position, cu_->instruction_set);
- if (cu_->instruction_set == kX86 || cu_->instruction_set == kX86_64) {
+
+ if (cu_->instruction_set == kX86) {
/*
* When doing a call for x86, it moves the stack pointer in order to push return.
* Thus, we add another 4 bytes to figure out the out of caller (in of callee).
- * TODO: This needs revisited for 64-bit.
*/
offset += sizeof(uint32_t);
}
+ if (cu_->instruction_set == kX86_64) {
+ /*
+ * When doing a call for x86, it moves the stack pointer in order to push return.
+ * Thus, we add another 8 bytes to figure out the out of caller (in of callee).
+ */
+ offset += sizeof(uint64_t);
+ }
+
+ if (cu_->instruction_set == kX86_64) {
+ RegStorage reg_arg = GetArgMappingToPhysicalReg(in_position);
+ if (!reg_arg.Valid()) {
+ RegStorage new_reg = wide ? AllocTypedTempWide(false, reg_class) : AllocTypedTemp(false, reg_class);
+ LoadBaseDisp(TargetReg(kSp), offset, new_reg, wide ? k64 : k32);
+ return new_reg;
+ } else {
+ // Check if we need to copy the arg to a different reg_class.
+ if (!RegClassMatches(reg_class, reg_arg)) {
+ if (wide) {
+ RegStorage new_reg = AllocTypedTempWide(false, reg_class);
+ OpRegCopyWide(new_reg, reg_arg);
+ reg_arg = new_reg;
+ } else {
+ RegStorage new_reg = AllocTypedTemp(false, reg_class);
+ OpRegCopy(new_reg, reg_arg);
+ reg_arg = new_reg;
+ }
+ }
+ }
+ return reg_arg;
+ }
+
+ RegStorage reg_arg_low = GetArgMappingToPhysicalReg(in_position);
+ RegStorage reg_arg_high = wide ? GetArgMappingToPhysicalReg(in_position + 1) :
+ RegStorage::InvalidReg();
+
// If the VR is wide and there is no register for high part, we need to load it.
if (wide && !reg_arg_high.Valid()) {
// If the low part is not in a reg, we allocate a pair. Otherwise, we just load to high reg.
@@ -129,15 +160,22 @@ RegStorage Mir2Lir::LoadArg(int in_position, RegisterClass reg_class, bool wide)
void Mir2Lir::LoadArgDirect(int in_position, RegLocation rl_dest) {
int offset = StackVisitor::GetOutVROffset(in_position, cu_->instruction_set);
- if (cu_->instruction_set == kX86 || cu_->instruction_set == kX86_64) {
+ if (cu_->instruction_set == kX86) {
/*
* When doing a call for x86, it moves the stack pointer in order to push return.
* Thus, we add another 4 bytes to figure out the out of caller (in of callee).
- * TODO: This needs revisited for 64-bit.
*/
offset += sizeof(uint32_t);
}
+ if (cu_->instruction_set == kX86_64) {
+ /*
+ * When doing a call for x86, it moves the stack pointer in order to push return.
+ * Thus, we add another 8 bytes to figure out the out of caller (in of callee).
+ */
+ offset += sizeof(uint64_t);
+ }
+
if (!rl_dest.wide) {
RegStorage reg = GetArgMappingToPhysicalReg(in_position);
if (reg.Valid()) {
@@ -146,6 +184,16 @@ void Mir2Lir::LoadArgDirect(int in_position, RegLocation rl_dest) {
Load32Disp(TargetReg(kSp), offset, rl_dest.reg);
}
} else {
+ if (cu_->instruction_set == kX86_64) {
+ RegStorage reg = GetArgMappingToPhysicalReg(in_position);
+ if (reg.Valid()) {
+ OpRegCopy(rl_dest.reg, reg);
+ } else {
+ LoadBaseDisp(TargetReg(kSp), offset, rl_dest.reg, k64);
+ }
+ return;
+ }
+
RegStorage reg_arg_low = GetArgMappingToPhysicalReg(in_position);
RegStorage reg_arg_high = GetArgMappingToPhysicalReg(in_position + 1);