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");
 }