x64Emitter: add MOVSLDUP/MOVSHDUP

This commit is contained in:
Tillmann Karras 2015-08-04 23:22:13 +02:00
parent f5a10bddee
commit 439fb26b9b
3 changed files with 35 additions and 5 deletions

View File

@ -1636,22 +1636,47 @@ void XEmitter::MOVMSKPD(X64Reg dest, const OpArg& arg) {WriteSSEOp(0x66, 0x50, d
void XEmitter::LDDQU(X64Reg dest, const OpArg& arg) {WriteSSEOp(0xF2, sseLDDQU, dest, arg);} // For integer data only void XEmitter::LDDQU(X64Reg dest, const OpArg& arg) {WriteSSEOp(0xF2, sseLDDQU, dest, arg);} // For integer data only
// THESE TWO ARE UNTESTED.
void XEmitter::UNPCKLPS(X64Reg dest, const OpArg& arg) {WriteSSEOp(0x00, 0x14, dest, arg);} void XEmitter::UNPCKLPS(X64Reg dest, const OpArg& arg) {WriteSSEOp(0x00, 0x14, dest, arg);}
void XEmitter::UNPCKHPS(X64Reg dest, const OpArg& arg) {WriteSSEOp(0x00, 0x15, dest, arg);} void XEmitter::UNPCKHPS(X64Reg dest, const OpArg& arg) {WriteSSEOp(0x00, 0x15, dest, arg);}
void XEmitter::UNPCKLPD(X64Reg dest, const OpArg& arg) {WriteSSEOp(0x66, 0x14, dest, arg);} void XEmitter::UNPCKLPD(X64Reg dest, const OpArg& arg) {WriteSSEOp(0x66, 0x14, dest, arg);}
void XEmitter::UNPCKHPD(X64Reg dest, const OpArg& arg) {WriteSSEOp(0x66, 0x15, dest, arg);} void XEmitter::UNPCKHPD(X64Reg dest, const OpArg& arg) {WriteSSEOp(0x66, 0x15, dest, arg);}
// Pretty much every x86 CPU nowadays supports SSE3,
// but the SSE2 fallbacks are easy.
void XEmitter::MOVSLDUP(X64Reg regOp, const OpArg& arg)
{
if (cpu_info.bSSE3)
{
WriteSSEOp(0xF3, 0x12, regOp, arg);
}
else
{
if (!arg.IsSimpleReg(regOp))
MOVAPD(regOp, arg);
UNPCKLPS(regOp, R(regOp));
}
}
void XEmitter::MOVSHDUP(X64Reg regOp, const OpArg& arg)
{
if (cpu_info.bSSE3)
{
WriteSSEOp(0xF3, 0x16, regOp, arg);
}
else
{
if (!arg.IsSimpleReg(regOp))
MOVAPD(regOp, arg);
UNPCKHPS(regOp, R(regOp));
}
}
void XEmitter::MOVDDUP(X64Reg regOp, const OpArg& arg) void XEmitter::MOVDDUP(X64Reg regOp, const OpArg& arg)
{ {
if (cpu_info.bSSE3) if (cpu_info.bSSE3)
{ {
WriteSSEOp(0xF2, 0x12, regOp, arg); //SSE3 movddup WriteSSEOp(0xF2, 0x12, regOp, arg);
} }
else else
{ {
// Simulate this instruction with SSE2 instructions
if (!arg.IsSimpleReg(regOp)) if (!arg.IsSimpleReg(regOp))
MOVSD(regOp, arg); MOVSD(regOp, arg);
UNPCKLPD(regOp, R(regOp)); UNPCKLPD(regOp, R(regOp));

View File

@ -581,9 +581,12 @@ public:
void SHUFPS(X64Reg regOp, const OpArg& arg, u8 shuffle); void SHUFPS(X64Reg regOp, const OpArg& arg, u8 shuffle);
void SHUFPD(X64Reg regOp, const OpArg& arg, u8 shuffle); void SHUFPD(X64Reg regOp, const OpArg& arg, u8 shuffle);
// SSE/SSE2: Useful alternative to shuffle in some cases. // SSE3
void MOVSLDUP(X64Reg regOp, const OpArg& arg);
void MOVSHDUP(X64Reg regOp, const OpArg& arg);
void MOVDDUP(X64Reg regOp, const OpArg& arg); void MOVDDUP(X64Reg regOp, const OpArg& arg);
// SSE/SSE2: Useful alternative to shuffle in some cases.
void UNPCKLPS(X64Reg dest, const OpArg& src); void UNPCKLPS(X64Reg dest, const OpArg& src);
void UNPCKHPS(X64Reg dest, const OpArg& src); void UNPCKHPS(X64Reg dest, const OpArg& src);
void UNPCKLPD(X64Reg dest, const OpArg& src); void UNPCKLPD(X64Reg dest, const OpArg& src);

View File

@ -721,6 +721,8 @@ TWO_OP_SSE_TEST(ANDNPD, "dqword")
TWO_OP_SSE_TEST(ORPD, "dqword") TWO_OP_SSE_TEST(ORPD, "dqword")
TWO_OP_SSE_TEST(XORPD, "dqword") TWO_OP_SSE_TEST(XORPD, "dqword")
TWO_OP_SSE_TEST(MOVSLDUP, "dqword")
TWO_OP_SSE_TEST(MOVSHDUP, "dqword")
TWO_OP_SSE_TEST(MOVDDUP, "qword") TWO_OP_SSE_TEST(MOVDDUP, "qword")
TWO_OP_SSE_TEST(UNPCKLPS, "dqword") TWO_OP_SSE_TEST(UNPCKLPS, "dqword")