diff --git a/Source/Core/Common/x64Emitter.cpp b/Source/Core/Common/x64Emitter.cpp index 14458ae7d4..f1aa26eae3 100644 --- a/Source/Core/Common/x64Emitter.cpp +++ b/Source/Core/Common/x64Emitter.cpp @@ -250,7 +250,7 @@ void OpArg::WriteVEX(XEmitter* emit, X64Reg regOp1, X64Reg regOp2, int L, int pp int X = !(indexReg & 8); int B = !(offsetOrBaseReg & 8); - int vvvv = (regOp2 == X64Reg::INVALID_REG) ? 0xf : (regOp2 ^ 0xf); + u8 vvvv = (regOp2 == X64Reg::INVALID_REG) ? 0xf : (regOp2 ^ 0xf); // do we need any VEX fields that only appear in the three-byte form? if (X == 1 && B == 1 && W == 0 && mmmmm == 1) @@ -343,7 +343,7 @@ void OpArg::WriteRest(XEmitter* emit, int extraBytes, X64Reg _operandReg, if (SIB) oreg = 4; - emit->WriteModRM(mod, _operandReg & 7, oreg & 7); + emit->WriteModRM(mod, _operandReg, oreg); if (SIB) { @@ -1844,8 +1844,9 @@ void XEmitter::WriteVEXOp(u8 opPrefix, u16 op, X64Reg regOp1, X64Reg regOp2, con { int mmmmm = GetVEXmmmmm(op); int pp = GetVEXpp(opPrefix); - // FIXME: we currently don't support 256-bit instructions, and "size" is not the vector size here - arg.WriteVEX(this, regOp1, regOp2, 0, pp, mmmmm, W); + // Note that mixing an XMM register with a YMM register is invalid, which isn't checked here. + int L = (regOp1 != INVALID_REG && regOp1 & 0x100) || (regOp2 != INVALID_REG && regOp2 & 0x100); + arg.WriteVEX(this, regOp1, regOp2, L, pp, mmmmm, W); Write8(op & 0xFF); arg.WriteRest(this, extrabytes, regOp1); } @@ -1857,19 +1858,23 @@ void XEmitter::WriteVEXOp4(u8 opPrefix, u16 op, X64Reg regOp1, X64Reg regOp2, co Write8((u8)regOp3 << 4); } -void XEmitter::WriteAVXOp(u8 opPrefix, u16 op, X64Reg regOp1, X64Reg regOp2, const OpArg& arg, - int W, int extrabytes) +void CheckAVXSupport() { if (!cpu_info.bAVX) PanicAlertFmt("Trying to use AVX on a system that doesn't support it. Bad programmer."); +} + +void XEmitter::WriteAVXOp(u8 opPrefix, u16 op, X64Reg regOp1, X64Reg regOp2, const OpArg& arg, + int W, int extrabytes) +{ + CheckAVXSupport(); WriteVEXOp(opPrefix, op, regOp1, regOp2, arg, W, extrabytes); } void XEmitter::WriteAVXOp4(u8 opPrefix, u16 op, X64Reg regOp1, X64Reg regOp2, const OpArg& arg, X64Reg regOp3, int W) { - if (!cpu_info.bAVX) - PanicAlertFmt("Trying to use AVX on a system that doesn't support it. Bad programmer."); + CheckAVXSupport(); WriteVEXOp4(opPrefix, op, regOp1, regOp2, arg, regOp3, W); } @@ -3029,6 +3034,19 @@ void XEmitter::VPXOR(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) WriteAVXOp(0x66, 0xEF, regOp1, regOp2, arg); } +void XEmitter::VMOVAPS(const OpArg& arg, X64Reg regOp) +{ + WriteAVXOp(0x00, 0x29, X64Reg::INVALID_REG, regOp, arg); +} + +void XEmitter::VZEROUPPER() +{ + CheckAVXSupport(); + Write8(0xC5); + Write8(0xF8); + Write8(0x77); +} + void XEmitter::VFMADD132PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteFMA3Op(0x98, regOp1, regOp2, arg); diff --git a/Source/Core/Common/x64Emitter.h b/Source/Core/Common/x64Emitter.h index 2b7bbb7726..3c8a411159 100644 --- a/Source/Core/Common/x64Emitter.h +++ b/Source/Core/Common/x64Emitter.h @@ -876,6 +876,10 @@ public: void VPOR(X64Reg regOp1, X64Reg regOp2, const OpArg& arg); void VPXOR(X64Reg regOp1, X64Reg regOp2, const OpArg& arg); + void VMOVAPS(const OpArg& arg, X64Reg regOp); + + void VZEROUPPER(); + // FMA3 void VFMADD132PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg); void VFMADD213PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg); diff --git a/Source/Core/Common/x64Reg.h b/Source/Core/Common/x64Reg.h index a868e3047a..c359738429 100644 --- a/Source/Core/Common/x64Reg.h +++ b/Source/Core/Common/x64Reg.h @@ -72,7 +72,8 @@ enum X64Reg XMM14, XMM15, - YMM0 = 0, + // Use the bit 0x100 to distinguish XMM and YMM registers. + YMM0 = 0x100, YMM1, YMM2, YMM3, diff --git a/Source/Core/Core/PowerPC/Jit64/Jit64_Tables.cpp b/Source/Core/Core/PowerPC/Jit64/Jit64_Tables.cpp index 62275b3dd8..be5458bffc 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit64_Tables.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit64_Tables.cpp @@ -101,7 +101,7 @@ constexpr std::array s_table4{{ {592, &Jit64::ps_mergeXX}, // ps_merge10 {624, &Jit64::ps_mergeXX}, // ps_merge11 - {1014, &Jit64::FallBackToInterpreter}, // dcbz_l + {1014, &Jit64::dcbz}, // dcbz_l }}; constexpr std::array s_table4_2{{ diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp index a200689f35..9f0eff7493 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp @@ -8,6 +8,7 @@ #include "Common/Assert.h" #include "Common/BitSet.h" +#include "Common/CPUDetect.h" #include "Common/CommonTypes.h" #include "Common/MsgHandler.h" #include "Common/x64ABI.h" @@ -473,9 +474,18 @@ void Jit64::dcbz(UGeckoInstruction inst) FixupBranch slow = J_CC(CC_Z, Jump::Near); // Fast path: compute full address, then zero out 32 bytes of memory. - XORPS(XMM0, R(XMM0)); - MOVAPS(MComplex(RMEM, RSCRATCH, SCALE_1, 0), XMM0); - MOVAPS(MComplex(RMEM, RSCRATCH, SCALE_1, 16), XMM0); + if (cpu_info.bAVX) + { + VXORPS(XMM0, XMM0, R(XMM0)); + VMOVAPS(MComplex(RMEM, RSCRATCH, SCALE_1, 0), YMM0); + VZEROUPPER(); + } + else + { + XORPS(XMM0, R(XMM0)); + MOVAPS(MComplex(RMEM, RSCRATCH, SCALE_1, 16), XMM0); + MOVAPS(MComplex(RMEM, RSCRATCH, SCALE_1, 0), XMM0); + } // Slow path: call the general-case code. SwitchToFarCode(); diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Tables.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Tables.cpp index 0aac345296..eb97db9b91 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Tables.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Tables.cpp @@ -101,7 +101,7 @@ constexpr std::array s_table4{{ {592, &JitArm64::ps_mergeXX}, // ps_merge10 {624, &JitArm64::ps_mergeXX}, // ps_merge11 - {1014, &JitArm64::FallBackToInterpreter}, // dcbz_l + {1014, &JitArm64::dcbz}, // dcbz_l }}; constexpr std::array s_table4_2{{