diff options
Diffstat (limited to 'compiler/jni/quick/x86/calling_convention_x86.cc')
-rw-r--r-- | compiler/jni/quick/x86/calling_convention_x86.cc | 59 |
1 files changed, 49 insertions, 10 deletions
diff --git a/compiler/jni/quick/x86/calling_convention_x86.cc b/compiler/jni/quick/x86/calling_convention_x86.cc index a5686e1ac7..fc72e88c00 100644 --- a/compiler/jni/quick/x86/calling_convention_x86.cc +++ b/compiler/jni/quick/x86/calling_convention_x86.cc @@ -77,12 +77,34 @@ bool X86ManagedRuntimeCallingConvention::IsCurrentParamInRegister() { } bool X86ManagedRuntimeCallingConvention::IsCurrentParamOnStack() { - return true; // Everything is passed by stack + // We assume all parameters are on stack, args coming via registers are spilled as entry_spills. + return true; } ManagedRegister X86ManagedRuntimeCallingConvention::CurrentParamRegister() { - LOG(FATAL) << "Should not reach here"; - return ManagedRegister::NoRegister(); + ManagedRegister res = ManagedRegister::NoRegister(); + if (!IsCurrentParamAFloatOrDouble()) { + switch (gpr_arg_count_) { + case 0: res = X86ManagedRegister::FromCpuRegister(ECX); break; + case 1: res = X86ManagedRegister::FromCpuRegister(EDX); break; + case 2: res = X86ManagedRegister::FromCpuRegister(EBX); break; + } + } else if (itr_float_and_doubles_ < 4) { + // First four float parameters are passed via XMM0..XMM3 + res = X86ManagedRegister::FromXmmRegister( + static_cast<XmmRegister>(XMM0 + itr_float_and_doubles_)); + } + return res; +} + +ManagedRegister X86ManagedRuntimeCallingConvention::CurrentParamHighLongRegister() { + ManagedRegister res = ManagedRegister::NoRegister(); + DCHECK(IsCurrentParamALong()); + switch (gpr_arg_count_) { + case 0: res = X86ManagedRegister::FromCpuRegister(EDX); break; + case 1: res = X86ManagedRegister::FromCpuRegister(EBX); break; + } + return res; } FrameOffset X86ManagedRuntimeCallingConvention::CurrentParamStackOffset() { @@ -95,15 +117,32 @@ const ManagedRegisterEntrySpills& X86ManagedRuntimeCallingConvention::EntrySpill // We spill the argument registers on X86 to free them up for scratch use, we then assume // all arguments are on the stack. if (entry_spills_.size() == 0) { - size_t num_spills = NumArgs() + NumLongOrDoubleArgs(); - if (num_spills > 0) { - entry_spills_.push_back(X86ManagedRegister::FromCpuRegister(ECX)); - if (num_spills > 1) { - entry_spills_.push_back(X86ManagedRegister::FromCpuRegister(EDX)); - if (num_spills > 2) { - entry_spills_.push_back(X86ManagedRegister::FromCpuRegister(EBX)); + ResetIterator(FrameOffset(0)); + while (HasNext()) { + ManagedRegister in_reg = CurrentParamRegister(); + if (!in_reg.IsNoRegister()) { + int32_t size = IsParamADouble(itr_args_) ? 8 : 4; + int32_t spill_offset = CurrentParamStackOffset().Uint32Value(); + ManagedRegisterSpill spill(in_reg, size, spill_offset); + entry_spills_.push_back(spill); + if (IsCurrentParamALong() && !IsCurrentParamAReference()) { // Long. + // special case, as we may need a second register here. + in_reg = CurrentParamHighLongRegister(); + if (!in_reg.IsNoRegister()) { + // We have to spill the second half of the long. + ManagedRegisterSpill spill2(in_reg, size, spill_offset + 4); + entry_spills_.push_back(spill2); + // Long was allocated in 2 registers. + gpr_arg_count_++; + } + } + + // Keep track of the number of GPRs allocated. + if (!IsCurrentParamAFloatOrDouble()) { + gpr_arg_count_++; } } + Next(); } } return entry_spills_; |