From 986d19b9d57d6f5f724a5f21529a046c4ca00831 Mon Sep 17 00:00:00 2001 From: Tillmann Karras Date: Sat, 6 Dec 2014 16:01:09 +0100 Subject: [PATCH 1/3] x64Emitter: fix bitwise AVX opcodes The reason this didn't break is that bitwise instructions like VPAND, VANDPS, and VANDPD do the exact same thing. The only difference is the data type they are intended for. --- Source/Core/Common/x64Emitter.cpp | 18 ++++++++++++++---- Source/Core/Common/x64Emitter.h | 20 +++++++++++++++----- 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/Source/Core/Common/x64Emitter.cpp b/Source/Core/Common/x64Emitter.cpp index e894a19e09..38e957d7b7 100644 --- a/Source/Core/Common/x64Emitter.cpp +++ b/Source/Core/Common/x64Emitter.cpp @@ -1795,14 +1795,24 @@ void XEmitter::VSUBPD(X64Reg regOp1, X64Reg regOp2, OpArg arg) {WriteAVXOp(0x6 void XEmitter::VMULPD(X64Reg regOp1, X64Reg regOp2, OpArg arg) {WriteAVXOp(0x66, sseMUL, regOp1, regOp2, arg);} void XEmitter::VDIVPD(X64Reg regOp1, X64Reg regOp2, OpArg arg) {WriteAVXOp(0x66, sseDIV, regOp1, regOp2, arg);} void XEmitter::VSQRTSD(X64Reg regOp1, X64Reg regOp2, OpArg arg) {WriteAVXOp(0xF2, sseSQRT, regOp1, regOp2, arg);} -void XEmitter::VPAND(X64Reg regOp1, X64Reg regOp2, OpArg arg) {WriteAVXOp(0x66, sseAND, regOp1, regOp2, arg);} -void XEmitter::VPANDN(X64Reg regOp1, X64Reg regOp2, OpArg arg) {WriteAVXOp(0x66, sseANDN, regOp1, regOp2, arg);} -void XEmitter::VPOR(X64Reg regOp1, X64Reg regOp2, OpArg arg) {WriteAVXOp(0x66, sseOR, regOp1, regOp2, arg);} -void XEmitter::VPXOR(X64Reg regOp1, X64Reg regOp2, OpArg arg) {WriteAVXOp(0x66, sseXOR, regOp1, regOp2, arg);} void XEmitter::VSHUFPD(X64Reg regOp1, X64Reg regOp2, OpArg arg, u8 shuffle) {WriteAVXOp(0x66, sseSHUF, regOp1, regOp2, arg, 0, 1); Write8(shuffle);} void XEmitter::VUNPCKLPD(X64Reg regOp1, X64Reg regOp2, OpArg arg){WriteAVXOp(0x66, 0x14, regOp1, regOp2, arg);} void XEmitter::VUNPCKHPD(X64Reg regOp1, X64Reg regOp2, OpArg arg){WriteAVXOp(0x66, 0x15, regOp1, regOp2, arg);} +void XEmitter::VANDPS(X64Reg regOp1, X64Reg regOp2, OpArg arg) {WriteAVXOp(0x00, sseAND, regOp1, regOp2, arg);} +void XEmitter::VANDPD(X64Reg regOp1, X64Reg regOp2, OpArg arg) {WriteAVXOp(0x66, sseAND, regOp1, regOp2, arg);} +void XEmitter::VANDNPS(X64Reg regOp1, X64Reg regOp2, OpArg arg) {WriteAVXOp(0x00, sseANDN, regOp1, regOp2, arg);} +void XEmitter::VANDNPD(X64Reg regOp1, X64Reg regOp2, OpArg arg) {WriteAVXOp(0x66, sseANDN, regOp1, regOp2, arg);} +void XEmitter::VORPS(X64Reg regOp1, X64Reg regOp2, OpArg arg) {WriteAVXOp(0x00, sseOR, regOp1, regOp2, arg);} +void XEmitter::VORPD(X64Reg regOp1, X64Reg regOp2, OpArg arg) {WriteAVXOp(0x66, sseOR, regOp1, regOp2, arg);} +void XEmitter::VXORPS(X64Reg regOp1, X64Reg regOp2, OpArg arg) {WriteAVXOp(0x00, sseXOR, regOp1, regOp2, arg);} +void XEmitter::VXORPD(X64Reg regOp1, X64Reg regOp2, OpArg arg) {WriteAVXOp(0x66, sseXOR, regOp1, regOp2, arg);} + +void XEmitter::VPAND(X64Reg regOp1, X64Reg regOp2, OpArg arg) {WriteAVXOp(0x66, 0xDB, regOp1, regOp2, arg);} +void XEmitter::VPANDN(X64Reg regOp1, X64Reg regOp2, OpArg arg) {WriteAVXOp(0x66, 0xDF, regOp1, regOp2, arg);} +void XEmitter::VPOR(X64Reg regOp1, X64Reg regOp2, OpArg arg) {WriteAVXOp(0x66, 0xEB, regOp1, regOp2, arg);} +void XEmitter::VPXOR(X64Reg regOp1, X64Reg regOp2, OpArg arg) {WriteAVXOp(0x66, 0xEF, regOp1, regOp2, arg);} + void XEmitter::VFMADD132PS(X64Reg regOp1, X64Reg regOp2, OpArg arg) {WriteAVXOp(0x66, 0x3898, regOp1, regOp2, arg);} void XEmitter::VFMADD213PS(X64Reg regOp1, X64Reg regOp2, OpArg arg) {WriteAVXOp(0x66, 0x38A8, regOp1, regOp2, arg);} void XEmitter::VFMADD231PS(X64Reg regOp1, X64Reg regOp2, OpArg arg) {WriteAVXOp(0x66, 0x38B8, regOp1, regOp2, arg);} diff --git a/Source/Core/Common/x64Emitter.h b/Source/Core/Common/x64Emitter.h index e67c763aaa..639b78e5f7 100644 --- a/Source/Core/Common/x64Emitter.h +++ b/Source/Core/Common/x64Emitter.h @@ -766,15 +766,25 @@ public: void VMULPD(X64Reg regOp1, X64Reg regOp2, OpArg arg); void VDIVPD(X64Reg regOp1, X64Reg regOp2, OpArg arg); void VSQRTSD(X64Reg regOp1, X64Reg regOp2, OpArg arg); - void VPAND(X64Reg regOp1, X64Reg regOp2, OpArg arg); - void VPANDN(X64Reg regOp1, X64Reg regOp2, OpArg arg); - void VPOR(X64Reg regOp1, X64Reg regOp2, OpArg arg); - void VPXOR(X64Reg regOp1, X64Reg regOp2, OpArg arg); void VSHUFPD(X64Reg regOp1, X64Reg regOp2, OpArg arg, u8 shuffle); void VUNPCKLPD(X64Reg regOp1, X64Reg regOp2, OpArg arg); void VUNPCKHPD(X64Reg regOp1, X64Reg regOp2, OpArg arg); - // FMA + void VANDPS(X64Reg regOp1, X64Reg regOp2, OpArg arg); + void VANDPD(X64Reg regOp1, X64Reg regOp2, OpArg arg); + void VANDNPS(X64Reg regOp1, X64Reg regOp2, OpArg arg); + void VANDNPD(X64Reg regOp1, X64Reg regOp2, OpArg arg); + void VORPS(X64Reg regOp1, X64Reg regOp2, OpArg arg); + void VORPD(X64Reg regOp1, X64Reg regOp2, OpArg arg); + void VXORPS(X64Reg regOp1, X64Reg regOp2, OpArg arg); + void VXORPD(X64Reg regOp1, X64Reg regOp2, OpArg arg); + + void VPAND(X64Reg regOp1, X64Reg regOp2, OpArg arg); + void VPANDN(X64Reg regOp1, X64Reg regOp2, OpArg arg); + void VPOR(X64Reg regOp1, X64Reg regOp2, OpArg arg); + void VPXOR(X64Reg regOp1, X64Reg regOp2, OpArg arg); + + // FMA3 void VFMADD132PS(X64Reg regOp1, X64Reg regOp2, OpArg arg); void VFMADD213PS(X64Reg regOp1, X64Reg regOp2, OpArg arg); void VFMADD231PS(X64Reg regOp1, X64Reg regOp2, OpArg arg); From ddebdb61c4cde0ad03c0a5a5b716ea4a37ebded9 Mon Sep 17 00:00:00 2001 From: Tillmann Karras Date: Sat, 6 Dec 2014 15:50:38 +0100 Subject: [PATCH 2/3] UnitTests: fix register symbol name in AVX tests --- Source/UnitTests/Common/x64EmitterTest.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/UnitTests/Common/x64EmitterTest.cpp b/Source/UnitTests/Common/x64EmitterTest.cpp index 22164b8120..d0b2932e65 100644 --- a/Source/UnitTests/Common/x64EmitterTest.cpp +++ b/Source/UnitTests/Common/x64EmitterTest.cpp @@ -963,9 +963,9 @@ VEX_RMI_TEST(RORX) for (const auto& regset : regsets) \ for (const auto& r : regset.regs) \ { \ - emitter->Name(r.reg, RAX, R(RAX)); \ - emitter->Name(RAX, RAX, R(r.reg)); \ - emitter->Name(RAX, r.reg, MatR(R12)); \ + emitter->Name(r.reg, XMM0, R(XMM0)); \ + emitter->Name(XMM0, XMM0, R(r.reg)); \ + emitter->Name(XMM0, r.reg, MatR(R12)); \ ExpectDisassembly(#Name " " + r.name+ ", " + regset.out_name + ", " + regset.out_name + " " \ #Name " " + regset.out_name + ", " + regset.out_name + ", " + r.name + " " \ #Name " " + regset.out_name + ", " + r.name + ", " + regset.size + " ptr ds:[r12] "); \ From 791d5458e58b6580b591c42528bb690d774c45af Mon Sep 17 00:00:00 2001 From: Tillmann Karras Date: Sat, 6 Dec 2014 17:02:58 +0100 Subject: [PATCH 3/3] UnitTests: add tests for bitwise AVX instructions --- Source/UnitTests/Common/x64EmitterTest.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Source/UnitTests/Common/x64EmitterTest.cpp b/Source/UnitTests/Common/x64EmitterTest.cpp index d0b2932e65..83a3741e7f 100644 --- a/Source/UnitTests/Common/x64EmitterTest.cpp +++ b/Source/UnitTests/Common/x64EmitterTest.cpp @@ -972,6 +972,19 @@ VEX_RMI_TEST(RORX) } \ } +AVX_RRM_TEST(VANDPS, "dqword") +AVX_RRM_TEST(VANDPD, "dqword") +AVX_RRM_TEST(VANDNPS, "dqword") +AVX_RRM_TEST(VANDNPD, "dqword") +AVX_RRM_TEST(VORPS, "dqword") +AVX_RRM_TEST(VORPD, "dqword") +AVX_RRM_TEST(VXORPS, "dqword") +AVX_RRM_TEST(VXORPD, "dqword") +AVX_RRM_TEST(VPAND, "dqword") +AVX_RRM_TEST(VPANDN, "dqword") +AVX_RRM_TEST(VPOR, "dqword") +AVX_RRM_TEST(VPXOR, "dqword") + #define FMA_TEST(Name, P, packed) \ AVX_RRM_TEST(Name ## 132 ## P ## S, packed ? "dqword" : "dword") \ AVX_RRM_TEST(Name ## 213 ## P ## S, packed ? "dqword" : "dword") \