x86 jit: SIMD-ify some more

This commit is contained in:
Henrik Rydgard committed 2014-11-25 23:56:46 +01:00
1 parent b5ee47a80c
commit b3c8a82c49
3 files changed
+49

No files matched your search

+32
View File
@@ -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);
+16
View File
@@ -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)) {
+1
View File
@@ -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?