mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-01 14:58:14 +00:00
irjit: Handle vrot overlap more correctly.
Sine ignores overlap, cosine does not.
This commit is contained in:
1 parent
1fb7fe02b0
commit
3f997518f3
3 files changed
+50
-8
No files matched your search
@@ -1848,33 +1848,54 @@ namespace MIPSComp {
|
||||
int imm = (op >> 16) & 0x1f;
|
||||
VectorSize sz = GetVecSize(op);
|
||||
int n = GetNumVectorElements(sz);
|
||||
int sineLane = (imm >> 2) & 3;
|
||||
int cosineLane = imm & 3;
|
||||
bool negSin = (imm & 0x10) ? true : false;
|
||||
bool broadcastSine = sineLane == cosineLane;
|
||||
|
||||
char d[4] = { '0', '0', '0', '0' };
|
||||
if (((imm >> 2) & 3) == (imm & 3)) {
|
||||
if (broadcastSine) {
|
||||
for (int i = 0; i < 4; i++)
|
||||
d[i] = 's';
|
||||
}
|
||||
d[(imm >> 2) & 3] = 's';
|
||||
d[imm & 3] = 'c';
|
||||
d[sineLane] = 's';
|
||||
d[cosineLane] = 'c';
|
||||
|
||||
u8 dregs[4];
|
||||
GetVectorRegs(dregs, sz, vd);
|
||||
u8 sreg[1];
|
||||
GetVectorRegs(sreg, V_Single, vs);
|
||||
|
||||
// If there's overlap, sin is calculated without it, but cosine uses the result.
|
||||
// This corresponds with prefix handling, where cosine doesn't get in prefixes.
|
||||
if (broadcastSine || !IsOverlapSafe(n, dregs, 1, sreg)) {
|
||||
ir.Write(IROp::FSin, IRVTEMP_0, sreg[0]);
|
||||
if (negSin)
|
||||
ir.Write(IROp::FNeg, IRVTEMP_0, IRVTEMP_0);
|
||||
}
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
switch (d[i]) {
|
||||
case '0':
|
||||
ir.Write(IROp::SetConstF, dregs[i], ir.AddConstantFloat(0.0f));
|
||||
break;
|
||||
case 's':
|
||||
ir.Write(IROp::FSin, dregs[i], sreg[0]);
|
||||
if (negSin) {
|
||||
ir.Write(IROp::FNeg, dregs[i], dregs[i]);
|
||||
if (broadcastSine || !IsOverlapSafe(n, dregs, 1, sreg)) {
|
||||
ir.Write(IROp::FMov, dregs[i], IRVTEMP_0);
|
||||
} else {
|
||||
ir.Write(IROp::FSin, dregs[i], sreg[0]);
|
||||
if (negSin) {
|
||||
ir.Write(IROp::FNeg, dregs[i], dregs[i]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'c':
|
||||
ir.Write(IROp::FCos, dregs[i], sreg[0]);
|
||||
if (IsOverlapSafe(n, dregs, 1, sreg))
|
||||
ir.Write(IROp::FCos, dregs[i], sreg[0]);
|
||||
else if (dregs[sineLane] == sreg[0])
|
||||
ir.Write(IROp::FCos, dregs[i], IRVTEMP_0);
|
||||
else
|
||||
ir.Write(IROp::SetConstF, dregs[i], ir.AddConstantFloat(1.0f));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1607,7 +1607,24 @@ namespace MIPSInt
|
||||
} else {
|
||||
d[sineLane] = sine;
|
||||
}
|
||||
d[cosineLane] = cosine;
|
||||
|
||||
if (((vd >> 2) & 7) == ((vs >> 2) & 7)) {
|
||||
u8 dregs[4]{};
|
||||
GetVectorRegs(dregs, sz, vd);
|
||||
// Calculate cosine based on sine/zero result.
|
||||
bool written = false;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (vs == dregs[i]) {
|
||||
d[cosineLane] = vfpu_cos(d[i]);
|
||||
written = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!written)
|
||||
d[cosineLane] = cosine;
|
||||
} else {
|
||||
d[cosineLane] = cosine;
|
||||
}
|
||||
|
||||
// D prefix works, just not for x.
|
||||
currentMIPS->vfpuCtrl[VFPU_CTRL_DPREFIX] &= 0xFFEFC;
|
||||
|
||||
@@ -343,6 +343,10 @@ void WriteMatrix(const float *rd, MatrixSize size, int reg) {
|
||||
}
|
||||
|
||||
int GetVectorOverlap(int vec1, VectorSize size1, int vec2, VectorSize size2) {
|
||||
// Different matrices? Can't overlap, return early.
|
||||
if (((vec1 >> 2) & 7) != ((vec2 >> 2) & 7))
|
||||
return 0;
|
||||
|
||||
int n1 = GetNumVectorElements(size1);
|
||||
int n2 = GetNumVectorElements(size2);
|
||||
u8 regs1[4];
|
||||
|
||||
Reference in new issue
Block a user