Fix for argument passing bug

The code was using r1 as a temp when it was live.

Change-Id: I79f42203eced2aff49980241c890629ecc3ff09a
diff --git a/build/Android.common.mk b/build/Android.common.mk
index 72d42d1..aa9b719 100644
--- a/build/Android.common.mk
+++ b/build/Android.common.mk
@@ -167,4 +167,5 @@
 	StaticLeafMethods \
 	Statics \
 	SystemMethods \
+	Invoke \
 	XandY
diff --git a/src/compiler/codegen/arm/MethodCodegenDriver.cc b/src/compiler/codegen/arm/MethodCodegenDriver.cc
index 78a9767..96f5423 100644
--- a/src/compiler/codegen/arm/MethodCodegenDriver.cc
+++ b/src/compiler/codegen/arm/MethodCodegenDriver.cc
@@ -716,7 +716,6 @@
     if (dInsn->vA == 0)
         return callState;
 
-    oatLockCallTemps(cUnit);
     callState = nextCallInsn(cUnit, mir, dInsn, callState, rollback);
 
     /*
@@ -729,8 +728,9 @@
         if (rlArg.location == kLocPhysReg) {
             reg = rlArg.lowReg;
         } else {
-            reg = r1;
-            loadValueDirectFixed(cUnit, rlArg, r1);
+            // r3 is the last arg register loaded, so can safely be used here
+            reg = r3;
+            loadValueDirectFixed(cUnit, rlArg, reg);
             callState = nextCallInsn(cUnit, mir, dInsn, callState, rollback);
         }
         storeBaseDisp(cUnit, rSP, (i + 1) * 4, reg, kWord);
@@ -859,9 +859,6 @@
     callState = loadArgRegs(cUnit, mir, dInsn, callState, registerArgs,
                             nextCallInsn, rollback);
 
-    // Finally, deal with the register arguments
-    // We'll be using fixed registers here
-    oatLockCallTemps(cUnit);
     callState = nextCallInsn(cUnit, mir, dInsn, callState, rollback);
     return callState;
 }
@@ -873,9 +870,11 @@
     int callState = 0;
     ArmLIR* nullCk;
     ArmLIR** pNullCk = direct ? &nullCk : NULL;
-
     NextCallInsn nextCallInsn = nextSDCallInsn;
 
+    // Explicit register usage
+    oatLockCallTemps(cUnit);
+
     if (range) {
         callState = genDalvikArgsRange(cUnit, mir, dInsn, callState, pNullCk,
                                        nextCallInsn, NULL, false);
@@ -899,6 +898,9 @@
     DecodedInstruction* dInsn = &mir->dalvikInsn;
     int callState = 0;
     ArmLIR* nullCk;
+
+    // Explicit register usage
+    oatLockCallTemps(cUnit);
     /* Note: must call nextInterfaceCallInsn() prior to 1st argument load */
     callState = nextInterfaceCallInsn(cUnit, mir, dInsn, callState, NULL);
     if (mir->dalvikInsn.opcode == OP_INVOKE_INTERFACE)
@@ -925,6 +927,9 @@
         Get(dInsn->vB);
     NextCallInsn nextCallInsn;
     bool fastPath = true;
+
+    // Explicit register usage
+    oatLockCallTemps(cUnit);
     if (FORCE_SLOW || baseMethod == NULL) {
         fastPath = false;
     } else {
@@ -971,6 +976,8 @@
         Get(dInsn->vB);
     NextCallInsn nextCallInsn;
 
+    // Explicit register usage
+    oatLockCallTemps(cUnit);
     if (FORCE_SLOW || method == NULL) {
         // Slow path
         nextCallInsn = nextVCallInsnSP;
diff --git a/src/compiler_test.cc b/src/compiler_test.cc
index acfd5e5..a1aadc8 100644
--- a/src/compiler_test.cc
+++ b/src/compiler_test.cc
@@ -270,6 +270,26 @@
                         111);
 }
 
