From b3c8a82c4900c66a061f55550156d3a8a451a1fc Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 25 Nov 2014 23:56:46 +0100 Subject: [PATCH] x86 jit: SIMD-ify some more --- Core/MIPS/x86/CompVFPU.cpp | 32 ++++++++++++++++++++++++++++++++ Core/MIPS/x86/RegCacheFPU.cpp | 16 ++++++++++++++++ Core/MIPS/x86/RegCacheFPU.h | 1 + 3 files changed, 49 insertions(+) diff --git a/Core/MIPS/x86/CompVFPU.cpp b/Core/MIPS/x86/CompVFPU.cpp index 8e53d9be9d..7a1d3cc947 100644 --- a/Core/MIPS/x86/CompVFPU.cpp +++ b/Core/MIPS/x86/CompVFPU.cpp @@ -62,6 +62,7 @@ static const float minus_one = -1.0f; static const float zero = 0.0f; const u32 MEMORY_ALIGNED16( noSignMask[4] ) = {0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF}; +const u32 MEMORY_ALIGNED16( signBitAll[4] ) = {0x80000000, 0x80000000, 0x80000000, 0x80000000}; const u32 MEMORY_ALIGNED16( signBitLower[4] ) = {0x80000000, 0, 0, 0}; const float MEMORY_ALIGNED16( oneOneOneOne[4] ) = {1.0f, 1.0f, 1.0f, 1.0f}; const u32 MEMORY_ALIGNED16( solidOnes[4] ) = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}; @@ -1893,6 +1894,37 @@ void Jit::Comp_VV2Op(MIPSOpcode op) { GetVectorRegsPrefixS(sregs, sz, _VS); GetVectorRegsPrefixD(dregs, sz, _VD); + bool canSIMD = false; + // Some can be SIMD'd. + switch ((op >> 16) & 0x1f) { + case 0: // vmov + case 1: // vabs + case 2: // vneg + canSIMD = true; + break; + } + + if (canSIMD && fpr.TryMapDirtyInVS(dregs, sz, sregs, sz)) { + switch ((op >> 16) & 0x1f) { + case 0: // vmov + MOVAPS(fpr.VSX(dregs[0]), fpr.VS(sregs[0])); + break; + case 1: // vabs + if (dregs[0] != sregs[0]) + MOVAPS(fpr.VSX(dregs[0]), fpr.VS(sregs[0])); + ANDPS(fpr.VSX(dregs[0]), M(&noSignMask)); + break; + case 2: // vneg + if (dregs[0] != sregs[0]) + MOVAPS(fpr.VSX(dregs[0]), fpr.VS(sregs[0])); + XORPS(fpr.VSX(dregs[0]), M(&signBitAll)); + break; + } + ApplyPrefixD(dregs, sz); + fpr.ReleaseSpillLocks(); + return; + } + // Flush SIMD. fpr.SimpleRegsV(sregs, sz, 0); fpr.SimpleRegsV(dregs, sz, MAP_NOINIT | MAP_DIRTY); diff --git a/Core/MIPS/x86/RegCacheFPU.cpp b/Core/MIPS/x86/RegCacheFPU.cpp index a93cf49dc1..a7b51931c5 100644 --- a/Core/MIPS/x86/RegCacheFPU.cpp +++ b/Core/MIPS/x86/RegCacheFPU.cpp @@ -369,6 +369,22 @@ X64Reg FPURegCache::LoadRegsVS(const u8 *v, int n) { return xrs[0]; } +bool FPURegCache::TryMapDirtyInVS(const u8 *vd, VectorSize vdsz, const u8 *vs, VectorSize vssz, bool avoidLoad) { + // Don't waste time mapping if some will for sure fail. + if (!CanMapVS(vd, vdsz) || !CanMapVS(vs, vssz)) { + return false; + } + // But, they could still fail based on overlap. Hopefully not common... + bool success = TryMapRegsVS(vs, vssz, 0); + if (success) { + SpillLockV(vs, vssz); + success = TryMapRegsVS(vd, vdsz, avoidLoad ? (MAP_NOINIT | MAP_DIRTY) : MAP_DIRTY); + } + ReleaseSpillLockV(vs, vssz); + + return success; +} + bool FPURegCache::TryMapDirtyInInVS(const u8 *vd, VectorSize vdsz, const u8 *vs, VectorSize vssz, const u8 *vt, VectorSize vtsz, bool avoidLoad) { // Don't waste time mapping if some will for sure fail. if (!CanMapVS(vd, vdsz) || !CanMapVS(vs, vssz) || !CanMapVS(vt, vtsz)) { diff --git a/Core/MIPS/x86/RegCacheFPU.h b/Core/MIPS/x86/RegCacheFPU.h index 3f32570128..d6bec04d69 100644 --- a/Core/MIPS/x86/RegCacheFPU.h +++ b/Core/MIPS/x86/RegCacheFPU.h @@ -195,6 +195,7 @@ public: // TODO: This may trash XMM0/XMM1 some day. void MapRegsVS(const u8 *v, VectorSize vsz, int flags); bool TryMapRegsVS(const u8 *v, VectorSize vsz, int flags); + bool TryMapDirtyInVS(const u8 *vd, VectorSize vdsz, const u8 *vs, VectorSize vssz, bool avoidLoad = true); bool TryMapDirtyInInVS(const u8 *vd, VectorSize vdsz, const u8 *vs, VectorSize vssz, const u8 *vt, VectorSize vtsz, bool avoidLoad = true); // TODO: If s/t overlap differently, need read-only copies? Maybe finalize d? Major design flaw... // TODO: Matrix versions? Cols/Rows?