summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorskidau <skidau@gmail.com>2012-01-03 01:17:52 +1100
committercalc84maniac <calc84maniac@gmail.com>2012-01-03 01:24:18 -0500
commitdaf7e965219eb61f36c19d2f2a6c12276c5a371e (patch)
tree72f216cd2dc7e22162b1d2510792b3315d8ea534 /Source/Core
parentb9547a07f580410bf565a6de88b20f209ed14f95 (diff)
Fixed the safe write path of the stfd instruction in the JIT. Fixes issue 4001.
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStoreFloating.cpp91
1 files changed, 37 insertions, 54 deletions
diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStoreFloating.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStoreFloating.cpp
index 55990d6abf..46e888f935 100644
--- a/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStoreFloating.cpp
+++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStoreFloating.cpp
@@ -172,80 +172,63 @@ void Jit64::stfd(UGeckoInstruction inst)
int s = inst.RS;
int a = inst.RA;
- if (!a)
+
+ u32 mem_mask = Memory::ADDR_MASK_HW_ACCESS;
+ if (Core::g_CoreStartupParameter.bMMU ||
+ Core::g_CoreStartupParameter.iTLBHack) {
+ mem_mask |= Memory::ADDR_MASK_MEM1;
+ }
+#ifdef ENABLE_MEM_CHECK
+ if (Core::g_CoreStartupParameter.bEnableDebugging)
{
- Default(inst);
- return;
+ mem_mask |= Memory::EXRAM_MASK;
}
- s32 offset = (s32)(s16)inst.SIMM_16;
+#endif
+
gpr.FlushLockX(ABI_PARAM1);
gpr.Lock(a);
fpr.Lock(s);
gpr.BindToRegister(a, true, false);
+
+ s32 offset = (s32)(s16)inst.SIMM_16;
LEA(32, ABI_PARAM1, MDisp(gpr.R(a).GetSimpleReg(), offset));
- TEST(32, R(ABI_PARAM1), Imm32(0x0c000000));
- FixupBranch not_ram = J_CC(CC_Z);
- // Assume that any hardware writes using this instruction will go to the FIFO.
- // Star Wars - The Force Unleashed uses this trick.
- if (cpu_info.bSSSE3) {
- MOVAPD(XMM0, fpr.R(s));
- 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
+ TEST(32, R(ABI_PARAM1), Imm32(mem_mask));
+ FixupBranch safe = J_CC(CC_NZ);
+
+ // Fast routine
if (cpu_info.bSSSE3) {
MOVAPD(XMM0, fpr.R(s));
- PSHUFB(XMM0, M((void *)bswapShuffle1x8));
+ PSHUFB(XMM0, M((void*)bswapShuffle1x8));
#ifdef _M_X64
MOVQ_xmm(MComplex(RBX, ABI_PARAM1, SCALE_1, 0), XMM0);
#else
+ AND(32, R(ECX), Imm32(Memory::MEMVIEW32_MASK));
MOVQ_xmm(MDisp(ABI_PARAM1, (u32)Memory::base), XMM0);
#endif
} else {
-#ifdef _M_X64
- fpr.BindToRegister(s, true, false);
- MOVSD(M(&temp64), fpr.RX(s));
-
- MEMCHECK_START
+ MOVAPD(XMM0, fpr.R(s));
+ MOVD_xmm(R(EAX), XMM0);
+ UnsafeWriteRegToReg(EAX, ABI_PARAM1, 32, 4);
- MOV(64, R(EAX), M(&temp64));
- BSWAP(64, EAX);
- MOV(64, MComplex(RBX, ABI_PARAM1, SCALE_1, 0), R(EAX));
+ PSRLQ(XMM0, 32);
+ MOVD_xmm(R(EAX), XMM0);
+ UnsafeWriteRegToReg(EAX, ABI_PARAM1, 32, 0);
+ }
+ FixupBranch exit = J();
+ SetJumpTarget(safe);
- MEMCHECK_END
-#else
- fpr.BindToRegister(s, true, false);
- MOVSD(M(&temp64), fpr.RX(s));
+ // Safe but slow routine
+ MOVAPD(XMM0, fpr.R(s));
+ MOVD_xmm(R(EAX), XMM0);
+ SafeWriteRegToReg(EAX, ABI_PARAM1, 32, 4);
- MEMCHECK_START
+ PSRLQ(XMM0, 32);
+ MOVD_xmm(R(EAX), XMM0);
+ LEA(32, ABI_PARAM1, MDisp(gpr.R(a).GetSimpleReg(), offset));
+ SafeWriteRegToReg(EAX, ABI_PARAM1, 32, 0);
- 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));
+ SetJumpTarget(exit);
- MEMCHECK_END
-#endif
- }
- SetJumpTarget(quit);
gpr.UnlockAll();
gpr.UnlockAllX();
fpr.UnlockAll();