x86_64: Add XADD instruction and tests for it.

Bug: 65872996
Test: m test-art-host-gtest  # new test cases for XADD
Change-Id: Idaa5f40dab106e7f48bfd8adeee629bcdaa8e33a
diff --git a/compiler/utils/x86_64/assembler_x86_64.cc b/compiler/utils/x86_64/assembler_x86_64.cc
index 52cedf0..0f90ec8 100644
--- a/compiler/utils/x86_64/assembler_x86_64.cc
+++ b/compiler/utils/x86_64/assembler_x86_64.cc
@@ -3914,6 +3914,80 @@
 }
 
 
+void X86_64Assembler::xaddb(CpuRegister dst, CpuRegister src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitOptionalByteRegNormalizingRex32(src, dst, /*normalize_both=*/ true);
+  EmitUint8(0x0F);
+  EmitUint8(0xC0);
+  EmitRegisterOperand(src.LowBits(), dst.LowBits());
+}
+
+
+void X86_64Assembler::xaddb(const Address& address, CpuRegister reg) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitOptionalByteRegNormalizingRex32(reg, address);
+  EmitUint8(0x0F);
+  EmitUint8(0xC0);
+  EmitOperand(reg.LowBits(), address);
+}
+
+
+void X86_64Assembler::xaddw(CpuRegister dst, CpuRegister src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitOperandSizeOverride();
+  EmitOptionalRex32(src, dst);
+  EmitUint8(0x0F);
+  EmitUint8(0xC1);
+  EmitRegisterOperand(src.LowBits(), dst.LowBits());
+}
+
+
+void X86_64Assembler::xaddw(const Address& address, CpuRegister reg) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitOperandSizeOverride();
+  EmitOptionalRex32(reg, address);
+  EmitUint8(0x0F);
+  EmitUint8(0xC1);
+  EmitOperand(reg.LowBits(), address);
+}
+
+
+void X86_64Assembler::xaddl(CpuRegister dst, CpuRegister src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitOptionalRex32(src, dst);
+  EmitUint8(0x0F);
+  EmitUint8(0xC1);
+  EmitRegisterOperand(src.LowBits(), dst.LowBits());
+}
+
+
+void X86_64Assembler::xaddl(const Address& address, CpuRegister reg) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitOptionalRex32(reg, address);
+  EmitUint8(0x0F);
+  EmitUint8(0xC1);
+  EmitOperand(reg.LowBits(), address);
+}
+
+
+void X86_64Assembler::xaddq(CpuRegister dst, CpuRegister src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitRex64(src, dst);
+  EmitUint8(0x0F);
+  EmitUint8(0xC1);
+  EmitRegisterOperand(src.LowBits(), dst.LowBits());
+}
+
+
+void X86_64Assembler::xaddq(const Address& address, CpuRegister reg) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitRex64(reg, address);
+  EmitUint8(0x0F);
+  EmitUint8(0xC1);
+  EmitOperand(reg.LowBits(), address);
+}
+
+
 void X86_64Assembler::cmpb(const Address& address, const Immediate& imm) {
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   CHECK(imm.is_int32());
diff --git a/compiler/utils/x86_64/assembler_x86_64.h b/compiler/utils/x86_64/assembler_x86_64.h
index 8ef8931..bed3d34 100644
--- a/compiler/utils/x86_64/assembler_x86_64.h
+++ b/compiler/utils/x86_64/assembler_x86_64.h
@@ -787,6 +787,18 @@
   void xchgq(CpuRegister dst, CpuRegister src);
   void xchgq(CpuRegister reg, const Address& address);
 
+  void xaddb(CpuRegister dst, CpuRegister src);
+  void xaddb(const Address& address, CpuRegister reg);
+
+  void xaddw(CpuRegister dst, CpuRegister src);
+  void xaddw(const Address& address, CpuRegister reg);
+
+  void xaddl(CpuRegister dst, CpuRegister src);
+  void xaddl(const Address& address, CpuRegister reg);
+
+  void xaddq(CpuRegister dst, CpuRegister src);
+  void xaddq(const Address& address, CpuRegister reg);
+
   void cmpb(const Address& address, const Immediate& imm);
   void cmpw(const Address& address, const Immediate& imm);
 
diff --git a/compiler/utils/x86_64/assembler_x86_64_test.cc b/compiler/utils/x86_64/assembler_x86_64_test.cc
index feee577..2911d96 100644
--- a/compiler/utils/x86_64/assembler_x86_64_test.cc
+++ b/compiler/utils/x86_64/assembler_x86_64_test.cc
@@ -988,6 +988,38 @@
   DriverStr(RepeatbA(&x86_64::X86_64Assembler::xchgb, "xchgb %{reg}, {mem}"), "xchgb");
 }
 
+TEST_F(AssemblerX86_64Test, XaddqReg) {
+  DriverStr(RepeatRR(&x86_64::X86_64Assembler::xaddq, "xaddq %{reg2}, %{reg1}"), "xaddq");
+}
+
+TEST_F(AssemblerX86_64Test, XaddqMem) {
+  DriverStr(RepeatAR(&x86_64::X86_64Assembler::xaddq, "xaddq %{reg}, {mem}"), "xaddq");
+}
+
+TEST_F(AssemblerX86_64Test, XaddlReg) {
+  DriverStr(Repeatrr(&x86_64::X86_64Assembler::xaddl, "xaddl %{reg2}, %{reg1}"), "xaddl");
+}
+
+TEST_F(AssemblerX86_64Test, XaddlMem) {
+  DriverStr(RepeatAr(&x86_64::X86_64Assembler::xaddl, "xaddl %{reg}, {mem}"), "xaddl");
+}
+
+TEST_F(AssemblerX86_64Test, XaddwReg) {
+  DriverStr(Repeatww(&x86_64::X86_64Assembler::xaddw, "xaddw %{reg2}, %{reg1}"), "xaddw");
+}
+
+TEST_F(AssemblerX86_64Test, XaddwMem) {
+  DriverStr(RepeatAw(&x86_64::X86_64Assembler::xaddw, "xaddw %{reg}, {mem}"), "xaddw");
+}
+
+TEST_F(AssemblerX86_64Test, XaddbReg) {
+  DriverStr(Repeatbb(&x86_64::X86_64Assembler::xaddb, "xaddb %{reg2}, %{reg1}"), "xaddb");
+}
+
+TEST_F(AssemblerX86_64Test, XaddbMem) {
+  DriverStr(RepeatAb(&x86_64::X86_64Assembler::xaddb, "xaddb %{reg}, {mem}"), "xaddb");
+}
+
 TEST_F(AssemblerX86_64Test, Cmpxchgb) {
   DriverStr(RepeatAb(&x86_64::X86_64Assembler::cmpxchgb, "cmpxchgb %{reg}, {mem}"), "cmpxchgb");
 }