OSDN Git Service

Add X86/X86_64 support for CMOV from memory.
authorMark Mendell <mark.p.mendell@intel.com>
Fri, 12 Feb 2016 18:49:03 +0000 (13:49 -0500)
committerMark Mendell <mark.p.mendell@intel.com>
Fri, 12 Feb 2016 19:45:35 +0000 (14:45 -0500)
Add support for the memory form of CMOV.  Add tests.

Change-Id: Ib9f5dbd3031c7e235ee3f2afdb7db75eed46277a
Signed-off-by: Mark Mendell <mark.p.mendell@intel.com>
compiler/utils/x86/assembler_x86.cc
compiler/utils/x86/assembler_x86.h
compiler/utils/x86/assembler_x86_test.cc
compiler/utils/x86_64/assembler_x86_64.cc
compiler/utils/x86_64/assembler_x86_64.h
compiler/utils/x86_64/assembler_x86_64_test.cc

index 7138a46..3efef70 100644 (file)
@@ -326,6 +326,14 @@ void X86Assembler::cmovl(Condition condition, Register dst, Register src) {
 }
 
 
+void X86Assembler::cmovl(Condition condition, Register dst, const Address& src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x0F);
+  EmitUint8(0x40 + condition);
+  EmitOperand(dst, src);
+}
+
+
 void X86Assembler::setb(Condition condition, Register dst) {
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitUint8(0x0F);
index 759a41e..00ff7bd 100644 (file)
@@ -363,6 +363,7 @@ class X86Assembler FINAL : public Assembler {
   void leal(Register dst, const Address& src);
 
   void cmovl(Condition condition, Register dst, Register src);
+  void cmovl(Condition condition, Register dst, const Address& src);
 
   void setb(Condition condition, Register dst);
 
index 0fd0982..d0d5147 100644 (file)
@@ -332,6 +332,21 @@ TEST_F(AssemblerX86Test, UComisdAddr) {
 }
 
 
+TEST_F(AssemblerX86Test, CmovlAddress) {
+  GetAssembler()->cmovl(x86::kEqual, x86::Register(x86::EAX), x86::Address(
+      x86::Register(x86::EDI), x86::Register(x86::EBX), x86::TIMES_4, 12));
+  GetAssembler()->cmovl(x86::kNotEqual, x86::Register(x86::EDI), x86::Address(
+      x86::Register(x86::ESI), x86::Register(x86::EBX), x86::TIMES_4, 12));
+  GetAssembler()->cmovl(x86::kEqual, x86::Register(x86::EDI), x86::Address(
+      x86::Register(x86::EDI), x86::Register(x86::EAX), x86::TIMES_4, 12));
+  const char* expected =
+    "cmovzl 0xc(%EDI,%EBX,4), %eax\n"
+    "cmovnzl 0xc(%ESI,%EBX,4), %edi\n"
+    "cmovzl 0xc(%EDI,%EAX,4), %edi\n";
+
+  DriverStr(expected, "cmovl_address");
+}
+
 /////////////////
 // Near labels //
 /////////////////
index 10f5a00..d86ad1b 100644 (file)
@@ -223,6 +223,19 @@ void X86_64Assembler::cmov(Condition c, CpuRegister dst, CpuRegister src, bool i
 }
 
 
+void X86_64Assembler::cmov(Condition c, CpuRegister dst, const Address& src, bool is64bit) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  if (is64bit) {
+    EmitRex64(dst, src);
+  } else {
+    EmitOptionalRex32(dst, src);
+  }
+  EmitUint8(0x0F);
+  EmitUint8(0x40 + c);
+  EmitOperand(dst.LowBits(), src);
+}
+
+
 void X86_64Assembler::movzxb(CpuRegister dst, CpuRegister src) {
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitOptionalByteRegNormalizingRex32(dst, src);
index 6f0847e..f00cb12 100644 (file)
@@ -366,6 +366,7 @@ class X86_64Assembler FINAL : public Assembler {
 
   void cmov(Condition c, CpuRegister dst, CpuRegister src);  // This is the 64b version.
   void cmov(Condition c, CpuRegister dst, CpuRegister src, bool is64bit);
+  void cmov(Condition c, CpuRegister dst, const Address& src, bool is64bit);
 
   void movzxb(CpuRegister dst, CpuRegister src);
   void movzxb(CpuRegister dst, const Address& src);
index 8a87fca..4f65709 100644 (file)
@@ -1371,6 +1371,37 @@ TEST_F(AssemblerX86_64Test, PopcntqAddress) {
   DriverStr(expected, "popcntq_address");
 }
 
+TEST_F(AssemblerX86_64Test, CmovlAddress) {
+  GetAssembler()->cmov(x86_64::kEqual, x86_64::CpuRegister(x86_64::R10), x86_64::Address(
+      x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_4, 12), false);
+  GetAssembler()->cmov(x86_64::kNotEqual, x86_64::CpuRegister(x86_64::RDI), x86_64::Address(
+      x86_64::CpuRegister(x86_64::R10), x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_4, 12), false);
+  GetAssembler()->cmov(x86_64::kEqual, x86_64::CpuRegister(x86_64::RDI), x86_64::Address(
+      x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_4, 12), false);
+  const char* expected =
+    "cmovzl 0xc(%RDI,%RBX,4), %R10d\n"
+    "cmovnzl 0xc(%R10,%RBX,4), %edi\n"
+    "cmovzl 0xc(%RDI,%R9,4), %edi\n";
+
+  DriverStr(expected, "cmovl_address");
+}
+
+TEST_F(AssemblerX86_64Test, CmovqAddress) {
+  GetAssembler()->cmov(x86_64::kEqual, x86_64::CpuRegister(x86_64::R10), x86_64::Address(
+      x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_4, 12), true);
+  GetAssembler()->cmov(x86_64::kNotEqual, x86_64::CpuRegister(x86_64::RDI), x86_64::Address(
+      x86_64::CpuRegister(x86_64::R10), x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_4, 12), true);
+  GetAssembler()->cmov(x86_64::kEqual, x86_64::CpuRegister(x86_64::RDI), x86_64::Address(
+      x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_4, 12), true);
+  const char* expected =
+    "cmovzq 0xc(%RDI,%RBX,4), %R10\n"
+    "cmovnzq 0xc(%R10,%RBX,4), %rdi\n"
+    "cmovzq 0xc(%RDI,%R9,4), %rdi\n";
+
+  DriverStr(expected, "cmovq_address");
+}
+
+
 /////////////////
 // Near labels //
 /////////////////