x86_64: Fix intrinsics

The following intrinsics have been ported:

- Abs(double/long/int/float)
- String.indexOf/charAt/compareTo/is_empty/length
- Float.floatToRawIntBits, Float.intBitsToFloat
- Double.doubleToRawLongBits, Double.longBitsToDouble
- Thread.currentThread
- Unsafe.getInt/Long/Object, Unsafe.putInt/Long/Object
- Math.sqrt, Math.max, Math.min
- Long.reverseBytes

Math.min and max for longs have been implemented for x86_64.

Commented out until good tests available:
- Memory.peekShort/Int/Long, Memory.pokeShort/Int/Long

Turned off on x86-64 as reported having problems
- Cas

Change-Id: I934bc9c90fdf953be0d3836a17b6ee4e7c98f244
diff --git a/compiler/dex/quick/x86/int_x86.cc b/compiler/dex/quick/x86/int_x86.cc
old mode 100644
new mode 100755
index ed4c775..5372512
--- a/compiler/dex/quick/x86/int_x86.cc
+++ b/compiler/dex/quick/x86/int_x86.cc
@@ -716,17 +716,17 @@
 bool X86Mir2Lir::GenInlinedMinMax(CallInfo* info, bool is_min, bool is_long) {
   DCHECK(cu_->instruction_set == kX86 || cu_->instruction_set == kX86_64);
 
-  if (is_long) {
+  if (is_long && cu_->instruction_set == kX86) {
     return false;
   }
 
   // Get the two arguments to the invoke and place them in GP registers.
   RegLocation rl_src1 = info->args[0];
-  RegLocation rl_src2 = info->args[1];
-  rl_src1 = LoadValue(rl_src1, kCoreReg);
-  rl_src2 = LoadValue(rl_src2, kCoreReg);
+  RegLocation rl_src2 = (is_long) ? info->args[2] : info->args[1];
+  rl_src1 = (is_long) ? LoadValueWide(rl_src1, kCoreReg) : LoadValue(rl_src1, kCoreReg);
+  rl_src2 = (is_long) ? LoadValueWide(rl_src2, kCoreReg) : LoadValue(rl_src2, kCoreReg);
 
-  RegLocation rl_dest = InlineTarget(info);
+  RegLocation rl_dest = (is_long) ? InlineTargetWide(info) : InlineTarget(info);
   RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
 
   /*
@@ -752,43 +752,63 @@
     OpCondRegReg(kOpCmov, condition_code, rl_result.reg, rl_src2.reg);
   }
 
-  StoreValue(rl_dest, rl_result);
-  return true;
-}
-
-bool X86Mir2Lir::GenInlinedPeek(CallInfo* info, OpSize size) {
-  RegLocation rl_src_address = info->args[0];  // long address
-  rl_src_address = NarrowRegLoc(rl_src_address);  // ignore high half in info->args[1]
-  RegLocation rl_dest = size == k64 ? InlineTargetWide(info) : InlineTarget(info);
-  RegLocation rl_address = LoadValue(rl_src_address, kCoreReg);
-  RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
-  // Unaligned access is allowed on x86.
-  LoadBaseDisp(rl_address.reg, 0, rl_result.reg, size, kNotVolatile);
-  if (size == k64) {
+  if (is_long) {
     StoreValueWide(rl_dest, rl_result);
   } else {
-    DCHECK(size == kSignedByte || size == kSignedHalf || size == k32);
     StoreValue(rl_dest, rl_result);
   }
   return true;
 }
 
+bool X86Mir2Lir::GenInlinedPeek(CallInfo* info, OpSize size) {
+  return false;
+// Turned off until tests available in Art.
+//
+//  RegLocation rl_src_address = info->args[0];  // long address
+//  RegLocation rl_address;
+//  if (!cu_->target64) {
+//    rl_src_address = NarrowRegLoc(rl_src_address);  // ignore high half in info->args[0]
+//    rl_address = LoadValue(rl_src_address, kCoreReg);
+//  } else {
+//    rl_address = LoadValueWide(rl_src_address, kCoreReg);
+//  }
+//  RegLocation rl_dest = size == k64 ? InlineTargetWide(info) : InlineTarget(info);
+//  RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
+//  // Unaligned access is allowed on x86.
+//  LoadBaseDisp(rl_address.reg, 0, rl_result.reg, size, kNotVolatile);
+//  if (size == k64) {
+//    StoreValueWide(rl_dest, rl_result);
+//  } else {
+//    DCHECK(size == kSignedByte || size == kSignedHalf || size == k32);
+//    StoreValue(rl_dest, rl_result);
+//  }
+//  return true;
+}
+
 bool X86Mir2Lir::GenInlinedPoke(CallInfo* info, OpSize size) {
-  RegLocation rl_src_address = info->args[0];  // long address
-  rl_src_address = NarrowRegLoc(rl_src_address);  // ignore high half in info->args[1]
-  RegLocation rl_src_value = info->args[2];  // [size] value
-  RegLocation rl_address = LoadValue(rl_src_address, kCoreReg);
-  if (size == k64) {
-    // Unaligned access is allowed on x86.
-    RegLocation rl_value = LoadValueWide(rl_src_value, kCoreReg);
-    StoreBaseDisp(rl_address.reg, 0, rl_value.reg, size, kNotVolatile);
-  } else {
-    DCHECK(size == kSignedByte || size == kSignedHalf || size == k32);
-    // Unaligned access is allowed on x86.
-    RegLocation rl_value = LoadValue(rl_src_value, kCoreReg);
-    StoreBaseDisp(rl_address.reg, 0, rl_value.reg, size, kNotVolatile);
-  }
-  return true;
+  return false;
+// Turned off until tests available in Art.
+//
+//  RegLocation rl_src_address = info->args[0];  // long address
+//  RegLocation rl_address;
+//  if (!cu_->target64) {
+//    rl_src_address = NarrowRegLoc(rl_src_address);  // ignore high half in info->args[0]
+//    rl_address = LoadValue(rl_src_address, kCoreReg);
+//  } else {
+//    rl_address = LoadValueWide(rl_src_address, kCoreReg);
+//  }
+//  RegLocation rl_src_value = info->args[2];  // [size] value
+//  if (size == k64) {
+//    // Unaligned access is allowed on x86.
+//    RegLocation rl_value = LoadValueWide(rl_src_value, kCoreReg);
+//    StoreBaseDisp(rl_address.reg, 0, rl_value.reg, size, kNotVolatile);
+//  } else {
+//    DCHECK(size == kSignedByte || size == kSignedHalf || size == k32);
+//    // Unaligned access is allowed on x86.
+//    RegLocation rl_value = LoadValue(rl_src_value, kCoreReg);
+//    StoreBaseDisp(rl_address.reg, 0, rl_value.reg, size, kNotVolatile);
+//  }
+//  return true;
 }
 
 void X86Mir2Lir::OpLea(RegStorage r_base, RegStorage reg1, RegStorage reg2, int scale, int offset) {
@@ -811,6 +831,10 @@
 
 bool X86Mir2Lir::GenInlinedCas(CallInfo* info, bool is_long, bool is_object) {
   DCHECK(cu_->instruction_set == kX86 || cu_->instruction_set == kX86_64);
+  if (cu_->instruction_set == kX86_64) {
+    return false;  // TODO: Verify working on x86-64.
+  }
+
   // Unused - RegLocation rl_src_unsafe = info->args[0];
   RegLocation rl_src_obj = info->args[1];  // Object - known non-null
   RegLocation rl_src_offset = info->args[2];  // long low
@@ -820,7 +844,24 @@
   RegLocation rl_src_new_value = info->args[is_long ? 6 : 5];  // int, long or Object
   // If is_long, high half is in info->args[7]
 
-  if (is_long) {
+  if (is_long && cu_->target64) {
+    // RAX must hold expected for CMPXCHG. Neither rl_new_value, nor r_ptr may be in RAX.
+    FlushReg(rs_r0);
+    Clobber(rs_r0);
+    LockTemp(rs_r0);
+
+    RegLocation rl_object = LoadValue(rl_src_obj, kRefReg);
+    RegLocation rl_new_value = LoadValueWide(rl_src_new_value, kCoreReg);
+    RegLocation rl_offset = LoadValue(rl_src_offset, kCoreReg);
+    LoadValueDirectWide(rl_src_expected, rs_r0);
+    NewLIR5(kX86LockCmpxchg64AR, rl_object.reg.GetReg(), rl_offset.reg.GetReg(), 0, 0, rl_new_value.reg.GetReg());
+
+    // After a store we need to insert barrier in case of potential load. Since the
+    // locked cmpxchg has full barrier semantics, only a scheduling barrier will be generated.
+    GenMemBarrier(kStoreLoad);
+
+    FreeTemp(rs_r0);
+  } else if (is_long) {
     // TODO: avoid unnecessary loads of SI and DI when the values are in registers.
     // TODO: CFI support.
     FlushAllRegs();