Keep track of VFPU prefixes and flush them in jit.

This commit is contained in:
Unknown W. Brackets 2013-02-15 01:12:43 -08:00
parent f6f2927526
commit ccad259ae5
3 changed files with 68 additions and 25 deletions

View file

@ -62,19 +62,17 @@ void Jit::Comp_VPFX(u32 op)
switch (regnum) {
case 0: // S
js.prefixS = data;
js.prefixSKnown = true;
js.prefixSFlag = JitState::PREFIX_KNOWN_DIRTY;
break;
case 1: // T
js.prefixT = data;
js.prefixTKnown = true;
js.prefixTFlag = JitState::PREFIX_KNOWN_DIRTY;
break;
case 2: // D
js.prefixD = data;
js.prefixDKnown = true;
js.prefixDFlag = JitState::PREFIX_KNOWN_DIRTY;
break;
}
// TODO: Defer this to end of block
MOV(32, M((void *)&mips_->vfpuCtrl[VFPU_CTRL_SPREFIX + regnum]), Imm32(data));
}
@ -114,7 +112,7 @@ void Jit::ApplyPrefixST(u8 *vregs, u32 prefix, VectorSize sz) {
}
void Jit::ApplyPrefixD(const u8 *vregs, u32 prefix, VectorSize sz, bool onlyWriteMask) {
_assert_(js.prefixDKnown);
_assert_(js.prefixDFlag & JitState::PREFIX_KNOWN);
if (!prefix) return;
int n = GetNumVectorElements(sz);
@ -345,6 +343,8 @@ void Jit::Comp_Mftv(u32 op) {
gpr.BindToRegister(rt, false, true);
MOV(32, gpr.R(rt), fpr.V(imm));
} else if (imm < 128 + VFPU_CTRL_MAX) { //mtvc
// In case we have a saved prefix.
FlushAll();
gpr.BindToRegister(rt, false, true);
MOV(32, gpr.R(rt), M(&currentMIPS->vfpuCtrl[imm - 128]));
} else {
@ -366,11 +366,11 @@ void Jit::Comp_Mftv(u32 op) {
// TODO: Optimization if rt is Imm?
if (imm - 128 == VFPU_CTRL_SPREFIX) {
js.prefixSKnown = false;
js.prefixSFlag = JitState::PREFIX_UNKNOWN;
} else if (imm - 128 == VFPU_CTRL_TPREFIX) {
js.prefixTKnown = false;
js.prefixTFlag = JitState::PREFIX_UNKNOWN;
} else if (imm - 128 == VFPU_CTRL_DPREFIX) {
js.prefixDKnown = false;
js.prefixDFlag = JitState::PREFIX_UNKNOWN;
}
} else {
//ERROR
@ -393,11 +393,11 @@ void Jit::Comp_Vmtvc(u32 op) {
fpr.ReleaseSpillLocks();
if (imm - 128 == VFPU_CTRL_SPREFIX) {
js.prefixSKnown = false;
js.prefixSFlag = JitState::PREFIX_UNKNOWN;
} else if (imm - 128 == VFPU_CTRL_TPREFIX) {
js.prefixTKnown = false;
js.prefixTFlag = JitState::PREFIX_UNKNOWN;
} else if (imm - 128 == VFPU_CTRL_DPREFIX) {
js.prefixDKnown = false;
js.prefixDFlag = JitState::PREFIX_UNKNOWN;
}
}
}

View file

@ -109,6 +109,34 @@ void Jit::FlushAll()
{
gpr.Flush();
fpr.Flush();
FlushPrefixV();
}
void Jit::FlushPrefixV()
{
if ((js.prefixSFlag & JitState::PREFIX_DIRTY) != 0)
{
MOV(32, M((void *)&mips_->vfpuCtrl[VFPU_CTRL_SPREFIX]), Imm32(js.prefixS));
js.prefixSFlag = (JitState::PrefixState) (js.prefixSFlag & ~JitState::PREFIX_DIRTY);
}
if ((js.prefixTFlag & JitState::PREFIX_DIRTY) != 0)
{
MOV(32, M((void *)&mips_->vfpuCtrl[VFPU_CTRL_TPREFIX]), Imm32(js.prefixT));
js.prefixTFlag = (JitState::PrefixState) (js.prefixTFlag & ~JitState::PREFIX_DIRTY);
}
if ((js.prefixDFlag & JitState::PREFIX_DIRTY) != 0)
{
MOV(32, M((void *)&mips_->vfpuCtrl[VFPU_CTRL_DPREFIX]), Imm32(js.prefixD));
_dbg_assert_msg_(JIT, sizeof(bool) <= 4, "Bools shouldn't be that big?");
const size_t bool_stride = 4 / sizeof(bool);
for (size_t i = 0; i < ARRAY_SIZE(mips_->vfpuWriteMask); i += bool_stride)
MOV(32, M((void *)&mips_->vfpuWriteMask[i]), Imm32(*(u32 *)&js.writeMask[i]));
js.prefixDFlag = (JitState::PrefixState) (js.prefixDFlag & ~JitState::PREFIX_DIRTY);
}
}
void Jit::WriteDowncount(int offset)

View file

@ -48,6 +48,14 @@ struct JitOptions
struct JitState
{
enum PrefixState
{
PREFIX_UNKNOWN = 0x00,
PREFIX_KNOWN = 0x01,
PREFIX_DIRTY = 0x10,
PREFIX_KNOWN_DIRTY = 0x11,
};
u32 compilerPC;
u32 blockStart;
bool cancel;
@ -62,22 +70,28 @@ struct JitState
u32 prefixT;
u32 prefixD;
bool writeMask[4];
bool prefixSKnown;
bool prefixTKnown;
bool prefixDKnown;
PrefixState prefixSFlag;
PrefixState prefixTFlag;
PrefixState prefixDFlag;
void PrefixStart() {
prefixSKnown = false;
prefixTKnown = false;
prefixDKnown = false;
prefixSFlag = PREFIX_UNKNOWN;
prefixTFlag = PREFIX_UNKNOWN;
prefixDFlag = PREFIX_UNKNOWN;
}
void EatPrefix() {
prefixSKnown = true;
prefixTKnown = true;
prefixDKnown = true;
prefixS = 0xE4;
prefixT = 0xE4;
prefixD = 0x0;
writeMask[0] = writeMask[1] = writeMask[2] = writeMask[3] = false;
if ((prefixSFlag & PREFIX_KNOWN) == 0 || prefixS != 0xE4) {
prefixSFlag = PREFIX_KNOWN_DIRTY;
prefixS = 0xE4;
}
if ((prefixTFlag & PREFIX_KNOWN) == 0 || prefixT != 0xE4) {
prefixTFlag = PREFIX_KNOWN_DIRTY;
prefixT = 0xE4;
}
if ((prefixDFlag & PREFIX_KNOWN) == 0 || prefixD != 0x0 || writeMask[0] || writeMask[1] || writeMask[2] || writeMask[3]) {
prefixDFlag = PREFIX_KNOWN_DIRTY;
prefixD = 0x0;
writeMask[0] = writeMask[1] = writeMask[2] = writeMask[3] = false;
}
}
};
@ -155,6 +169,7 @@ public:
void ClearCacheAt(u32 em_address);
private:
void FlushAll();
void FlushPrefixV();
void WriteDowncount(int offset = 0);
// See CompileDelaySlotFlags for flags.