Skip r1 on arm if first parameter is a long.

Change-Id: I16d927ee0a0b55031ade4c92c0095fd74e18ed5b
diff --git a/compiler/dex/quick/arm/target_arm.cc b/compiler/dex/quick/arm/target_arm.cc
index b059391..52a516c 100644
--- a/compiler/dex/quick/arm/target_arm.cc
+++ b/compiler/dex/quick/arm/target_arm.cc
@@ -929,6 +929,10 @@
     }
   } 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 fd20715..669c3bb 100644
--- a/compiler/jni/quick/arm/calling_convention_arm.cc
+++ b/compiler/jni/quick/arm/calling_convention_arm.cc
@@ -168,6 +168,13 @@
         } 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 1cc2dcc..20b8b6a 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -590,9 +590,17 @@
       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 @@
       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 c1b4eda..8b29b15 100644
--- a/compiler/optimizing/code_generator_arm.h
+++ b/compiler/optimizing/code_generator_arm.h
@@ -33,7 +33,6 @@
 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 @@
                           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 e21e6c1..a3acd7e 100644
--- a/runtime/arch/arm/quick_entrypoints_cc_arm.cc
+++ b/runtime/arch/arm/quick_entrypoints_cc_arm.cc
@@ -75,7 +75,14 @@
         }
         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 4bec70a..ac640b4 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -59,6 +59,7 @@
   // | 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 @@
   // | 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 @@
   // | 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 @@
   // | 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 @@
   // | 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 @@
         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();