Handle a few more instructions in assembler (cmov, cdq, cmpxchg, xadd, xchg).

BUG=none
R=stichnot@chromium.org

Review URL: https://codereview.chromium.org/597643002
diff --git a/src/IceInstX8632.cpp b/src/IceInstX8632.cpp
index 8c6b99a..3fd74f9 100644
--- a/src/IceInstX8632.cpp
+++ b/src/IceInstX8632.cpp
@@ -213,7 +213,7 @@
   addSource(Desired);
 }
 
-InstX8632Cmpxchg8b::InstX8632Cmpxchg8b(Cfg *Func, OperandX8632 *Addr,
+InstX8632Cmpxchg8b::InstX8632Cmpxchg8b(Cfg *Func, OperandX8632Mem *Addr,
                                        Variable *Edx, Variable *Eax,
                                        Variable *Ecx, Variable *Ebx,
                                        bool Locked)
@@ -810,6 +810,34 @@
   }
 }
 
+template <> void InstX8632Cbwdq::emitIAS(const Cfg *Func) const {
+  Ostream &Str = Func->getContext()->getStrEmit();
+  x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>();
+  intptr_t StartPosition = Asm->GetPosition();
+  assert(getSrcSize() == 1);
+  Operand *Src0 = getSrc(0);
+  assert(llvm::isa<Variable>(Src0));
+  assert(llvm::cast<Variable>(Src0)->getRegNum() == RegX8632::Reg_eax);
+  switch (Src0->getType()) {
+  default:
+    llvm_unreachable("unexpected source type!");
+    break;
+  case IceType_i8:
+    assert(getDest()->getRegNum() == RegX8632::Reg_eax);
+    Asm->cbw();
+    break;
+  case IceType_i16:
+    assert(getDest()->getRegNum() == RegX8632::Reg_edx);
+    Asm->cwd();
+    break;
+  case IceType_i32:
+    assert(getDest()->getRegNum() == RegX8632::Reg_edx);
+    Asm->cdq();
+    break;
+  }
+  emitIASBytes(Str, Asm, StartPosition);
+}
+
 void InstX8632Mul::emit(const Cfg *Func) const {
   Ostream &Str = Func->getContext()->getStrEmit();
   assert(getSrcSize() == 2);
@@ -892,6 +920,23 @@
   Str << "\n";
 }
 
+void InstX8632Cmov::emitIAS(const Cfg *Func) const {
+  Ostream &Str = Func->getContext()->getStrEmit();
+  Str << "\t";
+  assert(Condition != CondX86::Br_None);
+  assert(getDest()->hasReg());
+  assert(getSrcSize() == 2);
+  // Only need the reg/reg form now.
+  const Variable *Src = llvm::cast<Variable>(getSrc(1));
+  assert(Src->hasReg());
+  assert(Src->getType() == IceType_i32);
+  x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>();
+  intptr_t StartPosition = Asm->GetPosition();
+  Asm->cmov(Condition, RegX8632::getEncodedGPR(getDest()->getRegNum()),
+            RegX8632::getEncodedGPR(Src->getRegNum()));
+  emitIASBytes(Str, Asm, StartPosition);
+}
+
 void InstX8632Cmov::dump(const Cfg *Func) const {
   Ostream &Str = Func->getContext()->getStrDump();
   Str << "cmov" << InstX8632BrAttributes[Condition].DisplayString << ".";
@@ -958,6 +1003,26 @@
   Str << "\n";
 }
 
