diff --git a/Source/Core/Common/x64Emitter.cpp b/Source/Core/Common/x64Emitter.cpp index 38e957d7b7..1beeec3824 100644 --- a/Source/Core/Common/x64Emitter.cpp +++ b/Source/Core/Common/x64Emitter.cpp @@ -1552,10 +1552,10 @@ void XEmitter::MOVSD(X64Reg regOp, OpArg arg) {WriteSSEOp(0xF2, sseMOVUPfromRM void XEmitter::MOVSS(OpArg arg, X64Reg regOp) {WriteSSEOp(0xF3, sseMOVUPtoRM, regOp, arg);} void XEmitter::MOVSD(OpArg arg, X64Reg regOp) {WriteSSEOp(0xF2, sseMOVUPtoRM, regOp, arg);} -void XEmitter::MOVLPD(X64Reg regOp, OpArg arg) {WriteSSEOp(0xF2, sseMOVLPDfromRM, regOp, arg);} -void XEmitter::MOVHPD(X64Reg regOp, OpArg arg) {WriteSSEOp(0xF2, sseMOVHPDfromRM, regOp, arg);} -void XEmitter::MOVLPD(OpArg arg, X64Reg regOp) {WriteSSEOp(0xF2, sseMOVLPDtoRM, regOp, arg);} -void XEmitter::MOVHPD(OpArg arg, X64Reg regOp) {WriteSSEOp(0xF2, sseMOVHPDtoRM, regOp, arg);} +void XEmitter::MOVLPD(X64Reg regOp, OpArg arg) {WriteSSEOp(0x66, sseMOVLPfromRM, regOp, arg);} +void XEmitter::MOVHPD(X64Reg regOp, OpArg arg) {WriteSSEOp(0x66, sseMOVHPfromRM, regOp, arg);} +void XEmitter::MOVLPD(OpArg arg, X64Reg regOp) {WriteSSEOp(0x66, sseMOVLPtoRM, regOp, arg);} +void XEmitter::MOVHPD(OpArg arg, X64Reg regOp) {WriteSSEOp(0x66, sseMOVHPtoRM, regOp, arg);} void XEmitter::MOVHLPS(X64Reg regOp1, X64Reg regOp2) {WriteSSEOp(0x00, sseMOVHLPS, regOp1, R(regOp2));} void XEmitter::MOVLHPS(X64Reg regOp1, X64Reg regOp2) {WriteSSEOp(0x00, sseMOVLHPS, regOp1, R(regOp2));} diff --git a/Source/UnitTests/Common/x64EmitterTest.cpp b/Source/UnitTests/Common/x64EmitterTest.cpp index 83a3741e7f..a6b6a7e81a 100644 --- a/Source/UnitTests/Common/x64EmitterTest.cpp +++ b/Source/UnitTests/Common/x64EmitterTest.cpp @@ -728,9 +728,42 @@ TWO_OP_SSE_TEST(UCOMISS, "dword") TWO_OP_SSE_TEST(COMISD, "qword") TWO_OP_SSE_TEST(UCOMISD, "qword") +// register-only instructions +#define TWO_OP_SSE_REG_TEST(Name, MemBits) \ + TEST_F(x64EmitterTest, Name) \ + { \ + for (const auto& r1 : xmmnames) \ + { \ + for (const auto& r2 : xmmnames) \ + { \ + emitter->Name(r1.reg, r2.reg); \ + ExpectDisassembly(#Name " " + r1.name + ", " + r2.name); \ + } \ + } \ + } + +TWO_OP_SSE_REG_TEST(MOVHLPS, "qword") +TWO_OP_SSE_REG_TEST(MOVLHPS, "qword") + +// "register + memory"-only instructions +#define TWO_OP_SSE_MEM_TEST(Name, MemBits) \ + TEST_F(x64EmitterTest, Name) \ + { \ + for (const auto& r1 : xmmnames) \ + { \ + emitter->Name(r1.reg, MatR(R12)); \ + ExpectDisassembly(#Name " " + r1.name + ", " MemBits " ptr ds:[r12]"); \ + emitter->Name(MatR(R12), r1.reg); \ + ExpectDisassembly(#Name " " MemBits " ptr ds:[r12], " + r1.name); \ + } \ + } + +TWO_OP_SSE_MEM_TEST(MOVLPD, "qword") +TWO_OP_SSE_MEM_TEST(MOVHPD, "qword") + // TODO: CMPSS/SD // TODO: SHUFPS/PD -// TODO: SSE MOVs +// TODO: more SSE MOVs // TODO: MOVMSK TEST_F(x64EmitterTest, MASKMOVDQU)