Index: src/IceInstX8632.cpp |
diff --git a/src/IceInstX8632.cpp b/src/IceInstX8632.cpp |
index e2d39c3ea4b30905e61b7744cf5cb1d065fad131..fd1f80d83e1cbe674cde3d998b240a2669b20a71 100644 |
--- a/src/IceInstX8632.cpp |
+++ b/src/IceInstX8632.cpp |
@@ -230,8 +230,8 @@ InstX8632Cmpxchg8b::InstX8632Cmpxchg8b(Cfg *Func, OperandX8632Mem *Addr, |
} |
InstX8632Cvt::InstX8632Cvt(Cfg *Func, Variable *Dest, Operand *Source, |
- bool Trunc) |
- : InstX8632(Func, InstX8632::Cvt, 1, Dest), Trunc(Trunc) { |
+ CvtVariant Variant) |
+ : InstX8632(Func, InstX8632::Cvt, 1, Dest), Variant(Variant) { |
addSource(Source); |
} |
@@ -647,6 +647,35 @@ void emitIASRegOpTyXMM(const Cfg *Func, Type Ty, const Variable *Var, |
emitIASBytes(Str, Asm, StartPosition); |
} |
+template <typename DReg_t, typename SReg_t, DReg_t (*destEnc)(int32_t), |
+ SReg_t (*srcEnc)(int32_t)> |
+void emitIASCastRegOp( |
+ const Cfg *Func, Type DispatchTy, const Variable *Dest, const Operand *Src, |
+ const x86::AssemblerX86::CastEmitterRegOp<DReg_t, SReg_t> Emitter) { |
+ x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
+ intptr_t StartPosition = Asm->GetPosition(); |
+ assert(Dest->hasReg()); |
+ DReg_t DestReg = destEnc(Dest->getRegNum()); |
+ if (const Variable *SrcVar = llvm::dyn_cast<Variable>(Src)) { |
+ if (SrcVar->hasReg()) { |
+ SReg_t SrcReg = srcEnc(SrcVar->getRegNum()); |
+ (Asm->*(Emitter.RegReg))(DispatchTy, DestReg, SrcReg); |
+ } else { |
+ x86::Address SrcStackAddr = static_cast<TargetX8632 *>(Func->getTarget()) |
+ ->stackVarToAsmOperand(SrcVar); |
+ (Asm->*(Emitter.RegAddr))(DispatchTy, DestReg, SrcStackAddr); |
+ } |
+ } else if (const OperandX8632Mem *Mem = |
+ llvm::dyn_cast<OperandX8632Mem>(Src)) { |
+ x86::Address SrcAddr = Mem->toAsmAddress(Asm); |
+ (Asm->*(Emitter.RegAddr))(DispatchTy, DestReg, SrcAddr); |
+ } else { |
+ llvm_unreachable("Unexpected operand type"); |
+ } |
+ Ostream &Str = Func->getContext()->getStrEmit(); |
+ emitIASBytes(Str, Asm, StartPosition); |
+} |
+ |
void emitIASMovlikeXMM(const Cfg *Func, const Variable *Dest, |
const Operand *Src, |
const x86::AssemblerX86::XmmEmitterMovOps Emitter) { |
@@ -1407,7 +1436,7 @@ void InstX8632Cvt::emit(const Cfg *Func) const { |
Ostream &Str = Func->getContext()->getStrEmit(); |
assert(getSrcSize() == 1); |
Str << "\tcvt"; |
- if (Trunc) |
+ if (isTruncating()) |
Str << "t"; |
Str << TypeX8632Attributes[getSrc(0)->getType()].CvtString << "2" |
<< TypeX8632Attributes[getDest()->getType()].CvtString << "\t"; |
@@ -1417,11 +1446,70 @@ void InstX8632Cvt::emit(const Cfg *Func) const { |
Str << "\n"; |
} |
+void InstX8632Cvt::emitIAS(const Cfg *Func) const { |
+ assert(getSrcSize() == 1); |
+ const Variable *Dest = getDest(); |
+ const Operand *Src = getSrc(0); |
+ Type DestTy = Dest->getType(); |
+ Type SrcTy = Src->getType(); |
+ switch (Variant) { |
+ case Si2ss: { |
+ assert(isScalarIntegerType(SrcTy)); |
+ assert(typeWidthInBytes(SrcTy) <= 4); |
+ assert(isScalarFloatingType(DestTy)); |
+ static const x86::AssemblerX86::CastEmitterRegOp< |
+ RegX8632::XmmRegister, RegX8632::GPRRegister> Emitter = { |
+ &x86::AssemblerX86::cvtsi2ss, &x86::AssemblerX86::cvtsi2ss}; |
+ emitIASCastRegOp<RegX8632::XmmRegister, RegX8632::GPRRegister, |
+ RegX8632::getEncodedXmm, RegX8632::getEncodedGPR>( |
+ Func, DestTy, Dest, Src, Emitter); |
+ return; |
+ } |
+ case Tss2si: { |
+ assert(isScalarFloatingType(SrcTy)); |
+ assert(isScalarIntegerType(DestTy)); |
+ assert(typeWidthInBytes(DestTy) <= 4); |
+ static const x86::AssemblerX86::CastEmitterRegOp< |
+ RegX8632::GPRRegister, RegX8632::XmmRegister> Emitter = { |
+ &x86::AssemblerX86::cvttss2si, &x86::AssemblerX86::cvttss2si}; |
+ emitIASCastRegOp<RegX8632::GPRRegister, RegX8632::XmmRegister, |
+ RegX8632::getEncodedGPR, RegX8632::getEncodedXmm>( |
+ Func, SrcTy, Dest, Src, Emitter); |
+ return; |
+ } |
+ case Float2float: { |
+ assert(isScalarFloatingType(SrcTy)); |
+ assert(isScalarFloatingType(DestTy)); |
+ assert(DestTy != SrcTy); |
+ static const x86::AssemblerX86::XmmEmitterRegOp Emitter = { |
+ &x86::AssemblerX86::cvtfloat2float, &x86::AssemblerX86::cvtfloat2float}; |
+ emitIASRegOpTyXMM(Func, SrcTy, Dest, Src, Emitter); |
+ return; |
+ } |
+ case Dq2ps: { |
+ assert(isVectorIntegerType(SrcTy)); |
+ assert(isVectorFloatingType(DestTy)); |
+ static const x86::AssemblerX86::XmmEmitterRegOp Emitter = { |
+ &x86::AssemblerX86::cvtdq2ps, &x86::AssemblerX86::cvtdq2ps}; |
+ emitIASRegOpTyXMM(Func, DestTy, Dest, Src, Emitter); |
+ return; |
+ } |
+ case Tps2dq: { |
+ assert(isVectorFloatingType(SrcTy)); |
+ assert(isVectorIntegerType(DestTy)); |
+ static const x86::AssemblerX86::XmmEmitterRegOp Emitter = { |
+ &x86::AssemblerX86::cvttps2dq, &x86::AssemblerX86::cvttps2dq}; |
+ emitIASRegOpTyXMM(Func, DestTy, Dest, Src, Emitter); |
+ return; |
+ } |
+ } |
+} |
+ |
void InstX8632Cvt::dump(const Cfg *Func) const { |
Ostream &Str = Func->getContext()->getStrDump(); |
dumpDest(Func); |
Str << " = cvt"; |
- if (Trunc) |
+ if (isTruncating()) |
Str << "t"; |
Str << TypeX8632Attributes[getSrc(0)->getType()].CvtString << "2" |
<< TypeX8632Attributes[getDest()->getType()].CvtString << " "; |