summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVladimir Marko <vmarko@google.com>2013-12-03 15:25:24 +0000
committerVladimir Marko <vmarko@google.com>2013-12-03 18:32:29 +0000
commit70b797d998f2a28e39f7d6ffc8a07c9cbc47da14 (patch)
treee5607068be133899ff9111e33327e0c2aa525cd1
parent057c74a3a2d50d1247d4e6472763ca6f59060762 (diff)
downloadart-70b797d998f2a28e39f7d6ffc8a07c9cbc47da14.tar.gz
art-70b797d998f2a28e39f7d6ffc8a07c9cbc47da14.tar.bz2
art-70b797d998f2a28e39f7d6ffc8a07c9cbc47da14.zip
Unsafe.compareAndSwapLong() intrinsic for x86.
Change-Id: Idbc5371a62dfdd84485a657d4548990519200205
-rw-r--r--compiler/dex/compiler_enums.h1
-rw-r--r--compiler/dex/quick/mir_to_lir.h1
-rw-r--r--compiler/dex/quick/x86/assemble_x86.cc6
-rw-r--r--compiler/dex/quick/x86/int_x86.cc21
-rw-r--r--compiler/dex/quick/x86/target_x86.cc4
-rw-r--r--compiler/dex/quick/x86/x86_dex_file_method_inliner.cc4
-rw-r--r--compiler/dex/quick/x86/x86_lir.h2
-rw-r--r--disassembler/disassembler_x86.cc7
8 files changed, 42 insertions, 4 deletions
diff --git a/compiler/dex/compiler_enums.h b/compiler/dex/compiler_enums.h
index 56facfd889..d73f148dcf 100644
--- a/compiler/dex/compiler_enums.h
+++ b/compiler/dex/compiler_enums.h
@@ -374,6 +374,7 @@ enum OpFeatureFlags {
kRegUseA,
kRegUseC,
kRegUseD,
+ kRegUseB,
kRegUseFPCSList0,
kRegUseFPCSList2,
kRegUseList0,
diff --git a/compiler/dex/quick/mir_to_lir.h b/compiler/dex/quick/mir_to_lir.h
index 92e21ffdf7..9d35667b51 100644
--- a/compiler/dex/quick/mir_to_lir.h
+++ b/compiler/dex/quick/mir_to_lir.h
@@ -71,6 +71,7 @@ typedef uint32_t CodeOffset; // Native code offset in bytes.
#define REG_USEA (1ULL << kRegUseA)
#define REG_USEC (1ULL << kRegUseC)
#define REG_USED (1ULL << kRegUseD)
+#define REG_USEB (1ULL << kRegUseB)
#define REG_USE_FPCS_LIST0 (1ULL << kRegUseFPCSList0)
#define REG_USE_FPCS_LIST2 (1ULL << kRegUseFPCSList2)
#define REG_USE_LIST0 (1ULL << kRegUseList0)
diff --git a/compiler/dex/quick/x86/assemble_x86.cc b/compiler/dex/quick/x86/assemble_x86.cc
index 0b7b2bd94f..96dc6ee7d1 100644
--- a/compiler/dex/quick/x86/assemble_x86.cc
+++ b/compiler/dex/quick/x86/assemble_x86.cc
@@ -246,7 +246,9 @@ ENCODING_MAP(Cmp, IS_LOAD, 0, 0,
UNARY_ENCODING_MAP(Idivmod, 0x7, 0, SETS_CCODES, DaR, kRegRegReg, IS_UNARY_OP | REG_USE0, DaM, kRegRegMem, IS_BINARY_OP | REG_USE0, DaA, kRegRegArray, IS_QUAD_OP | REG_USE01, 0, REG_DEFA_USEA, REG_DEFAD_USEAD, REG_DEFAD_USEAD, "ah:al,ax,", "dx:ax,dx:ax,", "edx:eax,edx:eax,"),
#undef UNARY_ENCODING_MAP
- { kX86Bswap32R, kRegOpcode, IS_UNARY_OP | REG_DEF0_USE0, { 0, 0, 0x0F, 0xC8, 0, 0, 0, 0 }, "Bswap32R", "!0r" },
+ { kX86Bswap32R, kRegOpcode, IS_UNARY_OP | REG_DEF0_USE0, { 0, 0, 0x0F, 0xC8, 0, 0, 0, 0 }, "Bswap32R", "!0r" },
+ { kX86Push32R, kRegOpcode, IS_UNARY_OP | REG_USE0 | IS_STORE, { 0, 0, 0x50, 0, 0, 0, 0, 0 }, "Push32R", "!0r" },
+ { kX86Pop32R, kRegOpcode, IS_UNARY_OP | REG_DEF0 | IS_LOAD, { 0, 0, 0x58, 0, 0, 0, 0, 0 }, "Pop32R", "!0r" },
#define EXT_0F_ENCODING_MAP(opname, prefix, opcode, reg_def) \
{ kX86 ## opname ## RR, kRegReg, IS_BINARY_OP | reg_def | REG_USE01, { prefix, 0, 0x0F, opcode, 0, 0, 0, 0 }, #opname "RR", "!0r,!1r" }, \
@@ -308,6 +310,8 @@ ENCODING_MAP(Cmp, IS_LOAD, 0, 0,
{ kX86CmpxchgAR, kArrayReg, IS_STORE | IS_QUIN_OP | REG_USE014 | REG_DEFA_USEA | SETS_CCODES, { 0, 0, 0x0F, 0xB1, 0, 0, 0, 0 }, "Cmpxchg", "[!0r+!1r<<!2d+!3d],!4r" },
{ kX86LockCmpxchgMR, kMemReg, IS_STORE | IS_TERTIARY_OP | REG_USE02 | REG_DEFA_USEA | SETS_CCODES, { 0xF0, 0, 0x0F, 0xB1, 0, 0, 0, 0 }, "Lock Cmpxchg", "[!0r+!1d],!2r" },
{ kX86LockCmpxchgAR, kArrayReg, IS_STORE | IS_QUIN_OP | REG_USE014 | REG_DEFA_USEA | SETS_CCODES, { 0xF0, 0, 0x0F, 0xB1, 0, 0, 0, 0 }, "Lock Cmpxchg", "[!0r+!1r<<!2d+!3d],!4r" },
+ { kX86LockCmpxchg8bM, kMem, IS_STORE | IS_BINARY_OP | REG_USE0 | REG_DEFAD_USEAD | REG_USEC | REG_USEB | SETS_CCODES, { 0xF0, 0, 0x0F, 0xC7, 0, 1, 0, 0 }, "Lock Cmpxchg8b", "[!0r+!1d]" },
+ { kX86LockCmpxchg8bA, kArray, IS_STORE | IS_QUAD_OP | REG_USE01 | REG_DEFAD_USEAD | REG_USEC | REG_USEB | SETS_CCODES, { 0xF0, 0, 0x0F, 0xC7, 0, 1, 0, 0 }, "Lock Cmpxchg8b", "[!0r+!1r<<!2d+!3d]" },
EXT_0F_ENCODING_MAP(Movzx8, 0x00, 0xB6, REG_DEF0),
EXT_0F_ENCODING_MAP(Movzx16, 0x00, 0xB7, REG_DEF0),
diff --git a/compiler/dex/quick/x86/int_x86.cc b/compiler/dex/quick/x86/int_x86.cc
index b65fe549c9..0133a0afaf 100644
--- a/compiler/dex/quick/x86/int_x86.cc
+++ b/compiler/dex/quick/x86/int_x86.cc
@@ -293,7 +293,26 @@ bool X86Mir2Lir::GenInlinedCas(CallInfo* info, bool is_long, bool is_object) {
// If is_long, high half is in info->args[7]
if (is_long) {
- LOG(FATAL) << "CAS64: Not implemented";
+ FlushAllRegs();
+ LockCallTemps();
+ NewLIR1(kX86Push32R, rDI);
+ MarkTemp(rDI);
+ LockTemp(rDI);
+ NewLIR1(kX86Push32R, rSI);
+ MarkTemp(rSI);
+ LockTemp(rSI);
+ LoadValueDirectFixed(rl_src_obj, rDI);
+ LoadValueDirectFixed(rl_src_offset, rSI);
+ LoadValueDirectWideFixed(rl_src_expected, rAX, rDX);
+ LoadValueDirectWideFixed(rl_src_new_value, rBX, rCX);
+ NewLIR4(kX86LockCmpxchg8bA, rDI, rSI, 0, 0);
+ FreeTemp(rSI);
+ UnmarkTemp(rSI);
+ NewLIR1(kX86Pop32R, rSI);
+ FreeTemp(rDI);
+ UnmarkTemp(rDI);
+ NewLIR1(kX86Pop32R, rDI);
+ FreeCallTemps();
} else {
// EAX must hold expected for CMPXCHG. Neither rl_new_value, nor r_ptr may be in EAX.
FlushReg(r0);
diff --git a/compiler/dex/quick/x86/target_x86.cc b/compiler/dex/quick/x86/target_x86.cc
index 878fa769b6..b7a607fa40 100644
--- a/compiler/dex/quick/x86/target_x86.cc
+++ b/compiler/dex/quick/x86/target_x86.cc
@@ -165,6 +165,10 @@ void X86Mir2Lir::SetupTargetResourceMasks(LIR* lir, uint64_t flags) {
if (flags & REG_USED) {
SetupRegMask(&lir->u.m.use_mask, rDX);
}
+
+ if (flags & REG_USEB) {
+ SetupRegMask(&lir->u.m.use_mask, rBX);
+ }
}
/* For dumping instructions */
diff --git a/compiler/dex/quick/x86/x86_dex_file_method_inliner.cc b/compiler/dex/quick/x86/x86_dex_file_method_inliner.cc
index f0e76c9e5e..88e933f868 100644
--- a/compiler/dex/quick/x86/x86_dex_file_method_inliner.cc
+++ b/compiler/dex/quick/x86/x86_dex_file_method_inliner.cc
@@ -66,8 +66,8 @@ const DexFileMethodInliner::IntrinsicDef X86DexFileMethodInliner::kIntrinsicMeth
INTRINSIC(SunMiscUnsafe, CompareAndSwapInt, ObjectJII_Z, kIntrinsicCas,
kIntrinsicFlagNone),
- // INTRINSIC(SunMiscUnsafe, CompareAndSwapLong, ObjectJJJ_Z, kIntrinsicCas,
- // kIntrinsicFlagIsLong),
+ INTRINSIC(SunMiscUnsafe, CompareAndSwapLong, ObjectJJJ_Z, kIntrinsicCas,
+ kIntrinsicFlagIsLong),
INTRINSIC(SunMiscUnsafe, CompareAndSwapObject, ObjectJObjectObject_Z, kIntrinsicCas,
kIntrinsicFlagIsObject),
diff --git a/compiler/dex/quick/x86/x86_lir.h b/compiler/dex/quick/x86/x86_lir.h
index bbcae92f7d..5fe76fe2f9 100644
--- a/compiler/dex/quick/x86/x86_lir.h
+++ b/compiler/dex/quick/x86/x86_lir.h
@@ -314,6 +314,7 @@ enum X86OpCode {
UnaryOpcode(kX86Divmod, DaR, DaM, DaA),
UnaryOpcode(kX86Idivmod, DaR, DaM, DaA),
kX86Bswap32R,
+ kX86Push32R, kX86Pop32R,
#undef UnaryOpcode
#define Binary0fOpCode(opcode) \
opcode ## RR, opcode ## RM, opcode ## RA
@@ -355,6 +356,7 @@ enum X86OpCode {
Binary0fOpCode(kX86Imul32), // 32bit multiply
kX86CmpxchgRR, kX86CmpxchgMR, kX86CmpxchgAR, // compare and exchange
kX86LockCmpxchgMR, kX86LockCmpxchgAR, // locked compare and exchange
+ kX86LockCmpxchg8bM, kX86LockCmpxchg8bA, // locked compare and exchange
Binary0fOpCode(kX86Movzx8), // zero-extend 8-bit value
Binary0fOpCode(kX86Movzx16), // zero-extend 16-bit value
Binary0fOpCode(kX86Movsx8), // sign-extend 8-bit value
diff --git a/disassembler/disassembler_x86.cc b/disassembler/disassembler_x86.cc
index 9ed65cd80a..8781c7a274 100644
--- a/disassembler/disassembler_x86.cc
+++ b/disassembler/disassembler_x86.cc
@@ -520,6 +520,13 @@ DISASSEMBLER_ENTRY(cmp,
case 0xB7: opcode << "movzxw"; has_modrm = true; load = true; break;
case 0xBE: opcode << "movsxb"; has_modrm = true; load = true; break;
case 0xBF: opcode << "movsxw"; has_modrm = true; load = true; break;
+ case 0xC7:
+ static const char* x0FxC7_opcodes[] = { "unknown-0f-c7", "cmpxchg8b", "unknown-0f-c7", "unknown-0f-c7", "unknown-0f-c7", "unknown-0f-c7", "unknown-0f-c7", "unknown-0f-c7" };
+ modrm_opcodes = x0FxC7_opcodes;
+ has_modrm = true;
+ reg_is_opcode = true;
+ store = true;
+ break;
case 0xC8: case 0xC9: case 0xCA: case 0xCB: case 0xCC: case 0xCD: case 0xCE: case 0xCF:
opcode << "bswap";
reg_in_opcode = true;