summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
authorcomex <comexk@gmail.com>2014-09-14 15:17:09 -0400
committercomex <comexk@gmail.com>2014-09-14 15:17:09 -0400
commit74f8a48ee6e967d9c46212fa48cd6392fdc9683f (patch)
treef871224efc5e7e3ef353531613a65b2757b919a3 /Source
parentdb7617248f18ba45ad1a81e4630b1bb283a78a73 (diff)
parent653140fcfae0d1b7024bd18ada4ece85067d3341 (diff)
Merge pull request #1063 from FioraAeterna/fastermmufix
MMU: properly check MEM1 range on Gamecube games
Diffstat (limited to 'Source')
-rw-r--r--Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp1
-rw-r--r--Source/Core/Core/PowerPC/Jit64/Jit_LoadStoreFloating.cpp3
-rw-r--r--Source/Core/Core/PowerPC/JitCommon/Jit_Util.cpp71
-rw-r--r--Source/Core/Core/PowerPC/JitCommon/Jit_Util.h1
4 files changed, 53 insertions, 23 deletions
diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp
index bf44c1ecbc..1dd12b0971 100644
--- a/Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp
+++ b/Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp
@@ -108,6 +108,7 @@ void Jit64::lXXx(UGeckoInstruction inst)
// do our job at first
s32 offset = (s32)(s16)inst.SIMM_16;
+ gpr.BindToRegister(a, true, false);
gpr.BindToRegister(d, false, true);
SafeLoadToReg(gpr.RX(d), gpr.R(a), accessSize, offset, CallerSavedRegistersInUse(), signExtend);
diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_LoadStoreFloating.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_LoadStoreFloating.cpp
index 4e35c13caa..ba45154601 100644
--- a/Source/Core/Core/PowerPC/Jit64/Jit_LoadStoreFloating.cpp
+++ b/Source/Core/Core/PowerPC/Jit64/Jit_LoadStoreFloating.cpp
@@ -29,8 +29,7 @@ void Jit64::lfXXX(UGeckoInstruction inst)
FALLBACK_IF((!indexed && !a) || (update && a == d));
- if (update)
- gpr.BindToRegister(a, true, true);
+ gpr.BindToRegister(a, true, update);
s32 offset = 0;
OpArg addr = gpr.R(a);
diff --git a/Source/Core/Core/PowerPC/JitCommon/Jit_Util.cpp b/Source/Core/Core/PowerPC/JitCommon/Jit_Util.cpp
index 8e91a79815..2ded60e859 100644
--- a/Source/Core/Core/PowerPC/JitCommon/Jit_Util.cpp
+++ b/Source/Core/Core/PowerPC/JitCommon/Jit_Util.cpp
@@ -250,6 +250,45 @@ void EmuCodeBlock::MMIOLoadToReg(MMIO::Mapping* mmio, Gen::X64Reg reg_value,
}
}
+FixupBranch EmuCodeBlock::CheckIfSafeAddress(X64Reg reg_value, X64Reg reg_addr, u32 registers_in_use, u32 mem_mask)
+{
+ registers_in_use |= (1 << reg_addr);
+ registers_in_use |= (1 << reg_value);
+
+ // Get ourselves a free register; try to pick one that doesn't involve pushing, if we can.
+ X64Reg scratch = RSCRATCH;
+ if (!(registers_in_use & (1 << RSCRATCH)))
+ scratch = RSCRATCH;
+ else if (!(registers_in_use & (1 << RSCRATCH_EXTRA)))
+ scratch = RSCRATCH_EXTRA;
+ else
+ scratch = reg_addr;
+
+ // On Gamecube games with MMU, do a little bit of extra work to make sure we're not accessing the
+ // 0x81800000 to 0x83FFFFFF range.
+ // It's okay to take a shortcut and not check this range on non-MMU games, since we're already
+ // assuming they'll never do an invalid memory access.
+ // The slightly more complex check needed for Wii games using the space just above MEM1 isn't
+ // implemented here yet, since there are no known working Wii MMU games to test it with.
+ if (jit->js.memcheck && !SConfig::GetInstance().m_LocalCoreStartupParameter.bWii)
+ {
+ if (scratch == reg_addr)
+ PUSH(scratch);
+ else
+ MOV(32, R(scratch), R(reg_addr));
+ AND(32, R(scratch), Imm32(0x3FFFFFFF));
+ CMP(32, R(scratch), Imm32(0x01800000));
+ if (scratch == reg_addr)
+ POP(scratch);
+ return J_CC(CC_AE, farcode.Enabled());
+ }
+ else
+ {
+ TEST(32, R(reg_addr), Imm32(mem_mask));
+ return J_CC(CC_NZ, farcode.Enabled());
+ }
+}
+
void EmuCodeBlock::SafeLoadToReg(X64Reg reg_value, const Gen::OpArg & opAddress, int accessSize, s32 offset, u32 registersInUse, bool signExtend, int flags)
{
if (!jit->js.memcheck)
@@ -333,46 +372,37 @@ void EmuCodeBlock::SafeLoadToReg(X64Reg reg_value, const Gen::OpArg & opAddress,
}
else
{
- OpArg addr_loc = opAddress;
+ _assert_msg_(DYNA_REC, opAddress.IsSimpleReg(), "Incorrect use of SafeLoadToReg (address isn't register or immediate)");
+ X64Reg reg_addr = opAddress.GetSimpleReg();
if (offset)
{
- addr_loc = R(RSCRATCH);
- if (opAddress.IsSimpleReg())
- {
- LEA(32, RSCRATCH, MDisp(opAddress.GetSimpleReg(), offset));
- }
- else
- {
- MOV(32, R(RSCRATCH), opAddress);
- ADD(32, R(RSCRATCH), Imm32(offset));
- }
+ reg_addr = RSCRATCH;
+ LEA(32, RSCRATCH, MDisp(opAddress.GetSimpleReg(), offset));
}
- TEST(32, addr_loc, Imm32(mem_mask));
FixupBranch slow, exit;
- slow = J_CC(CC_NZ, farcode.Enabled());
- UnsafeLoadToReg(reg_value, addr_loc, accessSize, 0, signExtend);
+ slow = CheckIfSafeAddress(reg_value, reg_addr, registersInUse, mem_mask);
+ UnsafeLoadToReg(reg_value, R(reg_addr), accessSize, 0, signExtend);
if (farcode.Enabled())
SwitchToFarCode();
else
exit = J(true);
SetJumpTarget(slow);
-
size_t rsp_alignment = (flags & SAFE_LOADSTORE_NO_PROLOG) ? 8 : 0;
ABI_PushRegistersAndAdjustStack(registersInUse, rsp_alignment);
switch (accessSize)
{
case 64:
- ABI_CallFunctionA((void *)&Memory::Read_U64, addr_loc);
+ ABI_CallFunctionR((void *)&Memory::Read_U64, reg_addr);
break;
case 32:
- ABI_CallFunctionA((void *)&Memory::Read_U32, addr_loc);
+ ABI_CallFunctionR((void *)&Memory::Read_U32, reg_addr);
break;
case 16:
- ABI_CallFunctionA((void *)&Memory::Read_U16_ZX, addr_loc);
+ ABI_CallFunctionR((void *)&Memory::Read_U16_ZX, reg_addr);
break;
case 8:
- ABI_CallFunctionA((void *)&Memory::Read_U8_ZX, addr_loc);
+ ABI_CallFunctionR((void *)&Memory::Read_U8_ZX, reg_addr);
break;
}
ABI_PopRegistersAndAdjustStack(registersInUse, rsp_alignment);
@@ -478,8 +508,7 @@ void EmuCodeBlock::SafeWriteRegToReg(X64Reg reg_value, X64Reg reg_addr, int acce
bool swap = !(flags & SAFE_LOADSTORE_NO_SWAP);
FixupBranch slow, exit;
- TEST(32, R(reg_addr), Imm32(mem_mask));
- slow = J_CC(CC_NZ, farcode.Enabled());
+ slow = CheckIfSafeAddress(reg_value, reg_addr, registersInUse, mem_mask);
UnsafeWriteRegToReg(reg_value, reg_addr, accessSize, 0, swap);
if (farcode.Enabled())
SwitchToFarCode();
diff --git a/Source/Core/Core/PowerPC/JitCommon/Jit_Util.h b/Source/Core/Core/PowerPC/JitCommon/Jit_Util.h
index 831d63572c..7a2051f742 100644
--- a/Source/Core/Core/PowerPC/JitCommon/Jit_Util.h
+++ b/Source/Core/Core/PowerPC/JitCommon/Jit_Util.h
@@ -76,6 +76,7 @@ public:
void LoadAndSwap(int size, Gen::X64Reg dst, const Gen::OpArg& src);
void SwapAndStore(int size, const Gen::OpArg& dst, Gen::X64Reg src);
+ Gen::FixupBranch CheckIfSafeAddress(Gen::X64Reg reg_value, Gen::X64Reg reg_addr, u32 registers_in_use, u32 mem_mask);
void UnsafeLoadRegToReg(Gen::X64Reg reg_addr, Gen::X64Reg reg_value, int accessSize, s32 offset = 0, bool signExtend = false);
void UnsafeLoadRegToRegNoSwap(Gen::X64Reg reg_addr, Gen::X64Reg reg_value, int accessSize, s32 offset, bool signExtend = false);
// these return the address of the MOV, for backpatching