diff --git a/Core/MIPS/x86/CompVFPU.cpp b/Core/MIPS/x86/CompVFPU.cpp index ad53308406..5ef039b99f 100644 --- a/Core/MIPS/x86/CompVFPU.cpp +++ b/Core/MIPS/x86/CompVFPU.cpp @@ -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(¤tMIPS->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; } } } diff --git a/Core/MIPS/x86/Jit.cpp b/Core/MIPS/x86/Jit.cpp index dc6a789830..24a3000f11 100644 --- a/Core/MIPS/x86/Jit.cpp +++ b/Core/MIPS/x86/Jit.cpp @@ -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) diff --git a/Core/MIPS/x86/Jit.h b/Core/MIPS/x86/Jit.h index e39b93868e..080375ba7b 100644 --- a/Core/MIPS/x86/Jit.h +++ b/Core/MIPS/x86/Jit.h @@ -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.