Handle double and long on the Managed side, and follow AAPCS on the Native side.

Change-Id: I43a8fa36cb79fb438f075986a46c66ab8258e725
diff --git a/src/calling_convention_arm.cc b/src/calling_convention_arm.cc
index f93dc9b..a7a080e 100644
--- a/src/calling_convention_arm.cc
+++ b/src/calling_convention_arm.cc
@@ -32,36 +32,44 @@
 // Managed runtime calling convention
 
 bool ManagedRuntimeCallingConvention::IsCurrentParamInRegister() {
-  return itr_position_ < 3;
+  if (itr_slots_ < 3) {
+    return true;
+  }
+  return false;  // everything else on the stack
 }
 
 bool ManagedRuntimeCallingConvention::IsCurrentParamOnStack() {
-  return itr_position_ >= 3;
+  return !IsCurrentParamInRegister();
 }
 
 static const Register kManagedArgumentRegisters[] = {
   R1, R2, R3
 };
 ManagedRegister ManagedRuntimeCallingConvention::CurrentParamRegister() {
-  CHECK_LT(itr_position_, 3u);
+  CHECK_LT(itr_slots_, 3u); // Otherwise, should have gone through stack
   const Method* method = GetMethod();
-  if (method->IsParamALongOrDouble(itr_position_)) {
-    // TODO: handle a long/double split between registers and the stack, also
-    // itr_position_ 0
-    if (itr_position_ != 1u) {
-      LOG(WARNING) << "Unimplemented";
+  if (method->IsParamALongOrDouble(itr_args_)) {
+    if (itr_slots_ == 0) {
+      // return R1 to denote R1_R2
+      return ManagedRegister::FromCoreRegister(kManagedArgumentRegisters
+                                               [itr_slots_]);
+    } else if (itr_slots_ == 1) {
+      return ManagedRegister::FromRegisterPair(R2_R3);
+    } else {
+      // This is a long/double split between registers and the stack
+      return ManagedRegister::FromCoreRegister(
+        kManagedArgumentRegisters[itr_slots_]);
     }
-    return ManagedRegister::FromRegisterPair(R2_R3);
   } else {
     return
-      ManagedRegister::FromCoreRegister(kManagedArgumentRegisters[itr_position_]);
+      ManagedRegister::FromCoreRegister(kManagedArgumentRegisters[itr_slots_]);
   }
 }
 
 FrameOffset ManagedRuntimeCallingConvention::CurrentParamStackOffset() {
-  CHECK_GE(itr_position_, 3u);
+  CHECK_GE(itr_slots_, 3u);
   return FrameOffset(displacement_.Int32Value() +
-                 ((itr_position_ + itr_longs_and_doubles_ - 3) * kPointerSize));
+             ((itr_slots_ - 3) * kPointerSize));
 }
 
 // JNI calling convention
@@ -72,37 +80,50 @@
   return true;
 }
 
+// JniCallingConvention ABI follows AAPCS
+//
+// In processing each parameter, we know that IsCurrentParamInRegister()
+// or IsCurrentParamOnStack() will be called first.
+// Both functions will ensure that we conform to AAPCS.
+//
 bool JniCallingConvention::IsCurrentParamInRegister() {
-  return (itr_position_ + itr_longs_and_doubles_) < 4;
+  // AAPCS processing
+  const Method* method = GetMethod();
+  int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni(method);
+  if ((itr_args_ >= 2) && method->IsParamALongOrDouble(arg_pos)) {
+    // itr_slots_ needs to be an even number, according to AAPCS.
+    if (itr_slots_ & 0x1u) {
+      itr_slots_++;
+    }
+  }
+
+  return itr_slots_ < 4;
 }
 
 bool JniCallingConvention::IsCurrentParamOnStack() {
-  return (itr_position_ + itr_longs_and_doubles_) >= 4;
+  return !IsCurrentParamInRegister();
 }
 
 static const Register kJniArgumentRegisters[] = {
   R0, R1, R2, R3
 };
 ManagedRegister JniCallingConvention::CurrentParamRegister() {
-  CHECK_LT(itr_position_ + itr_longs_and_doubles_, 4u);
+  CHECK_LT(itr_slots_, 4u);
   const Method* method = GetMethod();
-  int arg_pos = itr_position_ - (method->IsStatic() ? 2 : 1);
-  if ((itr_position_ >= 2) && method->IsParamALongOrDouble(arg_pos)) {
-    // TODO: handle a long/double split between registers and the stack
-    if (itr_position_ != 2u) {
-      LOG(WARNING) << "Unimplemented";
-    }
+  int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni(method);
+  if ((itr_args_ >= 2) && method->IsParamALongOrDouble(arg_pos)) {
+    CHECK_EQ(itr_slots_, 2u);
     return ManagedRegister::FromRegisterPair(R2_R3);
   } else {
     return
-      ManagedRegister::FromCoreRegister(kJniArgumentRegisters[itr_position_]);
+      ManagedRegister::FromCoreRegister(kJniArgumentRegisters[itr_slots_]);
   }
 }
 
 FrameOffset JniCallingConvention::CurrentParamStackOffset() {
-  CHECK_GE(itr_position_ + itr_longs_and_doubles_, 4u);
+  CHECK_GE(itr_slots_, 4u);
   return FrameOffset(displacement_.Int32Value() - OutArgSize()
-               + ((itr_position_ + itr_longs_and_doubles_ - 4) * kPointerSize));
+               + ((itr_slots_ - 4) * kPointerSize));
 }
 
 size_t JniCallingConvention::NumberOfOutgoingStackArgs() {