mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-17 16:30:30 +02:00
ARMJit bugfixes, enable vmul, vadd, vdiv, vsub.
Prefixes disabled until I can fix clamping.
This commit is contained in:
1 parent
338f2a100b
commit
ebcdd637ee
4 files changed
+64
-59
No files matched your search
@@ -125,7 +125,7 @@ void Jit::Comp_FPULS(u32 op)
|
||||
SetCC(CC_AL);
|
||||
}
|
||||
#endif
|
||||
fpr.ReleaseSpillLocks();
|
||||
fpr.ReleaseSpillLocksAndDiscardTemps();
|
||||
break;
|
||||
|
||||
case 57: //Memory::Write_U32(FI(ft), addr); break; //swc1
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
|
||||
// #define CONDITIONAL_DISABLE { fpr.ReleaseSpillLocks(); Comp_Generic(op); return; }
|
||||
#define CONDITIONAL_DISABLE ;
|
||||
#define DISABLE { fpr.ReleaseSpillLocks(); Comp_Generic(op); return; }
|
||||
#define DISABLE { fpr.ReleaseSpillLocksAndDiscardTemps(); Comp_Generic(op); return; }
|
||||
|
||||
namespace MIPSComp
|
||||
{
|
||||
@@ -117,9 +117,10 @@ namespace MIPSComp
|
||||
|
||||
// This puts the value into a temp reg, so we won't write the modified value back.
|
||||
vregs[i] = fpr.GetTempV();
|
||||
fpr.MapRegV(vregs[i], MAP_NOINIT | MAP_DIRTY);
|
||||
|
||||
if (!constants) {
|
||||
fpr.MapDirtyInV(vregs[i], origV[regnum]);
|
||||
fpr.SpillLockV(vregs[i]);
|
||||
|
||||
// Prefix may say "z, z, z, z" but if this is a pair, we force to x.
|
||||
// TODO: But some ops seem to use const 0 instead?
|
||||
if (regnum >= n) {
|
||||
@@ -137,13 +138,11 @@ namespace MIPSComp
|
||||
else
|
||||
VMOV(fpr.V(vregs[i]), fpr.V(origV[regnum]));
|
||||
}
|
||||
|
||||
} else {
|
||||
fpr.MapRegV(vregs[i], MAP_DIRTY | MAP_NOINIT);
|
||||
fpr.SpillLockV(vregs[i]);
|
||||
MOVI2F(fpr.V(vregs[i]), constantArray[regnum + (abs<<2)], R0, negate);
|
||||
}
|
||||
|
||||
// TODO: This probably means it will swap out soon, inefficiently...
|
||||
fpr.ReleaseSpillLockV(vregs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,15 +170,17 @@ namespace MIPSComp
|
||||
if (js.VfpuWriteMask(i))
|
||||
continue;
|
||||
|
||||
// TODO: Pretty sure these clampers are wrong - put this into google
|
||||
// TODO: These clampers are wrong - put this into google
|
||||
// and look at the plot: abs(x) - abs(x-0.5) + 0.5
|
||||
// It's too steep.
|
||||
|
||||
// Also, they mishandle NaN and Inf.
|
||||
int sat = (js.prefixD >> (i * 2)) & 3;
|
||||
if (sat == 1) {
|
||||
// clamped = fabs(x) - fabs(x-0.5f) + 0.5f; // [ 0, 1]
|
||||
fpr.MapRegV(vregs[i], MAP_DIRTY);
|
||||
MOVI2F(S0, 0.5f, R0);
|
||||
|
||||
MOVI2F(S0, 1.0f, R0);
|
||||
VABS(S1, fpr.V(vregs[i])); // S1 = fabs(x)
|
||||
VSUB(fpr.V(vregs[i]), fpr.V(vregs[i]), S0); // S2 = fabs(x-0.5f) {VABD}
|
||||
VABS(fpr.V(vregs[i]), fpr.V(vregs[i]));
|
||||
@@ -211,7 +212,6 @@ namespace MIPSComp
|
||||
{
|
||||
// CC might be set by slow path below, so load regs first.
|
||||
fpr.MapRegV(vt, MAP_DIRTY | MAP_NOINIT);
|
||||
fpr.ReleaseSpillLocks();
|
||||
if (gpr.IsImm(rs)) {
|
||||
u32 addr = (imm + gpr.GetImm(rs)) & 0x3FFFFFFF;
|
||||
MOVI2R(R0, addr + (u32)Memory::base);
|
||||
@@ -250,7 +250,6 @@ namespace MIPSComp
|
||||
{
|
||||
// CC might be set by slow path below, so load regs first.
|
||||
fpr.MapRegV(vt);
|
||||
fpr.ReleaseSpillLocks();
|
||||
if (gpr.IsImm(rs)) {
|
||||
u32 addr = (imm + gpr.GetImm(rs)) & 0x3FFFFFFF;
|
||||
MOVI2R(R0, addr + (u32)Memory::base);
|
||||
@@ -305,8 +304,7 @@ namespace MIPSComp
|
||||
// CC might be set by slow path below, so load regs first.
|
||||
u8 vregs[4];
|
||||
GetVectorRegs(vregs, V_Quad, vt);
|
||||
fpr.MapRegsV(vregs, V_Quad, MAP_DIRTY | MAP_NOINIT);
|
||||
fpr.ReleaseSpillLocks();
|
||||
fpr.MapRegsAndSpillLockV(vregs, V_Quad, MAP_DIRTY | MAP_NOINIT);
|
||||
|
||||
if (gpr.IsImm(rs)) {
|
||||
u32 addr = (imm + gpr.GetImm(rs)) & 0x3FFFFFFF;
|
||||
@@ -355,8 +353,7 @@ namespace MIPSComp
|
||||
// CC might be set by slow path below, so load regs first.
|
||||
u8 vregs[4];
|
||||
GetVectorRegs(vregs, V_Quad, vt);
|
||||
fpr.MapRegsV(vregs, V_Quad, 0);
|
||||
fpr.ReleaseSpillLocks();
|
||||
fpr.MapRegsAndSpillLockV(vregs, V_Quad, 0);
|
||||
|
||||
if (gpr.IsImm(rs)) {
|
||||
u32 addr = (imm + gpr.GetImm(rs)) & 0x3FFFFFFF;
|
||||
@@ -400,6 +397,7 @@ namespace MIPSComp
|
||||
DISABLE;
|
||||
break;
|
||||
}
|
||||
fpr.ReleaseSpillLocksAndDiscardTemps();
|
||||
}
|
||||
|
||||
void Jit::Comp_VVectorInit(u32 op)
|
||||
@@ -429,13 +427,14 @@ namespace MIPSComp
|
||||
|
||||
u8 dregs[4];
|
||||
GetVectorRegsPrefixD(dregs, sz, _VD);
|
||||
fpr.MapRegsV(dregs, sz, MAP_NOINIT | MAP_DIRTY);
|
||||
fpr.MapRegsAndSpillLockV(dregs, sz, MAP_NOINIT | MAP_DIRTY);
|
||||
|
||||
for (int i = 0; i < n; ++i)
|
||||
VMOV(fpr.V(dregs[i]), S0);
|
||||
|
||||
ApplyPrefixD(dregs, sz);
|
||||
fpr.ReleaseSpillLocks();
|
||||
|
||||
fpr.ReleaseSpillLocksAndDiscardTemps();
|
||||
}
|
||||
|
||||
void Jit::Comp_VIdt(u32 op) {
|
||||
@@ -453,7 +452,7 @@ namespace MIPSComp
|
||||
MOVI2F(S1, 1.0f, R0);
|
||||
u8 dregs[4];
|
||||
GetVectorRegsPrefixD(dregs, sz, _VD);
|
||||
fpr.MapRegsV(dregs, sz, MAP_NOINIT | MAP_DIRTY);
|
||||
fpr.MapRegsAndSpillLockV(dregs, sz, MAP_NOINIT | MAP_DIRTY);
|
||||
switch (sz)
|
||||
{
|
||||
case V_Pair:
|
||||
@@ -470,8 +469,10 @@ namespace MIPSComp
|
||||
_dbg_assert_msg_(CPU,0,"Trying to interpret instruction that can't be interpreted");
|
||||
break;
|
||||
}
|
||||
|
||||
ApplyPrefixD(dregs, sz);
|
||||
fpr.ReleaseSpillLocks();
|
||||
|
||||
fpr.ReleaseSpillLocksAndDiscardTemps();
|
||||
}
|
||||
|
||||
void Jit::Comp_VMatrixInit(u32 op)
|
||||
@@ -519,7 +520,7 @@ namespace MIPSComp
|
||||
break;
|
||||
}
|
||||
|
||||
fpr.ReleaseSpillLocks();
|
||||
fpr.ReleaseSpillLocksAndDiscardTemps();
|
||||
}
|
||||
|
||||
void Jit::Comp_VDot(u32 op)
|
||||
@@ -541,8 +542,8 @@ namespace MIPSComp
|
||||
GetVectorRegs(tregs, sz, vt);
|
||||
|
||||
// TODO: applyprefixST here somehow (shuffle, etc...)
|
||||
fpr.MapRegsV(sregs, sz, 0);
|
||||
fpr.MapRegsV(tregs, sz, 0);
|
||||
fpr.MapRegsAndSpillLockV(sregs, sz, 0);
|
||||
fpr.MapRegsAndSpillLockV(tregs, sz, 0);
|
||||
VMUL(S0, fpr.V(sregs[0]), fpr.V(tregs[0]));
|
||||
|
||||
int n = GetNumVectorElements(sz);
|
||||
@@ -550,14 +551,12 @@ namespace MIPSComp
|
||||
// sum += s[i]*t[i];
|
||||
VMLA(S0, fpr.V(sregs[i]), fpr.V(tregs[i]));
|
||||
}
|
||||
fpr.ReleaseSpillLocks();
|
||||
fpr.ReleaseSpillLocksAndDiscardTemps();
|
||||
|
||||
fpr.MapRegV(vd, MAP_NOINIT | MAP_DIRTY);
|
||||
|
||||
// TODO: applyprefixD here somehow (write mask etc..)
|
||||
VMOV(fpr.V(vd), S0);
|
||||
|
||||
fpr.ReleaseSpillLocks();
|
||||
}
|
||||
|
||||
void Jit::Comp_VecDo3(u32 op)
|
||||
@@ -638,17 +637,16 @@ namespace MIPSComp
|
||||
}
|
||||
ApplyPrefixD(dregs, sz);
|
||||
|
||||
fpr.ReleaseSpillLocks();
|
||||
|
||||
js.EatPrefix();
|
||||
fpr.ReleaseSpillLocksAndDiscardTemps();
|
||||
}
|
||||
|
||||
void Jit::Comp_VV2Op(u32 op) {
|
||||
CONDITIONAL_DISABLE;
|
||||
|
||||
DISABLE;
|
||||
// DISABLE;
|
||||
|
||||
if (js.MayHavePrefix()) {
|
||||
//if (js.HasUnknownPrefix()) {
|
||||
DISABLE;
|
||||
}
|
||||
|
||||
@@ -775,9 +773,7 @@ namespace MIPSComp
|
||||
|
||||
ApplyPrefixD(dregs, sz);
|
||||
|
||||
fpr.FlushAll();
|
||||
|
||||
fpr.ReleaseSpillLocks();
|
||||
fpr.ReleaseSpillLocksAndDiscardTemps();
|
||||
}
|
||||
|
||||
void Jit::Comp_Mftv(u32 op)
|
||||
@@ -847,7 +843,7 @@ namespace MIPSComp
|
||||
fpr.MapRegV(vs, 0);
|
||||
ADD(R0, CTXREG, offsetof(MIPSState, vfpuCtrl[0]) + (imm - 128) * 4);
|
||||
VSTR(fpr.V(vs), R0, 0);
|
||||
fpr.ReleaseSpillLocks();
|
||||
fpr.ReleaseSpillLocksAndDiscardTemps();
|
||||
|
||||
if (imm - 128 == VFPU_CTRL_SPREFIX) {
|
||||
js.prefixSFlag = ArmJitState::PREFIX_UNKNOWN;
|
||||
@@ -896,7 +892,7 @@ namespace MIPSComp
|
||||
VMOV(fpr.V(dregs[a * 4 + b]), fpr.V(sregs[a * 4 + b]));
|
||||
}
|
||||
}
|
||||
fpr.ReleaseSpillLocks();
|
||||
fpr.ReleaseSpillLocksAndDiscardTemps();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -947,7 +943,8 @@ namespace MIPSComp
|
||||
}
|
||||
|
||||
ApplyPrefixD(dregs, sz);
|
||||
fpr.ReleaseSpillLocks();
|
||||
|
||||
fpr.ReleaseSpillLocksAndDiscardTemps();
|
||||
}
|
||||
|
||||
void Jit::Comp_Vmmul(u32 op) {
|
||||
@@ -988,7 +985,7 @@ namespace MIPSComp
|
||||
VMOV(fpr.V(dregs[a * 4 + b]), S0);
|
||||
}
|
||||
}
|
||||
fpr.ReleaseSpillLocks();
|
||||
fpr.ReleaseSpillLocksAndDiscardTemps();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1053,7 +1050,7 @@ namespace MIPSComp
|
||||
VMOV(fpr.V(dregs[i]), fpr.V(temp));
|
||||
}
|
||||
|
||||
fpr.ReleaseSpillLocks();
|
||||
fpr.ReleaseSpillLocksAndDiscardTemps();
|
||||
}
|
||||
|
||||
void Jit::Comp_VHdp(u32 op) {
|
||||
@@ -1108,12 +1105,11 @@ namespace MIPSComp
|
||||
FP16 half;
|
||||
half.u = op & 0xFFFF;
|
||||
FP32 fval = half_to_float_fast5(half);
|
||||
MOVI2F(S0, fval.f, R0);
|
||||
fpr.MapRegV(dreg, MAP_DIRTY | MAP_NOINIT);
|
||||
VMOV(fpr.V(dreg), S0);
|
||||
MOVI2F(fpr.V(dreg), fval.f, R0);
|
||||
|
||||
ApplyPrefixD(&dreg, V_Single);
|
||||
fpr.ReleaseSpillLocks();
|
||||
fpr.ReleaseSpillLocksAndDiscardTemps();
|
||||
}
|
||||
|
||||
void Jit::Comp_Vcst(u32 op) {
|
||||
@@ -1134,7 +1130,7 @@ namespace MIPSComp
|
||||
|
||||
u8 dregs[4];
|
||||
GetVectorRegsPrefixD(dregs, sz, _VD);
|
||||
fpr.MapRegsV(dregs, sz, MAP_NOINIT | MAP_DIRTY);
|
||||
fpr.MapRegsAndSpillLockV(dregs, sz, MAP_NOINIT | MAP_DIRTY);
|
||||
|
||||
MOVI2R(R0, (u32)(void *)&cst_constants[conNum]);
|
||||
VLDR(S0, R0, 0);
|
||||
@@ -1142,7 +1138,7 @@ namespace MIPSComp
|
||||
VMOV(fpr.V(dregs[i]), S0);
|
||||
|
||||
ApplyPrefixD(dregs, sz);
|
||||
fpr.ReleaseSpillLocks();
|
||||
fpr.ReleaseSpillLocksAndDiscardTemps();
|
||||
}
|
||||
|
||||
void Jit::Comp_Vhoriz(u32 op) {
|
||||
@@ -1214,9 +1210,8 @@ namespace MIPSComp
|
||||
what[(imm >> 2) & 3] = 'S';
|
||||
what[imm & 3] = 'C';
|
||||
|
||||
fpr.MapRegsAndSpillLockV(dregs, sz, MAP_DIRTY | MAP_NOINIT);
|
||||
for (int i = 0; i < n; i++) {
|
||||
fpr.MapRegV(dregs[i], MAP_DIRTY | MAP_NOINIT);
|
||||
fpr.SpillLockV(dregs[i]);
|
||||
switch (what[i]) {
|
||||
case 'C': VMOV(fpr.V(dregs[i]), S1); break;
|
||||
case 'S': VMOV(fpr.V(dregs[i]), S0); break;
|
||||
@@ -1230,6 +1225,6 @@ namespace MIPSComp
|
||||
break;
|
||||
}
|
||||
}
|
||||
fpr.ReleaseSpillLocks();
|
||||
fpr.ReleaseSpillLocksAndDiscardTemps();
|
||||
}
|
||||
}
|
||||
@@ -110,7 +110,7 @@ allocate:
|
||||
int bestToSpill = -1;
|
||||
for (int i = 0; i < allocCount; i++) {
|
||||
int reg = allocOrder[i] - S0;
|
||||
if (ar[reg].mipsReg != -1 && (mr[ar[reg].mipsReg].spillLock || mr[ar[reg].mipsReg].tempLock))
|
||||
if (ar[reg].mipsReg != -1 && mr[ar[reg].mipsReg].spillLock)
|
||||
continue;
|
||||
bestToSpill = reg;
|
||||
break;
|
||||
@@ -130,7 +130,8 @@ void ArmRegCacheFPU::MapInIn(MIPSReg rd, MIPSReg rs) {
|
||||
SpillLock(rd, rs);
|
||||
MapReg(rd);
|
||||
MapReg(rs);
|
||||
ReleaseSpillLocks();
|
||||
ReleaseSpillLock(rd);
|
||||
ReleaseSpillLock(rs);
|
||||
}
|
||||
|
||||
void ArmRegCacheFPU::MapDirtyIn(MIPSReg rd, MIPSReg rs, bool avoidLoad) {
|
||||
@@ -138,7 +139,8 @@ void ArmRegCacheFPU::MapDirtyIn(MIPSReg rd, MIPSReg rs, bool avoidLoad) {
|
||||
bool overlap = avoidLoad && rd == rs;
|
||||
MapReg(rd, MAP_DIRTY | (overlap ? 0 : MAP_NOINIT));
|
||||
MapReg(rs);
|
||||
ReleaseSpillLocks();
|
||||
ReleaseSpillLock(rd);
|
||||
ReleaseSpillLock(rs);
|
||||
}
|
||||
|
||||
void ArmRegCacheFPU::MapDirtyInIn(MIPSReg rd, MIPSReg rs, MIPSReg rt, bool avoidLoad) {
|
||||
@@ -147,7 +149,9 @@ void ArmRegCacheFPU::MapDirtyInIn(MIPSReg rd, MIPSReg rs, MIPSReg rt, bool avoid
|
||||
MapReg(rd, MAP_DIRTY | (overlap ? 0 : MAP_NOINIT));
|
||||
MapReg(rt);
|
||||
MapReg(rs);
|
||||
ReleaseSpillLocks();
|
||||
ReleaseSpillLock(rd);
|
||||
ReleaseSpillLock(rs);
|
||||
ReleaseSpillLock(rt);
|
||||
}
|
||||
|
||||
void ArmRegCacheFPU::SpillLockV(const u8 *v, VectorSize sz) {
|
||||
@@ -175,7 +179,7 @@ void ArmRegCacheFPU::LoadToRegV(ARMReg armReg, int vreg) {
|
||||
}
|
||||
}
|
||||
|
||||
void ArmRegCacheFPU::MapRegsV(int vec, VectorSize sz, int flags) {
|
||||
void ArmRegCacheFPU::MapRegsAndSpillLockV(int vec, VectorSize sz, int flags) {
|
||||
u8 v[4];
|
||||
GetVectorRegs(v, sz, vec);
|
||||
SpillLockV(v, sz);
|
||||
@@ -184,7 +188,7 @@ void ArmRegCacheFPU::MapRegsV(int vec, VectorSize sz, int flags) {
|
||||
}
|
||||
}
|
||||
|
||||
void ArmRegCacheFPU::MapRegsV(const u8 *v, VectorSize sz, int flags) {
|
||||
void ArmRegCacheFPU::MapRegsAndSpillLockV(const u8 *v, VectorSize sz, int flags) {
|
||||
SpillLockV(v, sz);
|
||||
for (int i = 0; i < GetNumVectorElements(sz); i++) {
|
||||
MapRegV(v[i], flags);
|
||||
@@ -305,7 +309,7 @@ void ArmRegCacheFPU::DiscardR(MIPSReg r) {
|
||||
mr[r].loc = ML_MEM;
|
||||
mr[r].reg = (int)INVALID_REG;
|
||||
mr[r].tempLock = false;
|
||||
// spill lock?
|
||||
mr[r].spillLock = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -346,7 +350,7 @@ int ArmRegCacheFPU::GetMipsRegOffset(MIPSReg r) {
|
||||
// These are offsets within the MIPSState structure. First there are the GPRS, then FPRS, then the "VFPURs".
|
||||
if (r < 32 + 128 + NUM_TEMPS)
|
||||
return (r + 32) << 2;
|
||||
ERROR_LOG(JIT, "bad mips register %i", r);
|
||||
ERROR_LOG(JIT, "bad mips register %i, out of range", r);
|
||||
return 0; // or what?
|
||||
}
|
||||
|
||||
@@ -358,7 +362,7 @@ void ArmRegCacheFPU::SpillLock(MIPSReg r1, MIPSReg r2, MIPSReg r3, MIPSReg r4) {
|
||||
}
|
||||
|
||||
// This is actually pretty slow with all the 160 regs...
|
||||
void ArmRegCacheFPU::ReleaseSpillLocks() {
|
||||
void ArmRegCacheFPU::ReleaseSpillLocksAndDiscardTemps() {
|
||||
for (int i = 0; i < NUM_MIPSFPUREG; i++)
|
||||
mr[i].spillLock = false;
|
||||
for (int i = TEMP0; i < TEMP0 + NUM_TEMPS; ++i)
|
||||
@@ -369,7 +373,13 @@ ARMReg ArmRegCacheFPU::R(int mipsReg) {
|
||||
if (mr[mipsReg].loc == ML_ARMREG) {
|
||||
return (ARMReg)(mr[mipsReg].reg + S0);
|
||||
} else {
|
||||
ERROR_LOG(JIT, "Reg %i not in arm reg. compilerPC = %08x : %s", mipsReg, compilerPC_, currentMIPS->DisasmAt(compilerPC_));
|
||||
if (mipsReg < 32) {
|
||||
ERROR_LOG(JIT, "FReg %i not in ARM reg. compilerPC = %08x : %s", mipsReg, compilerPC_, currentMIPS->DisasmAt(compilerPC_));
|
||||
} else if (mipsReg < 32 + 128) {
|
||||
ERROR_LOG(JIT, "VReg %i not in ARM reg. compilerPC = %08x : %s", mipsReg - 32, compilerPC_, currentMIPS->DisasmAt(compilerPC_));
|
||||
} else {
|
||||
ERROR_LOG(JIT, "Tempreg %i not in ARM reg. compilerPC = %08x : %s", mipsReg - 128 - 32, compilerPC_, currentMIPS->DisasmAt(compilerPC_));
|
||||
}
|
||||
return INVALID_REG; // BAAAD
|
||||
}
|
||||
}
|
||||
@@ -63,7 +63,7 @@ public:
|
||||
void SpillLock(MIPSReg reg, MIPSReg reg2 = -1, MIPSReg reg3 = -1, MIPSReg reg4 = -1);
|
||||
void SpillLockV(MIPSReg r) { SpillLock(r + 32); }
|
||||
|
||||
void ReleaseSpillLocks();
|
||||
void ReleaseSpillLocksAndDiscardTemps();
|
||||
void ReleaseSpillLock(int mipsreg)
|
||||
{
|
||||
mr[mipsreg].spillLock = false;
|
||||
@@ -108,8 +108,8 @@ public:
|
||||
void LoadToRegV(ARMReg armReg, int vreg);
|
||||
|
||||
// NOTE: These require you to release spill locks manually!
|
||||
void MapRegsV(int vec, VectorSize vsz, int flags);
|
||||
void MapRegsV(const u8 *v, VectorSize vsz, int flags);
|
||||
void MapRegsAndSpillLockV(int vec, VectorSize vsz, int flags);
|
||||
void MapRegsAndSpillLockV(const u8 *v, VectorSize vsz, int flags);
|
||||
|
||||
void SpillLockV(const u8 *v, VectorSize vsz);
|
||||
void SpillLockV(int vec, VectorSize vsz);
|
||||
|
||||
Reference in new issue
Block a user