Commit 699bf02c by Jan Voung

emitIAS for cvtt?.*2.*

BUG=none R=stichnot@chromium.org Review URL: https://codereview.chromium.org/640603002
parent 2a063e2b
......@@ -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 << " ";
......
......@@ -1109,18 +1109,21 @@ private:
// operand needs to be done separately.
class InstX8632Cvt : public InstX8632 {
public:
enum CvtVariant { Si2ss, Tss2si, Float2float, Dq2ps, Tps2dq };
static InstX8632Cvt *create(Cfg *Func, Variable *Dest, Operand *Source,
bool Trunc) {
CvtVariant Variant) {
return new (Func->allocate<InstX8632Cvt>())
InstX8632Cvt(Func, Dest, Source, Trunc);
InstX8632Cvt(Func, Dest, Source, Variant);
}
void emit(const Cfg *Func) const override;
void emitIAS(const Cfg *Func) const override;
void dump(const Cfg *Func) const override;
static bool classof(const Inst *Inst) { return isClassof(Inst, Cvt); }
bool isTruncating() const { return Variant == Tss2si || Variant == Tps2dq; }
private:
bool Trunc;
InstX8632Cvt(Cfg *Func, Variable *Dest, Operand *Source, bool Trunc);
CvtVariant Variant;
InstX8632Cvt(Cfg *Func, Variable *Dest, Operand *Source, CvtVariant Variant);
InstX8632Cvt(const InstX8632Cvt &) = delete;
InstX8632Cvt &operator=(const InstX8632Cvt &) = delete;
~InstX8632Cvt() override {}
......
......@@ -2058,7 +2058,7 @@ void TargetX8632::lowerCast(const InstCast *Inst) {
Operand *Src0RM = legalize(Inst->getSrc(0), Legal_Reg | Legal_Mem);
// t1 = cvt Src0RM; Dest = t1
Variable *T = makeReg(Dest->getType());
_cvt(T, Src0RM);
_cvt(T, Src0RM, InstX8632Cvt::Float2float);
_mov(Dest, T);
break;
}
......@@ -2068,7 +2068,7 @@ void TargetX8632::lowerCast(const InstCast *Inst) {
Inst->getSrc(0)->getType() == IceType_v4f32);
Operand *Src0RM = legalize(Inst->getSrc(0), Legal_Reg | Legal_Mem);
Variable *T = makeReg(Dest->getType());
_cvtt(T, Src0RM);
_cvt(T, Src0RM, InstX8632Cvt::Tps2dq);
_movp(Dest, T);
} else if (Dest->getType() == IceType_i64) {
// Use a helper for converting floating-point values to 64-bit
......@@ -2091,7 +2091,7 @@ void TargetX8632::lowerCast(const InstCast *Inst) {
// t1.i32 = cvt Src0RM; t2.dest_type = t1; Dest = t2.dest_type
Variable *T_1 = makeReg(IceType_i32);
Variable *T_2 = makeReg(Dest->getType());
_cvtt(T_1, Src0RM);
_cvt(T_1, Src0RM, InstX8632Cvt::Tss2si);
_mov(T_2, T_1); // T_1 and T_2 may have different integer types
if (Dest->getType() == IceType_i1)
_and(T_2, Ctx->getConstantInt32(IceType_i1, 1));
......@@ -2127,7 +2127,7 @@ void TargetX8632::lowerCast(const InstCast *Inst) {
// t1.i32 = cvt Src0RM; t2.dest_type = t1; Dest = t2.dest_type
Variable *T_1 = makeReg(IceType_i32);
Variable *T_2 = makeReg(Dest->getType());
_cvtt(T_1, Src0RM);
_cvt(T_1, Src0RM, InstX8632Cvt::Tss2si);
_mov(T_2, T_1); // T_1 and T_2 may have different integer types
if (Dest->getType() == IceType_i1)
_and(T_2, Ctx->getConstantInt32(IceType_i1, 1));
......@@ -2140,7 +2140,7 @@ void TargetX8632::lowerCast(const InstCast *Inst) {
Inst->getSrc(0)->getType() == IceType_v4i32);
Operand *Src0RM = legalize(Inst->getSrc(0), Legal_Reg | Legal_Mem);
Variable *T = makeReg(Dest->getType());
_cvt(T, Src0RM);
_cvt(T, Src0RM, InstX8632Cvt::Dq2ps);
_movp(Dest, T);
} else if (Inst->getSrc(0)->getType() == IceType_i64) {
// Use a helper for x86-32.
......@@ -2163,7 +2163,7 @@ void TargetX8632::lowerCast(const InstCast *Inst) {
_mov(T_1, Src0RM);
else
_movsx(T_1, Src0RM);
_cvt(T_2, T_1);
_cvt(T_2, T_1, InstX8632Cvt::Si2ss);
_mov(Dest, T_2);
}
break;
......@@ -2202,7 +2202,7 @@ void TargetX8632::lowerCast(const InstCast *Inst) {
_mov(T_1, Src0RM);
else
_movzx(T_1, Src0RM);
_cvt(T_2, T_1);
_cvt(T_2, T_1, InstX8632Cvt::Si2ss);
_mov(Dest, T_2);
}
break;
......
......@@ -256,13 +256,8 @@ protected:
Context.insert(InstFakeDef::create(Func, Edx));
Context.insert(InstFakeDef::create(Func, Eax));
}
void _cvt(Variable *Dest, Operand *Src0) {
const bool Trunc = false;
Context.insert(InstX8632Cvt::create(Func, Dest, Src0, Trunc));
}
void _cvtt(Variable *Dest, Operand *Src0) {
const bool Trunc = true;
Context.insert(InstX8632Cvt::create(Func, Dest, Src0, Trunc));
void _cvt(Variable *Dest, Operand *Src0, InstX8632Cvt::CvtVariant Variant) {
Context.insert(InstX8632Cvt::create(Func, Dest, Src0, Variant));
}
void _div(Variable *Dest, Operand *Src0, Operand *Src1) {
Context.insert(InstX8632Div::create(Func, Dest, Src0, Src1));
......
......@@ -948,21 +948,6 @@ void AssemblerX86::sqrtpd(XmmRegister dst) {
EmitXmmRegisterOperand(dst, dst);
}
void AssemblerX86::cvtps2pd(XmmRegister dst, XmmRegister src) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
EmitUint8(0x0F);
EmitUint8(0x5A);
EmitXmmRegisterOperand(dst, src);
}
void AssemblerX86::cvtpd2ps(XmmRegister dst, XmmRegister src) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
EmitUint8(0x66);
EmitUint8(0x0F);
EmitUint8(0x5A);
EmitXmmRegisterOperand(dst, src);
}
void AssemblerX86::shufpd(XmmRegister dst, XmmRegister src,
const Immediate &imm) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
......@@ -974,78 +959,91 @@ void AssemblerX86::shufpd(XmmRegister dst, XmmRegister src,
EmitUint8(imm.value());
}
void AssemblerX86::cvtsi2ss(XmmRegister dst, GPRRegister src) {
void AssemblerX86::cvtdq2ps(Type /* Ignore */, XmmRegister dst,
XmmRegister src) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
EmitUint8(0xF3);
EmitUint8(0x0F);
EmitUint8(0x2A);
EmitOperand(dst, Operand(src));
EmitUint8(0x5B);
EmitXmmRegisterOperand(dst, src);
}
void AssemblerX86::cvtsi2sd(XmmRegister dst, GPRRegister src) {
void AssemblerX86::cvtdq2ps(Type /* Ignore */, XmmRegister dst,
const Address &src) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
EmitUint8(0xF2);
EmitUint8(0x0F);
EmitUint8(0x2A);
EmitOperand(dst, Operand(src));
EmitUint8(0x5B);
EmitOperand(dst, src);
}
void AssemblerX86::cvtss2si(GPRRegister dst, XmmRegister src) {
void AssemblerX86::cvttps2dq(Type /* Ignore */, XmmRegister dst,
XmmRegister src) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
EmitUint8(0xF3);
EmitUint8(0x0F);
EmitUint8(0x2D);
EmitUint8(0x5B);
EmitXmmRegisterOperand(dst, src);
}
void AssemblerX86::cvtss2sd(XmmRegister dst, XmmRegister src) {
void AssemblerX86::cvttps2dq(Type /* Ignore */, XmmRegister dst,
const Address &src) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
EmitUint8(0xF3);
EmitUint8(0x0F);
EmitUint8(0x5A);
EmitXmmRegisterOperand(dst, src);
EmitUint8(0x5B);
EmitOperand(dst, src);
}
void AssemblerX86::cvtsd2si(GPRRegister dst, XmmRegister src) {
void AssemblerX86::cvtsi2ss(Type DestTy, XmmRegister dst, GPRRegister src) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
EmitUint8(0xF2);
EmitUint8(isFloat32Asserting32Or64(DestTy) ? 0xF3 : 0xF2);
EmitUint8(0x0F);
EmitUint8(0x2D);
EmitXmmRegisterOperand(dst, src);
EmitUint8(0x2A);
EmitRegisterOperand(dst, src);
}
void AssemblerX86::cvttss2si(GPRRegister dst, XmmRegister src) {
void AssemblerX86::cvtsi2ss(Type DestTy, XmmRegister dst, const Address &src) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
EmitUint8(0xF3);
EmitUint8(isFloat32Asserting32Or64(DestTy) ? 0xF3 : 0xF2);
EmitUint8(0x0F);
EmitUint8(0x2C);
EmitXmmRegisterOperand(dst, src);
EmitUint8(0x2A);
EmitOperand(dst, src);
}
void AssemblerX86::cvttsd2si(GPRRegister dst, XmmRegister src) {
void AssemblerX86::cvtfloat2float(Type SrcTy, XmmRegister dst,
XmmRegister src) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
EmitUint8(0xF2);
// ss2sd or sd2ss
EmitUint8(isFloat32Asserting32Or64(SrcTy) ? 0xF3 : 0xF2);
EmitUint8(0x0F);
EmitUint8(0x2C);
EmitUint8(0x5A);
EmitXmmRegisterOperand(dst, src);
}
void AssemblerX86::cvtsd2ss(XmmRegister dst, XmmRegister src) {
void AssemblerX86::cvtfloat2float(Type SrcTy, XmmRegister dst,
const Address &src) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
EmitUint8(0xF2);
EmitUint8(isFloat32Asserting32Or64(SrcTy) ? 0xF3 : 0xF2);
EmitUint8(0x0F);
EmitUint8(0x5A);
EmitXmmRegisterOperand(dst, src);
EmitOperand(dst, src);
}
void AssemblerX86::cvtdq2pd(XmmRegister dst, XmmRegister src) {
void AssemblerX86::cvttss2si(Type SrcTy, GPRRegister dst, XmmRegister src) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
EmitUint8(0xF3);
EmitUint8(isFloat32Asserting32Or64(SrcTy) ? 0xF3 : 0xF2);
EmitUint8(0x0F);
EmitUint8(0xE6);
EmitUint8(0x2C);
EmitXmmRegisterOperand(dst, src);
}
void AssemblerX86::cvttss2si(Type SrcTy, GPRRegister dst, const Address &src) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
EmitUint8(isFloat32Asserting32Or64(SrcTy) ? 0xF3 : 0xF2);
EmitUint8(0x0F);
EmitUint8(0x2C);
EmitOperand(dst, src);
}
void AssemblerX86::ucomiss(Type Ty, XmmRegister a, XmmRegister b) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
if (Ty == IceType_f64)
......
......@@ -397,6 +397,15 @@ public:
TypedEmitXmmImm XmmImm;
};
// Cross Xmm/GPR cast instructions.
template <typename DReg_t, typename SReg_t> struct CastEmitterRegOp {
typedef void (AssemblerX86::*TypedEmitRegs)(Type, DReg_t, SReg_t);
typedef void (AssemblerX86::*TypedEmitAddr)(Type, DReg_t, const Address &);
TypedEmitRegs RegReg;
TypedEmitAddr RegAddr;
};
/*
* Emit Machine Instructions.
*/
......@@ -537,23 +546,22 @@ public:
void minpd(XmmRegister dst, XmmRegister src);
void maxpd(XmmRegister dst, XmmRegister src);
void sqrtpd(XmmRegister dst);
void cvtps2pd(XmmRegister dst, XmmRegister src);
void cvtpd2ps(XmmRegister dst, XmmRegister src);
void shufpd(XmmRegister dst, XmmRegister src, const Immediate &mask);
void cvtsi2ss(XmmRegister dst, GPRRegister src);
void cvtsi2sd(XmmRegister dst, GPRRegister src);
void cvtdq2ps(Type, XmmRegister dst, XmmRegister src);
void cvtdq2ps(Type, XmmRegister dst, const Address &src);
void cvtss2si(GPRRegister dst, XmmRegister src);
void cvtss2sd(XmmRegister dst, XmmRegister src);
void cvttps2dq(Type, XmmRegister dst, XmmRegister src);
void cvttps2dq(Type, XmmRegister dst, const Address &src);
void cvtsd2si(GPRRegister dst, XmmRegister src);
void cvtsd2ss(XmmRegister dst, XmmRegister src);
void cvtsi2ss(Type DestTy, XmmRegister dst, GPRRegister src);
void cvtsi2ss(Type DestTy, XmmRegister dst, const Address &src);
void cvttss2si(GPRRegister dst, XmmRegister src);
void cvttsd2si(GPRRegister dst, XmmRegister src);
void cvtfloat2float(Type SrcTy, XmmRegister dst, XmmRegister src);
void cvtfloat2float(Type SrcTy, XmmRegister dst, const Address &src);
void cvtdq2pd(XmmRegister dst, XmmRegister src);
void cvttss2si(Type SrcTy, GPRRegister dst, XmmRegister src);
void cvttss2si(Type SrcTy, GPRRegister dst, const Address &src);
void ucomiss(Type Ty, XmmRegister a, XmmRegister b);
void ucomiss(Type Ty, XmmRegister a, const Address &b);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment