Preserve orig regs when applying vfpu prefixes.

This commit is contained in:
Unknown W. Brackets 2013-02-17 22:37:56 -08:00
parent d63548799b
commit 08a42a1aaf
4 changed files with 40 additions and 11 deletions

View File

@ -75,9 +75,6 @@ void Jit::Comp_VPFX(u32 op)
}
}
// TODO: Got register value ownership issues. We need to be sure that if we modify input
// like this, it does NOT get written back!
void Jit::ApplyPrefixST(u8 *vregs, u32 prefix, VectorSize sz) {
if (prefix == 0xE4) return;
@ -86,10 +83,7 @@ void Jit::ApplyPrefixST(u8 *vregs, u32 prefix, VectorSize sz) {
static const float constantArray[8] = {0.f, 1.f, 2.f, 0.5f, 3.f, 1.f/3.f, 0.25f, 1.f/6.f};
for (int i = 0; i < n; i++)
{
// TODO: This needs to be the original values, not the original regs. (e.g. [-x, |x|, x])
origV[i] = vregs[i];
}
for (int i = 0; i < n; i++)
{
@ -98,22 +92,33 @@ void Jit::ApplyPrefixST(u8 *vregs, u32 prefix, VectorSize sz) {
int negate = (prefix >> (16+i)) & 1;
int constants = (prefix >> (12+i)) & 1;
// Unchanged, hurray.
if (!constants && regnum == i && !abs && !negate)
continue;
// 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) {
// 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) {
regnum = 0;
}
vregs[i] = origV[regnum];
MOVSS(fpr.VX(vregs[i]), fpr.V(origV[regnum]));
if (abs) {
ANDPS(fpr.VX(vregs[i]), M((void *)&noSignMask));
}
} else {
} else {
MOVSS(fpr.VX(vregs[i]), M((void *)&constantArray[regnum + (abs<<2)]));
}
if (negate)
XORPS(fpr.VX(vregs[i]), M((void *)&signBitLower));
// TODO: This probably means it will swap out soon, inefficiently...
fpr.ReleaseSpillLockV(vregs[i]);
}
}

View File

@ -79,7 +79,7 @@ struct JitState
prefixDFlag = PREFIX_UNKNOWN;
}
bool MayHavePrefix() const {
if (!(prefixSFlag & PREFIX_KNOWN) || !(prefixTFlag & PREFIX_KNOWN) || !(prefixDFlag & PREFIX_KNOWN)) {
if (HasUnknownPrefix()) {
return true;
} else if (prefixS != 0xE4 || prefixT != 0xE4 || prefixD != 0) {
return true;
@ -89,6 +89,12 @@ struct JitState
return false;
}
bool HasUnknownPrefix() const {
if (!(prefixSFlag & PREFIX_KNOWN) || !(prefixTFlag & PREFIX_KNOWN) || !(prefixDFlag & PREFIX_KNOWN)) {
return true;
}
return false;
}
void EatPrefix() {
if ((prefixSFlag & PREFIX_KNOWN) == 0 || prefixS != 0xE4) {
prefixSFlag = PREFIX_KNOWN_DIRTY;

View File

@ -148,10 +148,21 @@ void FPURegCache::DiscardR(int i) {
}
}
bool FPURegCache::IsTemp(X64Reg xr) {
bool FPURegCache::IsTempX(X64Reg xr) {
return xregs[xr].mipsReg >= TEMP0;
}
int FPURegCache::GetTempR() {
for (int r = TEMP0; r < TEMP0 + NUM_TEMPS; ++r) {
if (!regs[r].away) {
return r;
}
}
_assert_msg_(DYNA_REC, 0, "Regcache ran out of temp regs, might need to DiscardR() some.");
return -1;
}
void FPURegCache::Flush() {
for (int i = 0; i < NUM_MIPS_FPRS; i++) {
if (regs[i].locked) {

View File

@ -88,7 +88,11 @@ public:
void DiscardV(int vreg) {
DiscardR(vreg + 32);
}
bool IsTemp(X64Reg xreg);
bool IsTempX(X64Reg xreg);
int GetTempR();
int GetTempV() {
return GetTempR() - 32;
}
void SetEmitter(XEmitter *emitter) {emit = emitter;}
@ -127,6 +131,9 @@ public:
}
void SpillLockV(const u8 *v, VectorSize vsz);
void SpillLockV(int vec, VectorSize vsz);
void ReleaseSpillLockV(int vreg) {
ReleaseSpillLock(vreg + 32);
}
MIPSState *mips;