Fixed the safe write path of the stfd instruction in the JIT. Fixes issue 4001.
This commit is contained in:
parent
b9547a07f5
commit
daf7e96521
|
@ -172,80 +172,63 @@ void Jit64::stfd(UGeckoInstruction inst)
|
||||||
|
|
||||||
int s = inst.RS;
|
int s = inst.RS;
|
||||||
int a = inst.RA;
|
int a = inst.RA;
|
||||||
if (!a)
|
|
||||||
{
|
u32 mem_mask = Memory::ADDR_MASK_HW_ACCESS;
|
||||||
Default(inst);
|
if (Core::g_CoreStartupParameter.bMMU ||
|
||||||
return;
|
Core::g_CoreStartupParameter.iTLBHack) {
|
||||||
|
mem_mask |= Memory::ADDR_MASK_MEM1;
|
||||||
}
|
}
|
||||||
s32 offset = (s32)(s16)inst.SIMM_16;
|
#ifdef ENABLE_MEM_CHECK
|
||||||
|
if (Core::g_CoreStartupParameter.bEnableDebugging)
|
||||||
|
{
|
||||||
|
mem_mask |= Memory::EXRAM_MASK;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
gpr.FlushLockX(ABI_PARAM1);
|
gpr.FlushLockX(ABI_PARAM1);
|
||||||
gpr.Lock(a);
|
gpr.Lock(a);
|
||||||
fpr.Lock(s);
|
fpr.Lock(s);
|
||||||
gpr.BindToRegister(a, true, false);
|
gpr.BindToRegister(a, true, false);
|
||||||
|
|
||||||
|
s32 offset = (s32)(s16)inst.SIMM_16;
|
||||||
LEA(32, ABI_PARAM1, MDisp(gpr.R(a).GetSimpleReg(), offset));
|
LEA(32, ABI_PARAM1, MDisp(gpr.R(a).GetSimpleReg(), offset));
|
||||||
TEST(32, R(ABI_PARAM1), Imm32(0x0c000000));
|
TEST(32, R(ABI_PARAM1), Imm32(mem_mask));
|
||||||
FixupBranch not_ram = J_CC(CC_Z);
|
FixupBranch safe = J_CC(CC_NZ);
|
||||||
// Assume that any hardware writes using this instruction will go to the FIFO.
|
|
||||||
// Star Wars - The Force Unleashed uses this trick.
|
// Fast routine
|
||||||
if (cpu_info.bSSSE3) {
|
if (cpu_info.bSSSE3) {
|
||||||
MOVAPD(XMM0, fpr.R(s));
|
MOVAPD(XMM0, fpr.R(s));
|
||||||
PSHUFB(XMM0, M((void *)bswapShuffle1x8));
|
PSHUFB(XMM0, M((void*)bswapShuffle1x8));
|
||||||
CALL(asm_routines.fifoDirectWriteXmm64);
|
|
||||||
} else {
|
|
||||||
// This ain't working yet
|
|
||||||
MOVAPD(XMM0, fpr.R(s));
|
|
||||||
MOVQ_xmm(M(&temp64), XMM0);
|
|
||||||
MOV(32, R(EAX), M(&temp64));
|
|
||||||
MOV(32, R(ABI_PARAM1), M((void*)((u8 *)&temp64 + 4)));
|
|
||||||
BSWAP(32, EAX);
|
|
||||||
BSWAP(32, ABI_PARAM1);
|
|
||||||
MOV(32, M(((u8 *)&temp64) + 4), R(EAX));
|
|
||||||
MOV(32, M((u8 *)&temp64), R(ABI_PARAM1));
|
|
||||||
MOVQ_xmm(XMM0, M(&temp64));
|
|
||||||
CALL(asm_routines.fifoDirectWriteXmm64);
|
|
||||||
}
|
|
||||||
FixupBranch quit = J(false);
|
|
||||||
SetJumpTarget(not_ram);
|
|
||||||
#ifdef _M_IX86
|
|
||||||
AND(32, R(ABI_PARAM1), Imm32(Memory::MEMVIEW32_MASK));
|
|
||||||
#endif
|
|
||||||
if (cpu_info.bSSSE3) {
|
|
||||||
MOVAPD(XMM0, fpr.R(s));
|
|
||||||
PSHUFB(XMM0, M((void *)bswapShuffle1x8));
|
|
||||||
#ifdef _M_X64
|
#ifdef _M_X64
|
||||||
MOVQ_xmm(MComplex(RBX, ABI_PARAM1, SCALE_1, 0), XMM0);
|
MOVQ_xmm(MComplex(RBX, ABI_PARAM1, SCALE_1, 0), XMM0);
|
||||||
#else
|
#else
|
||||||
|
AND(32, R(ECX), Imm32(Memory::MEMVIEW32_MASK));
|
||||||
MOVQ_xmm(MDisp(ABI_PARAM1, (u32)Memory::base), XMM0);
|
MOVQ_xmm(MDisp(ABI_PARAM1, (u32)Memory::base), XMM0);
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
#ifdef _M_X64
|
MOVAPD(XMM0, fpr.R(s));
|
||||||
fpr.BindToRegister(s, true, false);
|
MOVD_xmm(R(EAX), XMM0);
|
||||||
MOVSD(M(&temp64), fpr.RX(s));
|
UnsafeWriteRegToReg(EAX, ABI_PARAM1, 32, 4);
|
||||||
|
|
||||||
MEMCHECK_START
|
PSRLQ(XMM0, 32);
|
||||||
|
MOVD_xmm(R(EAX), XMM0);
|
||||||
MOV(64, R(EAX), M(&temp64));
|
UnsafeWriteRegToReg(EAX, ABI_PARAM1, 32, 0);
|
||||||
BSWAP(64, EAX);
|
|
||||||
MOV(64, MComplex(RBX, ABI_PARAM1, SCALE_1, 0), R(EAX));
|
|
||||||
|
|
||||||
MEMCHECK_END
|
|
||||||
#else
|
|
||||||
fpr.BindToRegister(s, true, false);
|
|
||||||
MOVSD(M(&temp64), fpr.RX(s));
|
|
||||||
|
|
||||||
MEMCHECK_START
|
|
||||||
|
|
||||||
MOV(32, R(EAX), M(&temp64));
|
|
||||||
BSWAP(32, EAX);
|
|
||||||
MOV(32, MDisp(ABI_PARAM1, (u32)Memory::base + 4), R(EAX));
|
|
||||||
MOV(32, R(EAX), M((void*)((u8 *)&temp64 + 4)));
|
|
||||||
BSWAP(32, EAX);
|
|
||||||
MOV(32, MDisp(ABI_PARAM1, (u32)Memory::base), R(EAX));
|
|
||||||
|
|
||||||
MEMCHECK_END
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
SetJumpTarget(quit);
|
FixupBranch exit = J();
|
||||||
|
SetJumpTarget(safe);
|
||||||
|
|
||||||
|
// Safe but slow routine
|
||||||
|
MOVAPD(XMM0, fpr.R(s));
|
||||||
|
MOVD_xmm(R(EAX), XMM0);
|
||||||
|
SafeWriteRegToReg(EAX, ABI_PARAM1, 32, 4);
|
||||||
|
|
||||||
|
PSRLQ(XMM0, 32);
|
||||||
|
MOVD_xmm(R(EAX), XMM0);
|
||||||
|
LEA(32, ABI_PARAM1, MDisp(gpr.R(a).GetSimpleReg(), offset));
|
||||||
|
SafeWriteRegToReg(EAX, ABI_PARAM1, 32, 0);
|
||||||
|
|
||||||
|
SetJumpTarget(exit);
|
||||||
|
|
||||||
gpr.UnlockAll();
|
gpr.UnlockAll();
|
||||||
gpr.UnlockAllX();
|
gpr.UnlockAllX();
|
||||||
fpr.UnlockAll();
|
fpr.UnlockAll();
|
||||||
|
|
Loading…
Reference in New Issue