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();