x86_64: Add LockXadd* helper function and tests for it.
A separate function is need for 16-bit variant `lock xaddw` because the
LOCK prefix should go after the operand size override prefix to match
the order of prefixes emitted by the reference implementation.
Bug: 65872996
Test: m test-art-host-gtest # new test cases for LOCK XADD
Change-Id: I29946c75c76966cb9c6425b2a22eae3664ce3c00
diff --git a/compiler/utils/x86_64/assembler_x86_64.h b/compiler/utils/x86_64/assembler_x86_64.h
index bed3d34..2eb018d 100644
--- a/compiler/utils/x86_64/assembler_x86_64.h
+++ b/compiler/utils/x86_64/assembler_x86_64.h
@@ -1011,6 +1011,30 @@
lock()->cmpxchgq(address, reg);
}
+ void LockXaddb(const Address& address, CpuRegister reg) {
+ lock()->xaddb(address, reg);
+ }
+
+ void LockXaddw(const Address& address, CpuRegister reg) {
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+ // We make sure that the operand size override bytecode is emited before the lock bytecode.
+ // We test against clang which enforces this bytecode order.
+ EmitOperandSizeOverride();
+ EmitUint8(0xF0);
+ EmitOptionalRex32(reg, address);
+ EmitUint8(0x0F);
+ EmitUint8(0xC1);
+ EmitOperand(reg.LowBits(), address);
+ }
+
+ void LockXaddl(const Address& address, CpuRegister reg) {
+ lock()->xaddl(address, reg);
+ }
+
+ void LockXaddq(const Address& address, CpuRegister reg) {
+ lock()->xaddq(address, reg);
+ }
+
//
// Misc. functionality
//
diff --git a/compiler/utils/x86_64/assembler_x86_64_test.cc b/compiler/utils/x86_64/assembler_x86_64_test.cc
index 2911d96..38fc568 100644
--- a/compiler/utils/x86_64/assembler_x86_64_test.cc
+++ b/compiler/utils/x86_64/assembler_x86_64_test.cc
@@ -1020,6 +1020,26 @@
DriverStr(RepeatAb(&x86_64::X86_64Assembler::xaddb, "xaddb %{reg}, {mem}"), "xaddb");
}
+TEST_F(AssemblerX86_64Test, LockXaddq) {
+ DriverStr(
+ RepeatAR(&x86_64::X86_64Assembler::LockXaddq, "lock xaddq %{reg}, {mem}"), "lock_xaddq");
+}
+
+TEST_F(AssemblerX86_64Test, LockXaddl) {
+ DriverStr(
+ RepeatAr(&x86_64::X86_64Assembler::LockXaddl, "lock xaddl %{reg}, {mem}"), "lock_xaddl");
+}
+
+TEST_F(AssemblerX86_64Test, LockXaddw) {
+ DriverStr(
+ RepeatAw(&x86_64::X86_64Assembler::LockXaddw, "lock xaddw %{reg}, {mem}"), "lock_xaddw");
+}
+
+TEST_F(AssemblerX86_64Test, LockXaddb) {
+ DriverStr(
+ RepeatAb(&x86_64::X86_64Assembler::LockXaddb, "lock xaddb %{reg}, {mem}"), "lock_xaddb");
+}
+
TEST_F(AssemblerX86_64Test, Cmpxchgb) {
DriverStr(RepeatAb(&x86_64::X86_64Assembler::cmpxchgb, "cmpxchgb %{reg}, {mem}"), "cmpxchgb");
}