Initial ARM JNI compiler support.

Change-Id: I85183eec9a2645e6cb074b4b18bc6af800a77e06
diff --git a/src/calling_convention_arm.cc b/src/calling_convention_arm.cc
index 7535389..f93dc9b 100644
--- a/src/calling_convention_arm.cc
+++ b/src/calling_convention_arm.cc
@@ -17,9 +17,9 @@
 ManagedRegister CallingConvention::ReturnRegister() {
   const Method *method = GetMethod();
   if (GetMethod()->IsReturnAFloat()) {
-    return ManagedRegister::FromSRegister(S0);
+    return ManagedRegister::FromCoreRegister(R0);
   } else if (GetMethod()->IsReturnADouble()) {
-    return ManagedRegister::FromDRegister(D0);
+    return ManagedRegister::FromRegisterPair(R0_R1);
   } else if (method->IsReturnALong()) {
     return ManagedRegister::FromRegisterPair(R0_R1);
   } else if (method->IsReturnVoid()) {
@@ -44,8 +44,18 @@
 };
 ManagedRegister ManagedRuntimeCallingConvention::CurrentParamRegister() {
   CHECK_LT(itr_position_, 3u);
-  return
-    ManagedRegister::FromCoreRegister(kManagedArgumentRegisters[itr_position_]);
+  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";
+    }
+    return ManagedRegister::FromRegisterPair(R2_R3);
+  } else {
+    return
+      ManagedRegister::FromCoreRegister(kManagedArgumentRegisters[itr_position_]);
+  }
 }
 
 FrameOffset ManagedRuntimeCallingConvention::CurrentParamStackOffset() {
@@ -56,25 +66,41 @@
 
 // JNI calling convention
 
+// Will reg be crushed by an outgoing argument?
+bool JniCallingConvention::IsOutArgRegister(ManagedRegister) {
+  // R0 holds the method register and will be crushed by the JNIEnv*
+  return true;
+}
+
 bool JniCallingConvention::IsCurrentParamInRegister() {
-  return itr_position_ < 4;
+  return (itr_position_ + itr_longs_and_doubles_) < 4;
 }
 
 bool JniCallingConvention::IsCurrentParamOnStack() {
-  return itr_position_ >= 4;
+  return (itr_position_ + itr_longs_and_doubles_) >= 4;
 }
 
 static const Register kJniArgumentRegisters[] = {
   R0, R1, R2, R3
 };
 ManagedRegister JniCallingConvention::CurrentParamRegister() {
-  CHECK_LT(itr_position_, 4u);
-  return
-    ManagedRegister::FromCoreRegister(kJniArgumentRegisters[itr_position_]);
+  CHECK_LT(itr_position_ + itr_longs_and_doubles_, 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";
+    }
+    return ManagedRegister::FromRegisterPair(R2_R3);
+  } else {
+    return
+      ManagedRegister::FromCoreRegister(kJniArgumentRegisters[itr_position_]);
+  }
 }
 
 FrameOffset JniCallingConvention::CurrentParamStackOffset() {
-  CHECK_GE(itr_position_, 4u);
+  CHECK_GE(itr_position_ + itr_longs_and_doubles_, 4u);
   return FrameOffset(displacement_.Int32Value() - OutArgSize()
                + ((itr_position_ + itr_longs_and_doubles_ - 4) * kPointerSize));
 }