Commit 13cde0f5 by Nicolas Capens Committed by Nicolas Capens

Implement integer vector multiply intrinsics.

BUG=swiftshader:15 Change-Id: Ib822b50c0a14e5ebc114db9759cbeecbb9f7a3c1 Reviewed-on: https://chromium-review.googlesource.com/403472Reviewed-by: 's avatarJim Stichnoth <stichnot@chromium.org> Tested-by: 's avatarNicolas Capens <nicolascapens@google.com>
parent 956cfd60
......@@ -363,6 +363,12 @@ public:
void pandn(Type Ty, XmmRegister dst, const Address &src);
void pmull(Type Ty, XmmRegister dst, XmmRegister src);
void pmull(Type Ty, XmmRegister dst, const Address &src);
void pmulhw(Type Ty, XmmRegister dst, XmmRegister src);
void pmulhw(Type Ty, XmmRegister dst, const Address &src);
void pmulhuw(Type Ty, XmmRegister dst, XmmRegister src);
void pmulhuw(Type Ty, XmmRegister dst, const Address &src);
void pmaddwd(Type Ty, XmmRegister dst, XmmRegister src);
void pmaddwd(Type Ty, XmmRegister dst, const Address &src);
void pmuludq(Type Ty, XmmRegister dst, XmmRegister src);
void pmuludq(Type Ty, XmmRegister dst, const Address &src);
void por(Type Ty, XmmRegister dst, XmmRegister src);
......
......@@ -839,6 +839,87 @@ void AssemblerX86Base<TraitsType>::pmull(Type Ty, XmmRegister dst,
}
template <typename TraitsType>
void AssemblerX86Base<TraitsType>::pmulhw(Type Ty, XmmRegister dst,
XmmRegister src) {
AssemblerBuffer::EnsureCapacity ensured(&Buffer);
emitUint8(0x66);
emitRexRB(RexTypeIrrelevant, dst, src);
emitUint8(0x0F);
assert(Ty == IceType_v8i16);
(void)Ty;
emitUint8(0xE5);
emitXmmRegisterOperand(dst, src);
}
template <typename TraitsType>
void AssemblerX86Base<TraitsType>::pmulhw(Type Ty, XmmRegister dst,
const Address &src) {
AssemblerBuffer::EnsureCapacity ensured(&Buffer);
emitUint8(0x66);
emitAddrSizeOverridePrefix();
emitRex(RexTypeIrrelevant, src, dst);
emitUint8(0x0F);
assert(Ty == IceType_v8i16);
(void)Ty;
emitUint8(0xE5);
emitOperand(gprEncoding(dst), src);
}
template <typename TraitsType>
void AssemblerX86Base<TraitsType>::pmulhuw(Type Ty, XmmRegister dst,
XmmRegister src) {
AssemblerBuffer::EnsureCapacity ensured(&Buffer);
emitUint8(0x66);
emitRexRB(RexTypeIrrelevant, dst, src);
emitUint8(0x0F);
assert(Ty == IceType_v8i16);
(void)Ty;
emitUint8(0xE4);
emitXmmRegisterOperand(dst, src);
}
template <typename TraitsType>
void AssemblerX86Base<TraitsType>::pmulhuw(Type Ty, XmmRegister dst,
const Address &src) {
AssemblerBuffer::EnsureCapacity ensured(&Buffer);
emitUint8(0x66);
emitAddrSizeOverridePrefix();
emitRex(RexTypeIrrelevant, src, dst);
emitUint8(0x0F);
assert(Ty == IceType_v8i16);
(void)Ty;
emitUint8(0xE4);
emitOperand(gprEncoding(dst), src);
}
template <typename TraitsType>
void AssemblerX86Base<TraitsType>::pmaddwd(Type Ty, XmmRegister dst,
XmmRegister src) {
AssemblerBuffer::EnsureCapacity ensured(&Buffer);
emitUint8(0x66);
emitRexRB(RexTypeIrrelevant, dst, src);
emitUint8(0x0F);
assert(Ty == IceType_v8i16);
(void)Ty;
emitUint8(0xF5);
emitXmmRegisterOperand(dst, src);
}
template <typename TraitsType>
void AssemblerX86Base<TraitsType>::pmaddwd(Type Ty, XmmRegister dst,
const Address &src) {
AssemblerBuffer::EnsureCapacity ensured(&Buffer);
emitUint8(0x66);
emitAddrSizeOverridePrefix();
emitRex(RexTypeIrrelevant, src, dst);
emitUint8(0x0F);
assert(Ty == IceType_v8i16);
(void)Ty;
emitUint8(0xF5);
emitOperand(gprEncoding(dst), src);
}
template <typename TraitsType>
void AssemblerX86Base<TraitsType>::pmuludq(Type /* Ty */, XmmRegister dst,
XmmRegister src) {
AssemblerBuffer::EnsureCapacity ensured(&Buffer);
......
......@@ -140,6 +140,9 @@ template <typename TraitsType> struct InstImpl {
Pextr,
Pinsr,
Pmull,
Pmulhw,
Pmulhuw,
Pmaddwd,
Pmuludq,
Pop,
Por,
......@@ -1848,6 +1851,60 @@ template <typename TraitsType> struct InstImpl {
Source) {}
};
class InstX86Pmulhw
: public InstX86BaseBinopXmm<InstX86Base::Pmulhw, false,
InstX86Base::SseSuffix::None> {
public:
static InstX86Pmulhw *create(Cfg *Func, Variable *Dest, Operand *Source) {
assert(Dest->getType() == IceType_v8i16 &&
Source->getType() == IceType_v8i16);
return new (Func->allocate<InstX86Pmulhw>())
InstX86Pmulhw(Func, Dest, Source);
}
private:
InstX86Pmulhw(Cfg *Func, Variable *Dest, Operand *Source)
: InstX86BaseBinopXmm<InstX86Base::Pmulhw, false,
InstX86Base::SseSuffix::None>(Func, Dest,
Source) {}
};
class InstX86Pmulhuw
: public InstX86BaseBinopXmm<InstX86Base::Pmulhuw, false,
InstX86Base::SseSuffix::None> {
public:
static InstX86Pmulhuw *create(Cfg *Func, Variable *Dest, Operand *Source) {
assert(Dest->getType() == IceType_v8i16 &&
Source->getType() == IceType_v8i16);
return new (Func->allocate<InstX86Pmulhuw>())
InstX86Pmulhuw(Func, Dest, Source);
}
private:
InstX86Pmulhuw(Cfg *Func, Variable *Dest, Operand *Source)
: InstX86BaseBinopXmm<InstX86Base::Pmulhuw, false,
InstX86Base::SseSuffix::None>(Func, Dest,
Source) {}
};
class InstX86Pmaddwd
: public InstX86BaseBinopXmm<InstX86Base::Pmaddwd, false,
InstX86Base::SseSuffix::None> {
public:
static InstX86Pmaddwd *create(Cfg *Func, Variable *Dest, Operand *Source) {
assert(Dest->getType() == IceType_v8i16 &&
Source->getType() == IceType_v8i16);
return new (Func->allocate<InstX86Pmaddwd>())
InstX86Pmaddwd(Func, Dest, Source);
}
private:
InstX86Pmaddwd(Cfg *Func, Variable *Dest, Operand *Source)
: InstX86BaseBinopXmm<InstX86Base::Pmaddwd, false,
InstX86Base::SseSuffix::None>(Func, Dest,
Source) {}
};
class InstX86Pmuludq
: public InstX86BaseBinopXmm<InstX86Base::Pmuludq, false,
InstX86Base::SseSuffix::None> {
......@@ -3066,6 +3123,9 @@ template <typename TraitsType> struct Insts {
using Mulps = typename InstImpl<TraitsType>::InstX86Mulps;
using Mulss = typename InstImpl<TraitsType>::InstX86Mulss;
using Pmull = typename InstImpl<TraitsType>::InstX86Pmull;
using Pmulhw = typename InstImpl<TraitsType>::InstX86Pmulhw;
using Pmulhuw = typename InstImpl<TraitsType>::InstX86Pmulhuw;
using Pmaddwd = typename InstImpl<TraitsType>::InstX86Pmaddwd;
using Pmuludq = typename InstImpl<TraitsType>::InstX86Pmuludq;
using Divps = typename InstImpl<TraitsType>::InstX86Divps;
using Divss = typename InstImpl<TraitsType>::InstX86Divss;
......@@ -3291,6 +3351,15 @@ template <typename TraitsType> struct Insts {
const char *InstImpl<TraitsType>::InstX86Pmull::Base::Opcode = "pmull"; \
template <> \
template <> \
const char *InstImpl<TraitsType>::InstX86Pmulhw::Base::Opcode = "pmulhw"; \
template <> \
template <> \
const char *InstImpl<TraitsType>::InstX86Pmulhuw::Base::Opcode = "pmulhuw"; \
template <> \
template <> \
const char *InstImpl<TraitsType>::InstX86Pmaddwd::Base::Opcode = "pmaddwd"; \
template <> \
template <> \
const char *InstImpl<TraitsType>::InstX86Pmuludq::Base::Opcode = "pmuludq"; \
template <> \
template <> \
......@@ -3644,6 +3713,24 @@ template <typename TraitsType> struct Insts {
template <> \
template <> \
const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \
InstImpl<TraitsType>::InstX86Pmulhw::Base::Emitter = { \
&InstImpl<TraitsType>::Assembler::pmulhw, \
&InstImpl<TraitsType>::Assembler::pmulhw}; \
template <> \
template <> \
const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \
InstImpl<TraitsType>::InstX86Pmulhuw::Base::Emitter = { \
&InstImpl<TraitsType>::Assembler::pmulhuw, \
&InstImpl<TraitsType>::Assembler::pmulhuw}; \
template <> \
template <> \
const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \
InstImpl<TraitsType>::InstX86Pmaddwd::Base::Emitter = { \
&InstImpl<TraitsType>::Assembler::pmaddwd, \
&InstImpl<TraitsType>::Assembler::pmaddwd}; \
template <> \
template <> \
const InstImpl<TraitsType>::Assembler::XmmEmitterRegOp \
InstImpl<TraitsType>::InstX86Pmuludq::Base::Emitter = { \
&InstImpl<TraitsType>::Assembler::pmuludq, \
&InstImpl<TraitsType>::Assembler::pmuludq}; \
......
......@@ -1082,8 +1082,7 @@ void InstImpl<TraitsType>::InstX86Sqrt::emit(const Cfg *Func) const {
Type Ty = this->getSrc(0)->getType();
assert(isScalarFloatingType(Ty));
Str << "\t"
"sqrt"
<< Traits::TypeAttributes[Ty].SpSdString << "\t";
"sqrt" << Traits::TypeAttributes[Ty].SpSdString << "\t";
this->getSrc(0)->emit(Func);
Str << ", ";
this->getDest()->emit(Func);
......
......@@ -63,10 +63,13 @@ public:
Trap,
// The intrinsics below are not part of the PNaCl specification.
LoadSubVector,
MultiplyAddPairs,
MultiplyHighSigned,
MultiplyHighUnsigned,
SignMask,
StoreSubVector,
VectorPackSigned,
VectorPackUnsigned,
SignMask
VectorPackUnsigned
};
/// Operations that can be represented by the AtomicRMW intrinsic.
......
......@@ -801,6 +801,18 @@ protected:
AutoMemorySandboxer<> _(this, &Dest, &Src0);
Context.insert<typename Traits::Insts::Pmull>(Dest, Src0);
}
void _pmulhw(Variable *Dest, Operand *Src0) {
AutoMemorySandboxer<> _(this, &Dest, &Src0);
Context.insert<typename Traits::Insts::Pmulhw>(Dest, Src0);
}
void _pmulhuw(Variable *Dest, Operand *Src0) {
AutoMemorySandboxer<> _(this, &Dest, &Src0);
Context.insert<typename Traits::Insts::Pmulhuw>(Dest, Src0);
}
void _pmaddwd(Variable *Dest, Operand *Src0) {
AutoMemorySandboxer<> _(this, &Dest, &Src0);
Context.insert<typename Traits::Insts::Pmaddwd>(Dest, Src0);
}
void _pmuludq(Variable *Dest, Operand *Src0) {
AutoMemorySandboxer<> _(this, &Dest, &Src0);
Context.insert<typename Traits::Insts::Pmuludq>(Dest, Src0);
......
......@@ -4473,6 +4473,42 @@ void TargetX86Base<TraitsType>::lowerIntrinsicCall(
_mov(Dest, T);
return;
}
case Intrinsics::MultiplyHighSigned: {
Operand *Src0 = Instr->getArg(0);
Operand *Src1 = Instr->getArg(1);
Variable *Dest = Instr->getDest();
auto *T = makeReg(Dest->getType());
auto *Src0RM = legalize(Src0, Legal_Reg | Legal_Mem);
auto *Src1RM = legalize(Src1, Legal_Reg | Legal_Mem);
_movp(T, Src0RM);
_pmulhw(T, Src1RM);
_movp(Dest, T);
return;
}
case Intrinsics::MultiplyHighUnsigned: {
Operand *Src0 = Instr->getArg(0);
Operand *Src1 = Instr->getArg(1);
Variable *Dest = Instr->getDest();
auto *T = makeReg(Dest->getType());
auto *Src0RM = legalize(Src0, Legal_Reg | Legal_Mem);
auto *Src1RM = legalize(Src1, Legal_Reg | Legal_Mem);
_movp(T, Src0RM);
_pmulhuw(T, Src1RM);
_movp(Dest, T);
return;
}
case Intrinsics::MultiplyAddPairs: {
Operand *Src0 = Instr->getArg(0);
Operand *Src1 = Instr->getArg(1);
Variable *Dest = Instr->getDest();
auto *T = makeReg(Dest->getType());
auto *Src0RM = legalize(Src0, Legal_Reg | Legal_Mem);
auto *Src1RM = legalize(Src1, Legal_Reg | Legal_Mem);
_movp(T, Src0RM);
_pmaddwd(T, Src1RM);
_movp(Dest, T);
return;
}
default: // UnknownIntrinsic
Func->setError("Unexpected intrinsic");
return;
......
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