Various assembly fixes.

Change-Id: I42655af8dc3d7201d53c3393cdc585d9faa8cb82
diff --git a/src/assembler_arm.cc b/src/assembler_arm.cc
index cd0c5f5..e1976d7 100644
--- a/src/assembler_arm.cc
+++ b/src/assembler_arm.cc
@@ -1046,6 +1046,14 @@
   Emit(encoding);
 }
 
+void ArmAssembler::bx(Register rm, Condition cond) {
+  CHECK_NE(rm, kNoRegister);
+  CHECK_NE(cond, kNoCondition);
+  int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
+                     B24 | B21 | (0xfff << 8) | B4 |
+                     (static_cast<int32_t>(rm) << kRmShift);
+  Emit(encoding);
+}
 
 void ArmAssembler::MarkExceptionHandler(Label* label) {
   EmitType01(AL, 1, TST, 1, PC, R0, ShifterOperand(0));
diff --git a/src/assembler_arm.h b/src/assembler_arm.h
index 3f979c6..e1d43e4 100644
--- a/src/assembler_arm.h
+++ b/src/assembler_arm.h
@@ -346,6 +346,7 @@
   void b(Label* label, Condition cond = AL);
   void bl(Label* label, Condition cond = AL);
   void blx(Register rm, Condition cond = AL);
+  void bx(Register rm, Condition cond = AL);
 
   // Macros.
   // Add signed constant value to rd. May clobber IP.
diff --git a/src/jni_internal_arm.cc b/src/jni_internal_arm.cc
index 93380b1..f1ed092 100644
--- a/src/jni_internal_arm.cc
+++ b/src/jni_internal_arm.cc
@@ -46,7 +46,7 @@
   // Move the managed thread pointer into R9.
   __ mov(R9, ShifterOperand(R2));
 
-  // Reset R4 to suspend check intercal
+  // Reset R4 to suspend check interval
   __ LoadImmediate(R4, SUSPEND_CHECK_INTERVAL);
 
   // Move frame down for arguments less 3 pushed values above
@@ -106,15 +106,10 @@
   __ blx(IP);
 
   // If the method returns a value, store it to the result pointer.
-  char ch = method->GetShorty()->CharAt(0);
-  if (ch != 'V') {
+  if (!method->IsReturnVoid()) {
     // Load the result JValue pointer of the stub caller's out args.
     __ LoadFromOffset(kLoadWord, IP, SP, frame_size);
-    if (ch == 'D' || ch == 'J') {
-      __ StoreToOffset(kStoreWordPair, R0, IP, 0);
-    } else {
-      __ StoreToOffset(kStoreWord, R0, IP, 0);
-    }
+    __ StoreToOffset(method->IsReturnALongOrDouble() ? kStoreWordPair : kStoreWord, R0, IP, 0);
   }
 
   // Remove the frame less the spilled R4, R9 and LR
diff --git a/src/object.h b/src/object.h
index 80a4ce9..e5036e6 100644
--- a/src/object.h
+++ b/src/object.h
@@ -755,6 +755,10 @@
 
   bool IsReturnALong() const;
 
+  bool IsReturnALongOrDouble() const {
+    return IsReturnALong() || IsReturnADouble();
+  }
+
   bool IsReturnVoid() const;
 
   // "Args" may refer to any of the 3 levels of "Args."
diff --git a/src/runtime_support_asm.S b/src/runtime_support_asm.S
index 2017c40..38eaf82 100644
--- a/src/runtime_support_asm.S
+++ b/src/runtime_support_asm.S
@@ -182,7 +182,7 @@
     bl     artHandleFillArrayDataFromCode  @ (Array* array, const uint16_t* table, Thread*, SP)
     RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
     cmp    r0, #0                          @ success?
-    moveq  pc, lr                          @ return on success
+    bxeq   lr                              @ return on success
     DELIVER_PENDING_EXCEPTION
 
     .global art_lock_object_from_code
@@ -209,7 +209,7 @@
     bl     artUnlockObjectFromCode  @ (Object* obj, Thread*, SP)
     RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
     cmp    r0, #0                   @ success?
-    moveq  pc, lr                   @ return on success
+    bxeq   lr                       @ return on success
     DELIVER_PENDING_EXCEPTION
 
     .global art_check_cast_from_code
@@ -224,7 +224,7 @@
     bl     artCheckCastFromCode         @ (Class* a, Class* b, Thread*, SP)
     RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
     cmp    r0, #0                       @ success?
-    moveq  pc, lr                       @ return on success
+    bxeq   lr                           @ return on success
     DELIVER_PENDING_EXCEPTION
 
     .global art_can_put_array_element_from_code
@@ -235,14 +235,14 @@
      */
 art_can_put_array_element_from_code:
     cmp    r0, #0                         @ return if element == NULL
-    moveq  pc, lr
+    bxeq   lr
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME    @ save callee saves in case exception allocation triggers GC
     mov    r2, r9                         @ pass Thread::Current
     mov    r3, sp                         @ pass SP
     bl     artCanPutArrayElementFromCode  @ (Object* element, Class* array_class, Thread*, SP)
     RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
     cmp    r0, #0                         @ success?
-    moveq  pc, lr                         @ return on success
+    bxeq   lr                             @ return on success
     DELIVER_PENDING_EXCEPTION
 
     .global art_initialize_static_storage_from_code
@@ -260,7 +260,7 @@
     bl     artInitializeStaticStorageFromCode
     RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
     cmp    r0, #0                              @ success if result is non-null
-    movne  pc, lr                              @ return on success
+    bxne   lr                                  @ return on success
     DELIVER_PENDING_EXCEPTION
 
     .global art_find_instance_field_from_code
@@ -275,7 +275,7 @@
     bl     artFindInstanceFieldFromCode  @ (uint32_t field_idx, const Method* referrer, Thread*, SP)
     RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
     cmp    r0, #0                        @ success if result is non-null
-    movne  pc, lr                        @ return on success
+    bxne   lr                            @ return on success
     DELIVER_PENDING_EXCEPTION
 
     .global art_get32_static_from_code
@@ -291,7 +291,7 @@
     ldr    r12, [r9, #THREAD_EXCEPTION_OFFSET]  @ load Thread::Current()->exception_
     RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
     cmp    r12, #0                       @ success if no exception is pending
-    moveq  pc, lr                        @ return on success
+    bxeq   lr                            @ return on success
     DELIVER_PENDING_EXCEPTION
 
     .global art_get64_static_from_code
@@ -307,7 +307,7 @@
     ldr    r12, [r9, #THREAD_EXCEPTION_OFFSET]  @ load Thread::Current()->exception_
     RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
     cmp    r12, #0                       @ success if no exception is pending
-    moveq  pc, lr                        @ return on success
+    bxeq    lr                           @ return on success
     DELIVER_PENDING_EXCEPTION
 
     .global art_get_obj_static_from_code
@@ -323,7 +323,7 @@
     ldr    r12, [r9, #THREAD_EXCEPTION_OFFSET]  @ load Thread::Current()->exception_
     RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
     cmp    r12, #0                       @ success if no exception is pending
-    moveq  pc, lr                        @ return on success
+    bxeq   lr                            @ return on success
     DELIVER_PENDING_EXCEPTION
 
     .global art_set32_static_from_code
@@ -338,7 +338,7 @@
     bl     artSet32StaticFromCode        @ (field_idx, referrer, new_val, Thread*, SP)
     RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
     cmp    r0, #0                        @ success if result is 0
-    moveq  pc, lr                        @ return on success
+    bxeq   lr                            @ return on success
     DELIVER_PENDING_EXCEPTION
 
     .global art_set64_static_from_code
@@ -355,7 +355,7 @@
     add    sp, #16                       @ release out args
     RESTORE_REF_ONLY_CALLEE_SAVE_FRAME   @ TODO: we can clearly save an add here
     cmp    r0, #0                        @ success if result is 0
-    moveq  pc, lr                        @ return on success
+    bxeq   lr                            @ return on success
     DELIVER_PENDING_EXCEPTION
 
     .global art_set_obj_static_from_code
@@ -370,7 +370,7 @@
     bl     artSetObjStaticFromCode       @ (field_idx, referrer, new_val, Thread*, SP)
     RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
     cmp    r0, #0                        @ success if result is 0
-    moveq  pc, lr                        @ return on success
+    bxeq   lr                            @ return on success
     DELIVER_PENDING_EXCEPTION
 
     .global art_alloc_object_from_code
@@ -385,7 +385,7 @@
     bl     artAllocObjectFromCode     @ (uint32_t type_idx, Method* method, Thread*, SP)
     RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
     cmp    r0, #0                     @ success if result is non-null
-    movne  pc, lr                     @ return on success
+    bxne   lr                         @ return on success
     DELIVER_PENDING_EXCEPTION
 
     .global art_alloc_array_from_code
@@ -401,7 +401,7 @@
     bl     artAllocArrayFromCode
     RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
     cmp    r0, #0                     @ success if result is non-null
-    movne  pc, lr                     @ return on success
+    bxne   lr                         @ return on success
     DELIVER_PENDING_EXCEPTION
 
     .global art_check_and_alloc_array_from_code
@@ -417,7 +417,7 @@
     bl     artCheckAndAllocArrayFromCode
     RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
     cmp    r0, #0                     @ success if result is non-null
-    movne  pc, lr                     @ return on success
+    bxne   lr                         @ return on success
     DELIVER_PENDING_EXCEPTION
 
     .global art_test_suspend
diff --git a/src/stub_arm.cc b/src/stub_arm.cc
index bb36415..b959377 100644
--- a/src/stub_arm.cc
+++ b/src/stub_arm.cc
@@ -32,7 +32,7 @@
   // Restore registers which may have been modified by GC and R0 which will now hold the method*
   __ DecreaseFrameSize(12);
   __ PopList(save);
-  __ mov(PC, ShifterOperand(R12));  // Leaf call to method's code
+  __ bx(R12);  // Leaf call to method's code
 
   __ bkpt(0);
 
@@ -89,11 +89,11 @@
   __ LoadFromOffset(kLoadWord, R12, TR, OFFSETOF_MEMBER(Thread, pFindNativeMethod));
   __ blx(R12);
   __ mov(R12, ShifterOperand(R0));  // Save result of FindNativeMethod in R12
-  __ AddConstant(SP, 12);  // Restore registers (including outgoing arguments)
+  __ AddConstant(SP, 12);           // Restore registers (including outgoing arguments)
   __ PopList(save);
   __ cmp(R12, ShifterOperand(0));
-  __ mov(PC, ShifterOperand(R12), NE);  // If R12 != 0 tail call into native code
-  __ mov(PC, ShifterOperand(LR));  // Return to caller to handle exception
+  __ bx(R12, NE);                   // If R12 != 0 tail call into native code
+  __ bx(LR);                        // Return to caller to handle exception
 
   assembler->EmitSlowPaths();