Make inlined CAS32 loop until store is successful if values match.

The native implementation of compareAndSwap uses android_atomic_cas,
which will repeat the strex until it succeeds. The compiled version
was changed to do the same.

Bug: 10530407
Change-Id: I7efb3f92d0d0610fcc5a885e2c97f1d701b5a4ea
(cherry picked from commit 2de2aa1a96dfa5bebc004f29b5dbfafd37039cee)
diff --git a/compiler/dex/quick/arm/int_arm.cc b/compiler/dex/quick/arm/int_arm.cc
index f2ff58e..6fbdd2f 100644
--- a/compiler/dex/quick/arm/int_arm.cc
+++ b/compiler/dex/quick/arm/int_arm.cc
@@ -535,25 +535,26 @@
   ClobberSReg(rl_offset.s_reg_low);
   FreeTemp(rl_offset.low_reg);
 
-  int r_old_value = AllocTemp();
-  NewLIR3(kThumb2Ldrex, r_old_value, r_ptr, 0);  // r_old_value := [r_ptr]
+  RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
+  LoadConstant(rl_result.low_reg, 0);  // r_result := 0
 
-  RegLocation rl_expected = LoadValue(rl_src_expected, kCoreReg);
-
-  // if (r_old_value == rExpected) {
+  // while ([r_ptr] == rExpected && r_result == 0) {
   //   [r_ptr] <- r_new_value && r_result := success ? 0 : 1
   //   r_result ^= 1
-  // } else {
-  //   r_result := 0
   // }
+  int r_old_value = AllocTemp();
+  LIR* target = NewLIR0(kPseudoTargetLabel);
+  NewLIR3(kThumb2Ldrex, r_old_value, r_ptr, 0);
+
+  RegLocation rl_expected = LoadValue(rl_src_expected, kCoreReg);
   OpRegReg(kOpCmp, r_old_value, rl_expected.low_reg);
   FreeTemp(r_old_value);  // Now unneeded.
-  RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
-  OpIT(kCondEq, "TE");
-  NewLIR4(kThumb2Strex, rl_result.low_reg, rl_new_value.low_reg, r_ptr, 0);
+  OpIT(kCondEq, "TT");
+  NewLIR4(kThumb2Strex /* eq */, rl_result.low_reg, rl_new_value.low_reg, r_ptr, 0);
   FreeTemp(r_ptr);  // Now unneeded.
-  OpRegImm(kOpXor, rl_result.low_reg, 1);
-  OpRegReg(kOpXor, rl_result.low_reg, rl_result.low_reg);
+  OpRegImm(kOpXor /* eq */, rl_result.low_reg, 1);
+  OpRegImm(kOpCmp /* eq */, rl_result.low_reg, 0);
+  OpCondBranch(kCondEq, target);
 
   StoreValue(rl_dest, rl_result);