+TEST_F(CompilerTest, InvokeTest) {
+  CompileDirectMethod(NULL, "java.lang.Object", "<init>", "()V");
+  const ClassLoader* class_loader = LoadDex("Invoke");
+  CompileDirectMethod(class_loader, "Invoke", "<init>", "()V");
+  CompileVirtualMethod(class_loader, "Invoke", "virI_I", "(I)I");
+  CompileVirtualMethod(class_loader, "Invoke", "virI_II", "(II)I");
+  CompileVirtualMethod(class_loader, "Invoke", "virI_III", "(III)I");
+  CompileVirtualMethod(class_loader, "Invoke", "virI_IIII", "(IIII)I");
+  CompileVirtualMethod(class_loader, "Invoke", "virI_IIIII", "(IIIII)I");
+  CompileVirtualMethod(class_loader, "Invoke", "virI_IIIIII", "(IIIIII)I");
+  CompileDirectMethod(class_loader, "Invoke", "statI_I", "(I)I");
+  CompileDirectMethod(class_loader, "Invoke", "statI_II", "(II)I");
+  CompileDirectMethod(class_loader, "Invoke", "statI_III", "(III)I");
+  CompileDirectMethod(class_loader, "Invoke", "statI_IIII", "(IIII)I");
+  CompileDirectMethod(class_loader, "Invoke", "statI_IIIII", "(IIIII)I");
+  CompileDirectMethod(class_loader, "Invoke", "statI_IIIIII", "(IIIIII)I");
+  AssertStaticIntMethod(class_loader, "Invoke", "test0", "(I)I", 20664,
+                        912);
+}
+
 TEST_F(CompilerTest, SystemMethodsTest) {
   CompileDirectMethod(NULL, "java.lang.Object", "<init>", "()V");
 
diff --git a/test/Invoke/Invoke.java b/test/Invoke/Invoke.java
new file mode 100644
index 0000000..8bb03d3
--- /dev/null
+++ b/test/Invoke/Invoke.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+class Invoke {
+
+    int virI_I(int a) {
+        return a + 123;
+    }
+
+    int virI_II(int a, int b) {
+        return a + b + 321;
+    }
+
+    int virI_III(int a, int b, int c) {
+        return a + b + c + 432;
+    }
+
+    int virI_IIII(int a, int b, int c, int d) {
+        return a + b + c + d + 919;
+    }
+
+    int virI_IIIII(int a, int b, int c, int d, int e) {
+        return a + b + c + d + e + 1010;
+    }
+
+    int virI_IIIIII(int a, int b, int c, int d, int e, int f) {
+        return a + b + c + d + e + f + 2020;
+    }
+
+    static int statI_I(int a) {
+         return a + 123;
+    }
+
+    static int statI_II(int a, int b) {
+        return a + b + 321;
+    }
+
+    static int statI_III(int a, int b, int c) {
+        return a + b + c + 432;
+    }
+
+    static int statI_IIII(int a, int b, int c, int d) {
+        return a + b + c + d + 919;
+    }
+
+    static int statI_IIIII(int a, int b, int c, int d, int e) {
+        return a + b + c + d + e + 1010;
+    }
+
+    static int statI_IIIIII(int a, int b, int c, int d, int e, int f) {
+        return a + b + c + d + e + f + 2020;
+    }
+
+    static int test0(int a) {
+        Invoke foo = new Invoke();
+
+        return foo.virI_I(a) +
+               foo.virI_II(a, 1) +
+               foo.virI_III(a, 1, 2) +
+               foo.virI_IIII(a, 1, 2, 3) +
+               foo.virI_IIIII(a, 1, 2, 3, 4) +
+               foo.virI_IIIIII(a, 1, 2, 3, 4, 5) +
+               statI_I(a) +
+               statI_II(a, 1) +
+               statI_III(a, 1, 2) +
+               statI_IIII(a, 1, 2, 3) +
+               statI_IIIII(a, 1, 2, 3, 4) +
+               statI_IIIIII(a, 1, 2, 3, 4, 5);
+    }
+
+    public static void main(String[] args) {
+        int res = test0(912);
+        if (res == 20664) {
+            System.out.println("test0 PASSED");
+        } else {
+            System.out.println("test0 FAILED: " + res);
+        }
+    }
+}