+void InstX8632Cmpxchg::emitIAS(const Cfg *Func) const {
+  Ostream &Str = Func->getContext()->getStrEmit();
+  assert(getSrcSize() == 3);
+  x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>();
+  intptr_t StartPosition = Asm->GetPosition();
+  Type Ty = getSrc(0)->getType();
+  const OperandX8632Mem *Mem = llvm::cast<OperandX8632Mem>(getSrc(0));
+  const x86::Address Addr = Mem->toAsmAddress(Asm);
+  const Variable *VarReg = llvm::cast<Variable>(getSrc(2));
+  assert(VarReg->hasReg());
+  const RegX8632::GPRRegister Reg =
+      RegX8632::getEncodedGPR(VarReg->getRegNum());
+  if (Locked) {
+    Asm->LockCmpxchg(Ty, Addr, Reg);
+  } else {
+    Asm->cmpxchg(Ty, Addr, Reg);
+  }
+  emitIASBytes(Str, Asm, StartPosition);
+}
+
 void InstX8632Cmpxchg::dump(const Cfg *Func) const {
   Ostream &Str = Func->getContext()->getStrDump();
   if (Locked) {
@@ -978,6 +1043,20 @@
   Str << "\n";
 }
 
+void InstX8632Cmpxchg8b::emitIAS(const Cfg *Func) const {
+  Ostream &Str = Func->getContext()->getStrEmit();
+  assert(getSrcSize() == 5);
+  x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>();
+  intptr_t StartPosition = Asm->GetPosition();
+  const OperandX8632Mem *Mem = llvm::cast<OperandX8632Mem>(getSrc(0));
+  const x86::Address Addr = Mem->toAsmAddress(Asm);
+  if (Locked) {
+    Asm->lock();
+  }
+  Asm->cmpxchg8b(Addr);
+  emitIASBytes(Str, Asm, StartPosition);
+}
+
 void InstX8632Cmpxchg8b::dump(const Cfg *Func) const {
   Ostream &Str = Func->getContext()->getStrDump();
   if (Locked) {
@@ -1573,6 +1652,25 @@
   Str << "\n";
 }
 
+void InstX8632Xadd::emitIAS(const Cfg *Func) const {
+  Ostream &Str = Func->getContext()->getStrEmit();
+  assert(getSrcSize() == 2);
+  x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>();
+  intptr_t StartPosition = Asm->GetPosition();
+  Type Ty = getSrc(0)->getType();
+  const OperandX8632Mem *Mem = llvm::cast<OperandX8632Mem>(getSrc(0));
+  const x86::Address Addr = Mem->toAsmAddress(Asm);
+  const Variable *VarReg = llvm::cast<Variable>(getSrc(1));
+  assert(VarReg->hasReg());
+  const RegX8632::GPRRegister Reg =
+      RegX8632::getEncodedGPR(VarReg->getRegNum());
+  if (Locked) {
+    Asm->lock();
+  }
+  Asm->xadd(Ty, Addr, Reg);
+  emitIASBytes(Str, Asm, StartPosition);
+}
+
 void InstX8632Xadd::dump(const Cfg *Func) const {
   Ostream &Str = Func->getContext()->getStrDump();
   if (Locked) {
@@ -1592,6 +1690,22 @@
   Str << "\n";
 }
 
+void InstX8632Xchg::emitIAS(const Cfg *Func) const {
+  Ostream &Str = Func->getContext()->getStrEmit();
+  assert(getSrcSize() == 2);
+  x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>();
+  intptr_t StartPosition = Asm->GetPosition();
+  Type Ty = getSrc(0)->getType();
+  const OperandX8632Mem *Mem = llvm::cast<OperandX8632Mem>(getSrc(0));
+  const x86::Address Addr = Mem->toAsmAddress(Asm);
+  const Variable *VarReg = llvm::cast<Variable>(getSrc(1));
+  assert(VarReg->hasReg());
+  const RegX8632::GPRRegister Reg =
+      RegX8632::getEncodedGPR(VarReg->getRegNum());
+  Asm->xchg(Ty, Addr, Reg);
+  emitIASBytes(Str, Asm, StartPosition);
+}
+
 void InstX8632Xchg::dump(const Cfg *Func) const {
   Ostream &Str = Func->getContext()->getStrDump();
   Type Ty = getSrc(0)->getType();
diff --git a/src/IceInstX8632.h b/src/IceInstX8632.h
index 514c374..facd4f4 100644
--- a/src/IceInstX8632.h
+++ b/src/IceInstX8632.h
@@ -895,6 +895,7 @@
         InstX8632Cmov(Func, Dest, Source, Cond);
   }
   virtual void emit(const Cfg *Func) const;
+  virtual void emitIAS(const Cfg *Func) const;
   virtual void dump(const Cfg *Func) const;
   static bool classof(const Inst *Inst) { return isClassof(Inst, Cmov); }
 
@@ -945,6 +946,7 @@
         InstX8632Cmpxchg(Func, DestOrAddr, Eax, Desired, Locked);
   }
   virtual void emit(const Cfg *Func) const;
+  virtual void emitIAS(const Cfg *Func) const;
   virtual void dump(const Cfg *Func) const;
   static bool classof(const Inst *Inst) { return isClassof(Inst, Cmpxchg); }
 
@@ -964,18 +966,19 @@
 // <m64> must be a memory operand.
 class InstX8632Cmpxchg8b : public InstX8632Lockable {
 public:
-  static InstX8632Cmpxchg8b *create(Cfg *Func, OperandX8632 *Dest,
+  static InstX8632Cmpxchg8b *create(Cfg *Func, OperandX8632Mem *Dest,
                                     Variable *Edx, Variable *Eax, Variable *Ecx,
                                     Variable *Ebx, bool Locked) {
     return new (Func->allocate<InstX8632Cmpxchg8b>())
         InstX8632Cmpxchg8b(Func, Dest, Edx, Eax, Ecx, Ebx, Locked);
   }
   virtual void emit(const Cfg *Func) const;
+  virtual void emitIAS(const Cfg *Func) const;
   virtual void dump(const Cfg *Func) const;
   static bool classof(const Inst *Inst) { return isClassof(Inst, Cmpxchg8b); }
 
 private:
-  InstX8632Cmpxchg8b(Cfg *Func, OperandX8632 *Dest, Variable *Edx,
+  InstX8632Cmpxchg8b(Cfg *Func, OperandX8632Mem *Dest, Variable *Edx,
                      Variable *Eax, Variable *Ecx, Variable *Ebx, bool Locked);
   InstX8632Cmpxchg8b(const InstX8632Cmpxchg8b &) LLVM_DELETED_FUNCTION;
   InstX8632Cmpxchg8b &
@@ -1319,6 +1322,7 @@
         InstX8632Xadd(Func, Dest, Source, Locked);
   }
   virtual void emit(const Cfg *Func) const;
+  virtual void emitIAS(const Cfg *Func) const;
   virtual void dump(const Cfg *Func) const;
   static bool classof(const Inst *Inst) { return isClassof(Inst, Xadd); }
 
@@ -1342,6 +1346,7 @@
         InstX8632Xchg(Func, Dest, Source);
   }
   virtual void emit(const Cfg *Func) const;
+  virtual void emitIAS(const Cfg *Func) const;
   virtual void dump(const Cfg *Func) const;
   static bool classof(const Inst *Inst) { return isClassof(Inst, Xchg); }
 
@@ -1378,6 +1383,8 @@
 template <> void InstX8632Sqrtss::emit(const Cfg *Func) const;
 template <> void InstX8632Subss::emit(const Cfg *Func) const;
 
+template <> void InstX8632Cbwdq::emitIAS(const Cfg *Func) const;
+
 } // end of namespace Ice
 
 #endif // SUBZERO_SRC_ICEINSTX8632_H
diff --git a/src/IceTargetLoweringX8632.h b/src/IceTargetLoweringX8632.h
index 71062cc..f5bd300 100644
--- a/src/IceTargetLoweringX8632.h
+++ b/src/IceTargetLoweringX8632.h
@@ -250,7 +250,7 @@
     Context.insert(
         InstFakeDef::create(Func, Eax, llvm::dyn_cast<Variable>(DestOrAddr)));
   }
-  void _cmpxchg8b(OperandX8632 *Addr, Variable *Edx, Variable *Eax,
+  void _cmpxchg8b(OperandX8632Mem *Addr, Variable *Edx, Variable *Eax,
                   Variable *Ecx, Variable *Ebx, bool Locked) {
     Context.insert(
         InstX8632Cmpxchg8b::create(Func, Addr, Edx, Eax, Ecx, Ebx, Locked));
diff --git a/src/assembler_ia32.cpp b/src/assembler_ia32.cpp
index ceed1d1..3cf9e25 100644
--- a/src/assembler_ia32.cpp
+++ b/src/assembler_ia32.cpp
@@ -1110,12 +1110,6 @@
   EmitUint8(0xF7);
 }
 
-void AssemblerX86::xchgl(GPRRegister dst, GPRRegister src) {
-  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
-  EmitUint8(0x87);
-  EmitRegisterOperand(dst, src);
-}
-
 void AssemblerX86::cmpl(GPRRegister reg, const Immediate &imm) {
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitComplex(7, Operand(reg), imm);
@@ -1307,6 +1301,18 @@
   EmitOperand(reg, address);
 }
 
+void AssemblerX86::cbw() {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitOperandSizeOverride();
+  EmitUint8(0x98);
+}
+
+void AssemblerX86::cwd() {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitOperandSizeOverride();
+  EmitUint8(0x99);
+}
+
 void AssemblerX86::cdq() {
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitUint8(0x99);
@@ -1674,11 +1680,46 @@
   EmitUint8(0xF0);
 }
 
-void AssemblerX86::cmpxchgl(const Address &address, GPRRegister reg) {
+void AssemblerX86::cmpxchg(Type Ty, const Address &address, GPRRegister reg) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  if (Ty == IceType_i16)
+    EmitOperandSizeOverride();
+  EmitUint8(0x0F);
+  if (Ty == IceType_i8 || Ty == IceType_i1)
+    EmitUint8(0xB0);
+  else
+    EmitUint8(0xB1);
+  EmitOperand(reg, address);
+}
+
+void AssemblerX86::cmpxchg8b(const Address &address) {
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitUint8(0x0F);
-  EmitUint8(0xB1);
-  EmitOperand(reg, address);
+  EmitUint8(0xC7);
+  EmitOperand(1, address);
+}
+
+void AssemblerX86::xadd(Type Ty, const Address &addr, GPRRegister reg) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  if (Ty == IceType_i16)
+    EmitOperandSizeOverride();
+  EmitUint8(0x0F);
+  if (Ty == IceType_i8 || Ty == IceType_i1)
+    EmitUint8(0xC0);
+  else
+    EmitUint8(0xC1);
+  EmitOperand(reg, addr);
+}
+
+void AssemblerX86::xchg(Type Ty, const Address &addr, GPRRegister reg) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  if (Ty == IceType_i16)
+    EmitOperandSizeOverride();
+  if (Ty == IceType_i8 || Ty == IceType_i1)
+    EmitUint8(0x86);
+  else
+    EmitUint8(0x87);
+  EmitOperand(reg, addr);
 }
 
 void AssemblerX86::Align(intptr_t alignment, intptr_t offset) {
diff --git a/src/assembler_ia32.h b/src/assembler_ia32.h
index 810fab3..6192e91 100644
--- a/src/assembler_ia32.h
+++ b/src/assembler_ia32.h
@@ -541,8 +541,6 @@
 
   void fincstp();
 
-  void xchgl(GPRRegister dst, GPRRegister src);
-
   void cmpl(GPRRegister reg, const Immediate &imm);
   void cmpl(GPRRegister reg0, GPRRegister reg1);
   void cmpl(GPRRegister reg, const Address &address);
@@ -582,6 +580,8 @@
   void subl(GPRRegister reg, const Address &address);
   void subl(const Address &address, GPRRegister reg);
 
+  void cbw();
+  void cwd();
   void cdq();
 
   void idivl(GPRRegister reg);
@@ -645,11 +645,14 @@
   void jmp(const ConstantRelocatable *label);
 
   void lock();
-  void cmpxchgl(const Address &address, GPRRegister reg);
+  void cmpxchg(Type Ty, const Address &address, GPRRegister reg);
+  void cmpxchg8b(const Address &address);
+  void xadd(Type Ty, const Address &address, GPRRegister reg);
+  void xchg(Type Ty, const Address &address, GPRRegister reg);
 
-  void LockCmpxchgl(const Address &address, GPRRegister reg) {
+  void LockCmpxchg(Type Ty, const Address &address, GPRRegister reg) {
     lock();
-    cmpxchgl(address, reg);
+    cmpxchg(Ty, address, reg);
   }
 
   intptr_t PreferredLoopAlignment() { return 16; }