diff options
author | Dmitry Petrochenko <dmitry.petrochenko@intel.com> | 2014-05-17 01:02:18 +0700 |
---|---|---|
committer | Dmitry Petrochenko <dmitry.petrochenko@intel.com> | 2014-06-07 01:28:05 +0000 |
commit | 58994cdb00b323339bd83828eddc53976048006f (patch) | |
tree | a1ec67c5b04cf99439619bf972a58b6d46dd2823 /compiler/dex/quick/mir_to_lir.cc | |
parent | 9529d6273777ee297a8aa7513e8172775f0496df (diff) | |
download | art-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.cc | 64 |
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); |