mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-15 02:29:51 +01:00
x86 jit: SIMD-ify some more
This commit is contained in:
1 parent
b5ee47a80c
commit
b3c8a82c49
3 files changed
+49
No files matched your search
@@ -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);
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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?
|
||||
|
||||
Reference in new issue
Block a user