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