diff options
-rw-r--r-- | compiler/dex/quick/arm/target_arm.cc | 4 | ||||
-rw-r--r-- | compiler/jni/quick/arm/calling_convention_arm.cc | 7 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_arm.cc | 17 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_arm.h | 6 | ||||
-rw-r--r-- | runtime/arch/arm/quick_entrypoints_cc_arm.cc | 7 | ||||
-rw-r--r-- | runtime/entrypoints/quick/quick_trampoline_entrypoints.cc | 10 |
6 files changed, 42 insertions, 9 deletions
diff --git a/compiler/dex/quick/arm/target_arm.cc b/compiler/dex/quick/arm/target_arm.cc index b05939156f..52a516cc5a 100644 --- a/compiler/dex/quick/arm/target_arm.cc +++ b/compiler/dex/quick/arm/target_arm.cc @@ -929,6 +929,10 @@ RegStorage ArmMir2Lir::InToRegStorageArmMapper::GetNextReg(ShortyArg arg) { } } else { if (cur_core_reg_ < coreArgMappingToPhysicalRegSize) { + if (!kArm32QuickCodeUseSoftFloat && arg.IsWide() && cur_core_reg_ == 0) { + // Skip r1, and use r2-r3 for the register pair. + cur_core_reg_++; + } result = coreArgMappingToPhysicalReg[cur_core_reg_++]; if (arg.IsWide() && cur_core_reg_ < coreArgMappingToPhysicalRegSize) { result = RegStorage::MakeRegPair(result, coreArgMappingToPhysicalReg[cur_core_reg_++]); diff --git a/compiler/jni/quick/arm/calling_convention_arm.cc b/compiler/jni/quick/arm/calling_convention_arm.cc index fd207150f7..669c3bb716 100644 --- a/compiler/jni/quick/arm/calling_convention_arm.cc +++ b/compiler/jni/quick/arm/calling_convention_arm.cc @@ -168,6 +168,13 @@ const ManagedRegisterEntrySpills& ArmManagedRuntimeCallingConvention::EntrySpill } else { // FIXME: Pointer this returns as both reference and long. if (IsCurrentParamALong() && !IsCurrentParamAReference()) { // Long. + if (gpr_index < arraysize(kHFCoreArgumentRegisters) - 1) { + // Skip R1, and use R2_R3 if the long is the first parameter. + if (gpr_index == 1) { + gpr_index++; + } + } + // If it spans register and memory, we must use the value in memory. if (gpr_index < arraysize(kHFCoreArgumentRegisters) - 1) { entry_spills_.push_back( diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc index 1cc2dcc9b8..20b8b6a62d 100644 --- a/compiler/optimizing/code_generator_arm.cc +++ b/compiler/optimizing/code_generator_arm.cc @@ -590,9 +590,17 @@ Location InvokeDexCallingConventionVisitor::GetNextLocation(Primitive::Type type gp_index_ += 2; stack_index_ += 2; if (index + 1 < calling_convention.GetNumberOfRegisters()) { - ArmManagedRegister pair = ArmManagedRegister::FromRegisterPair( - calling_convention.GetRegisterPairAt(index)); - return Location::RegisterPairLocation(pair.AsRegisterPairLow(), pair.AsRegisterPairHigh()); + if (calling_convention.GetRegisterAt(index) == R1) { + // Skip R1, and use R2_R3 instead. + gp_index_++; + index++; + } + } + if (index + 1 < calling_convention.GetNumberOfRegisters()) { + DCHECK_EQ(calling_convention.GetRegisterAt(index) + 1, + calling_convention.GetRegisterAt(index + 1)); + return Location::RegisterPairLocation(calling_convention.GetRegisterAt(index), + calling_convention.GetRegisterAt(index + 1)); } else { return Location::DoubleStackSlot(calling_convention.GetStackOffsetOf(stack_index)); } @@ -617,6 +625,9 @@ Location InvokeDexCallingConventionVisitor::GetNextLocation(Primitive::Type type if (double_index_ + 1 < calling_convention.GetNumberOfFpuRegisters()) { uint32_t index = double_index_; double_index_ += 2; + DCHECK_EQ(calling_convention.GetFpuRegisterAt(index) + 1, + calling_convention.GetFpuRegisterAt(index + 1)); + DCHECK_EQ(calling_convention.GetFpuRegisterAt(index) & 1, 0); return Location::FpuRegisterPairLocation( calling_convention.GetFpuRegisterAt(index), calling_convention.GetFpuRegisterAt(index + 1)); diff --git a/compiler/optimizing/code_generator_arm.h b/compiler/optimizing/code_generator_arm.h index c1b4eda3a4..8b29b159ab 100644 --- a/compiler/optimizing/code_generator_arm.h +++ b/compiler/optimizing/code_generator_arm.h @@ -33,7 +33,6 @@ class SlowPathCodeARM; static constexpr size_t kArmWordSize = kArmPointerSize; static constexpr Register kParameterCoreRegisters[] = { R1, R2, R3 }; -static constexpr RegisterPair kParameterCorePairRegisters[] = { R1_R2, R2_R3 }; static constexpr size_t kParameterCoreRegistersLength = arraysize(kParameterCoreRegisters); static constexpr SRegister kParameterFpuRegisters[] = { S0, S1, S2, S3, S4, S5, S6, S7, S8, S9, S10, S11, S12, S13, S14, S15 }; @@ -47,11 +46,6 @@ class InvokeDexCallingConvention : public CallingConvention<Register, SRegister> kParameterFpuRegisters, kParameterFpuRegistersLength) {} - RegisterPair GetRegisterPairAt(size_t argument_index) { - DCHECK_LT(argument_index + 1, GetNumberOfRegisters()); - return kParameterCorePairRegisters[argument_index]; - } - private: DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConvention); }; diff --git a/runtime/arch/arm/quick_entrypoints_cc_arm.cc b/runtime/arch/arm/quick_entrypoints_cc_arm.cc index e21e6c1a2e..a3acd7e10a 100644 --- a/runtime/arch/arm/quick_entrypoints_cc_arm.cc +++ b/runtime/arch/arm/quick_entrypoints_cc_arm.cc @@ -75,7 +75,14 @@ static void quick_invoke_reg_setup(mirror::ArtMethod* method, uint32_t* args, ui } break; case 'J': + if (gpr_index == 1 && !kArm32QuickCodeUseSoftFloat) { + // Don't use r1-r2 as a register pair, move to r2-r3 instead. + gpr_index++; + } if (gpr_index < arraysize(core_reg_args)) { + // Note that we don't need to do this if two registers are not available + // when !kArm32QuickCodeUseSoftFloat. We do it anyway to leave this + // code simple. core_reg_args[gpr_index++] = args[arg_index]; } ++arg_index; diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc index 4bec70acd6..ac640b4454 100644 --- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc +++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc @@ -59,6 +59,7 @@ class QuickArgumentVisitor { // | S0 | // | | 4x2 bytes padding // | Method* | <- sp + static constexpr bool kAlignPairRegister = !kArm32QuickCodeUseSoftFloat; static constexpr bool kQuickSoftFloatAbi = kArm32QuickCodeUseSoftFloat; static constexpr bool kQuickDoubleRegAlignedFloatBackFilled = !kArm32QuickCodeUseSoftFloat; static constexpr size_t kNumQuickGprArgs = 3; @@ -93,6 +94,7 @@ class QuickArgumentVisitor { // | D0 | // | | padding // | Method* | <- sp + static constexpr bool kAlignPairRegister = false; static constexpr bool kQuickSoftFloatAbi = false; // This is a hard float ABI. static constexpr bool kQuickDoubleRegAlignedFloatBackFilled = false; static constexpr size_t kNumQuickGprArgs = 7; // 7 arguments passed in GPRs. @@ -121,6 +123,7 @@ class QuickArgumentVisitor { // | A2 | arg2 // | A1 | arg1 // | A0/Method* | <- sp + static constexpr bool kAlignPairRegister = false; static constexpr bool kQuickSoftFloatAbi = true; // This is a soft float ABI. static constexpr bool kQuickDoubleRegAlignedFloatBackFilled = false; static constexpr size_t kNumQuickGprArgs = 3; // 3 arguments passed in GPRs. @@ -146,6 +149,7 @@ class QuickArgumentVisitor { // | EDX | arg2 // | ECX | arg1 // | EAX/Method* | <- sp + static constexpr bool kAlignPairRegister = false; static constexpr bool kQuickSoftFloatAbi = true; // This is a soft float ABI. static constexpr bool kQuickDoubleRegAlignedFloatBackFilled = false; static constexpr size_t kNumQuickGprArgs = 3; // 3 arguments passed in GPRs. @@ -184,6 +188,7 @@ class QuickArgumentVisitor { // | XMM0 | float arg 1 // | Padding | // | RDI/Method* | <- sp + static constexpr bool kAlignPairRegister = false; static constexpr bool kQuickSoftFloatAbi = false; // This is a hard float ABI. static constexpr bool kQuickDoubleRegAlignedFloatBackFilled = false; static constexpr size_t kNumQuickGprArgs = 5; // 5 arguments passed in GPRs. @@ -370,6 +375,11 @@ class QuickArgumentVisitor { case Primitive::kPrimDouble: case Primitive::kPrimLong: if (kQuickSoftFloatAbi || (cur_type_ == Primitive::kPrimLong)) { + if (cur_type_ == Primitive::kPrimLong && kAlignPairRegister && gpr_index_ == 0) { + // Currently, this is only for ARM, where the first available parameter register + // is R1. So we skip it, and use R2 instead. + gpr_index_++; + } is_split_long_or_double_ = (GetBytesPerGprSpillLocation(kRuntimeISA) == 4) && ((gpr_index_ + 1) == kNumQuickGprArgs); Visit(); |