Index: src/IceInstX8632.cpp |
diff --git a/src/IceInstX8632.cpp b/src/IceInstX8632.cpp |
index ab323350e5649774e8ff46e0e47e4a1997c375f8..8930a17a634df5632b8f8d914d0b0fef059c2356 100644 |
--- a/src/IceInstX8632.cpp |
+++ b/src/IceInstX8632.cpp |
@@ -536,6 +536,65 @@ void emitIASRegOpTyGPR(const Cfg *Func, Type Ty, const Variable *Var, |
emitIASBytes(Str, Asm, StartPosition); |
} |
+void emitIASGPRShift(const Cfg *Func, Type Ty, const Variable *Var, |
+ const Operand *Src, |
+ const x86::AssemblerX86::GPREmitterShiftOp &Emitter) { |
+ x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
+ intptr_t StartPosition = Asm->GetPosition(); |
+ // Technically, the Dest Var can be mem as well, but we only use Reg. |
+ // We can extend this to check Dest if we decide to use that form. |
+ assert(Var->hasReg()); |
+ // We cheat a little and use GPRRegister even for byte operations. |
+ RegX8632::GPRRegister VarReg = |
+ RegX8632::getEncodedByteRegOrGPR(Ty, Var->getRegNum()); |
+ // Src must be reg == ECX or an Imm8. |
+ // This is asserted by the assembler. |
+ if (const Variable *SrcVar = llvm::dyn_cast<Variable>(Src)) { |
+ assert(SrcVar->hasReg()); |
+ RegX8632::GPRRegister SrcReg = |
+ RegX8632::getEncodedByteRegOrGPR(Ty, SrcVar->getRegNum()); |
+ (Asm->*(Emitter.GPRGPR))(Ty, VarReg, SrcReg); |
+ } else if (const ConstantInteger32 *Imm = |
+ llvm::dyn_cast<ConstantInteger32>(Src)) { |
+ (Asm->*(Emitter.GPRImm))(Ty, VarReg, x86::Immediate(Imm->getValue())); |
+ } else { |
+ llvm_unreachable("Unexpected operand type"); |
+ } |
+ Ostream &Str = Func->getContext()->getStrEmit(); |
+ emitIASBytes(Str, Asm, StartPosition); |
+} |
+ |
+void emitIASXmmShift(const Cfg *Func, Type Ty, const Variable *Var, |
+ const Operand *Src, |
+ const x86::AssemblerX86::XmmEmitterShiftOp &Emitter) { |
+ x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
+ intptr_t StartPosition = Asm->GetPosition(); |
+ assert(Var->hasReg()); |
+ RegX8632::XmmRegister VarReg = RegX8632::getEncodedXmm(Var->getRegNum()); |
+ if (const Variable *SrcVar = llvm::dyn_cast<Variable>(Src)) { |
+ if (SrcVar->hasReg()) { |
+ RegX8632::XmmRegister SrcReg = |
+ RegX8632::getEncodedXmm(SrcVar->getRegNum()); |
+ (Asm->*(Emitter.XmmXmm))(Ty, VarReg, SrcReg); |
+ } else { |
+ x86::Address SrcStackAddr = static_cast<TargetX8632 *>(Func->getTarget()) |
+ ->stackVarToAsmOperand(SrcVar); |
+ (Asm->*(Emitter.XmmAddr))(Ty, VarReg, SrcStackAddr); |
+ } |
+ } else if (const OperandX8632Mem *Mem = |
+ llvm::dyn_cast<OperandX8632Mem>(Src)) { |
+ x86::Address SrcAddr = Mem->toAsmAddress(Asm); |
+ (Asm->*(Emitter.XmmAddr))(Ty, VarReg, SrcAddr); |
+ } else if (const ConstantInteger32 *Imm = |
+ llvm::dyn_cast<ConstantInteger32>(Src)) { |
+ (Asm->*(Emitter.XmmImm))(Ty, VarReg, x86::Immediate(Imm->getValue())); |
+ } else { |
+ llvm_unreachable("Unexpected operand type"); |
+ } |
+ Ostream &Str = Func->getContext()->getStrEmit(); |
+ emitIASBytes(Str, Asm, StartPosition); |
+} |
+ |
void |
emitIASVarOperandTyXMM(const Cfg *Func, Type Ty, const Variable *Var, |
const Operand *Src, |
@@ -691,6 +750,20 @@ template <> |
const x86::AssemblerX86::GPREmitterRegOp InstX8632Xor::Emitter = { |
&x86::AssemblerX86::Xor, &x86::AssemblerX86::Xor, &x86::AssemblerX86::Xor}; |
+// Binary Shift GPR ops |
+template <> |
+const x86::AssemblerX86::GPREmitterShiftOp InstX8632Rol::Emitter = { |
+ &x86::AssemblerX86::rol, &x86::AssemblerX86::rol}; |
+template <> |
+const x86::AssemblerX86::GPREmitterShiftOp InstX8632Sar::Emitter = { |
+ &x86::AssemblerX86::sar, &x86::AssemblerX86::sar}; |
+template <> |
+const x86::AssemblerX86::GPREmitterShiftOp InstX8632Shl::Emitter = { |
+ &x86::AssemblerX86::shl, &x86::AssemblerX86::shl}; |
+template <> |
+const x86::AssemblerX86::GPREmitterShiftOp InstX8632Shr::Emitter = { |
+ &x86::AssemblerX86::shr, &x86::AssemblerX86::shr}; |
+ |
// Binary XMM ops |
template <> |
const x86::AssemblerX86::XmmEmitterTwoOps InstX8632Addss::Emitter = { |
@@ -726,6 +799,9 @@ template <> |
const x86::AssemblerX86::XmmEmitterTwoOps InstX8632Pcmpgt::Emitter = { |
&x86::AssemblerX86::pcmpgt, &x86::AssemblerX86::pcmpgt, NULL}; |
template <> |
+const x86::AssemblerX86::XmmEmitterTwoOps InstX8632Pmull::Emitter = { |
+ &x86::AssemblerX86::pmull, &x86::AssemblerX86::pmull, NULL}; |
+template <> |
const x86::AssemblerX86::XmmEmitterTwoOps InstX8632Pmuludq::Emitter = { |
&x86::AssemblerX86::pmuludq, &x86::AssemblerX86::pmuludq, NULL}; |
template <> |
@@ -744,6 +820,16 @@ template <> |
const x86::AssemblerX86::XmmEmitterTwoOps InstX8632Subps::Emitter = { |
&x86::AssemblerX86::subps, &x86::AssemblerX86::subps, NULL}; |
+// Binary XMM Shift ops |
+template <> |
+const x86::AssemblerX86::XmmEmitterShiftOp InstX8632Psll::Emitter = { |
+ &x86::AssemblerX86::psll, &x86::AssemblerX86::psll, |
+ &x86::AssemblerX86::psll}; |
+template <> |
+const x86::AssemblerX86::XmmEmitterShiftOp InstX8632Psra::Emitter = { |
+ &x86::AssemblerX86::psra, &x86::AssemblerX86::psra, |
+ &x86::AssemblerX86::psra}; |
+ |
template <> void InstX8632Sqrtss::emit(const Cfg *Func) const { |
Ostream &Str = Func->getContext()->getStrEmit(); |
assert(getSrcSize() == 1); |
@@ -787,6 +873,22 @@ template <> void InstX8632Pmull::emit(const Cfg *Func) const { |
emitTwoAddress(buf, this, Func); |
} |
+template <> void InstX8632Pmull::emitIAS(const Cfg *Func) const { |
+ Type Ty = getDest()->getType(); |
+ bool TypesAreValid = Ty == IceType_v4i32 || Ty == IceType_v8i16; |
+ bool InstructionSetIsValid = |
+ Ty == IceType_v8i16 || |
+ static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= |
+ TargetX8632::SSE4_1; |
+ (void)TypesAreValid; |
+ (void)InstructionSetIsValid; |
+ assert(TypesAreValid); |
+ assert(InstructionSetIsValid); |
+ assert(getSrcSize() == 2); |
+ Type ElementTy = typeElementType(Ty); |
+ emitIASVarOperandTyXMM(Func, ElementTy, getDest(), getSrc(1), Emitter); |
+} |
+ |
template <> void InstX8632Subss::emit(const Cfg *Func) const { |
char buf[30]; |
snprintf(buf, llvm::array_lengthof(buf), "sub%s", |