Fix intrinsic Math.abs(double) for ARM.

Bug: 16930909
Change-Id: I1210cb3aa82a73b9e4d4df1ceddeff78ac1df42b
diff --git a/compiler/dex/quick/arm/fp_arm.cc b/compiler/dex/quick/arm/fp_arm.cc
index 2ad11da..3eb7c83 100644
--- a/compiler/dex/quick/arm/fp_arm.cc
+++ b/compiler/dex/quick/arm/fp_arm.cc
@@ -383,8 +383,17 @@
   RegLocation rl_result = EvalLoc(rl_dest, reg_class, true);
   if (reg_class == kFPReg) {
     NewLIR2(kThumb2Vabsd, rl_result.reg.GetReg(), rl_src.reg.GetReg());
+  } else if (rl_result.reg.GetLow().GetReg() != rl_src.reg.GetHigh().GetReg()) {
+    // No inconvenient overlap.
+    OpRegCopy(rl_result.reg.GetLow(), rl_src.reg.GetLow());
+    OpRegRegImm(kOpAnd, rl_result.reg.GetHigh(), rl_src.reg.GetHigh(), 0x7fffffff);
   } else {
-    OpRegImm(kOpAnd, rl_result.reg.GetHigh(), 0x7fffffff);
+    // Inconvenient overlap, use a temp register to preserve the high word of the source.
+    RegStorage rs_tmp = AllocTemp();
+    OpRegCopy(rs_tmp, rl_src.reg.GetHigh());
+    OpRegCopy(rl_result.reg.GetLow(), rl_src.reg.GetLow());
+    OpRegRegImm(kOpAnd, rl_result.reg.GetHigh(), rs_tmp, 0x7fffffff);
+    FreeTemp(rs_tmp);
   }
   StoreValueWide(rl_dest, rl_result);
   return true;