mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-29 09:09:52 -06:00
Support for dynamic BAT modification (dynamic-bat).
Fundamentally, all this does is enforce the invariant that we always translate effective addresses based on the current BAT registers and page table before we do anything else with them. This change can be logically divided into three parts. The first part is creating a table to represent the current BAT state, and keeping it up to date (PowerPC::IBATUpdated, PowerPC::DBATUpdated, etc.). This does nothing by itself, but it's necessary for the other parts. The second part (mostly in MMU.cpp) is simply removing all the hardcoded checks for specific untranslated addresses, and consistently translating addresses using the current BAT configuration. Very straightforward, but a lot of code changes because we hardcoded assumptions all over the place. The third part (mostly in Memmap.cpp) is making the fastmem arena reflect the current BAT configuration. We do this by redoing the mapping (calling memmap()) based on the BAT table whenever it changes. One additional minor change is that translation can fail in two ways: either the segment is a direct store segment, or page table lookup failed. The difference doesn't usually matter, but the difference affects cache instructions, like dcbz.
This commit is contained in:
@ -212,7 +212,7 @@ void EmuCodeBlock::MMIOLoadToReg(MMIO::Mapping* mmio, Gen::X64Reg reg_value,
|
||||
}
|
||||
|
||||
FixupBranch EmuCodeBlock::CheckIfSafeAddress(const OpArg& reg_value, X64Reg reg_addr,
|
||||
BitSet32 registers_in_use, u32 mem_mask)
|
||||
BitSet32 registers_in_use)
|
||||
{
|
||||
registers_in_use[reg_addr] = true;
|
||||
if (reg_value.IsSimpleReg())
|
||||
@ -227,29 +227,19 @@ FixupBranch EmuCodeBlock::CheckIfSafeAddress(const OpArg& reg_value, X64Reg reg_
|
||||
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->jo.memcheck && !SConfig::GetInstance().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());
|
||||
}
|
||||
if (scratch == reg_addr)
|
||||
PUSH(scratch);
|
||||
else
|
||||
{
|
||||
TEST(32, R(reg_addr), Imm32(mem_mask));
|
||||
return J_CC(CC_NZ, farcode.Enabled());
|
||||
}
|
||||
MOV(32, R(scratch), R(reg_addr));
|
||||
|
||||
// Perform lookup to see if we can use fast path.
|
||||
SHR(32, R(scratch), Imm8(PowerPC::BAT_INDEX_SHIFT));
|
||||
TEST(32, MScaled(scratch, SCALE_4, (u32)(u64)PowerPC::dbat_table), Imm32(2));
|
||||
|
||||
if (scratch == reg_addr)
|
||||
POP(scratch);
|
||||
|
||||
return J_CC(CC_Z, farcode.Enabled());
|
||||
}
|
||||
|
||||
void EmuCodeBlock::SafeLoadToReg(X64Reg reg_value, const Gen::OpArg& opAddress, int accessSize,
|
||||
@ -305,14 +295,11 @@ void EmuCodeBlock::SafeLoadToReg(X64Reg reg_value, const Gen::OpArg& opAddress,
|
||||
}
|
||||
|
||||
FixupBranch exit;
|
||||
if (!slowmem)
|
||||
bool dr_set = (flags & SAFE_LOADSTORE_DR_ON) || UReg_MSR(MSR).DR;
|
||||
bool fast_check_address = !slowmem && dr_set;
|
||||
if (fast_check_address)
|
||||
{
|
||||
u32 mem_mask = Memory::ADDR_MASK_HW_ACCESS;
|
||||
|
||||
// The following masks the region used by the GC/Wii virtual memory lib
|
||||
mem_mask |= Memory::ADDR_MASK_MEM1;
|
||||
|
||||
FixupBranch slow = CheckIfSafeAddress(R(reg_value), reg_addr, registersInUse, mem_mask);
|
||||
FixupBranch slow = CheckIfSafeAddress(R(reg_value), reg_addr, registersInUse);
|
||||
UnsafeLoadToReg(reg_value, R(reg_addr), accessSize, 0, signExtend);
|
||||
if (farcode.Enabled())
|
||||
SwitchToFarCode();
|
||||
@ -350,7 +337,7 @@ void EmuCodeBlock::SafeLoadToReg(X64Reg reg_value, const Gen::OpArg& opAddress,
|
||||
MOVZX(64, accessSize, reg_value, R(ABI_RETURN));
|
||||
}
|
||||
|
||||
if (!slowmem)
|
||||
if (fast_check_address)
|
||||
{
|
||||
if (farcode.Enabled())
|
||||
{
|
||||
@ -575,15 +562,12 @@ void EmuCodeBlock::SafeWriteRegToReg(OpArg reg_value, X64Reg reg_addr, int acces
|
||||
}
|
||||
}
|
||||
|
||||
FixupBranch slow, exit;
|
||||
if (!slowmem)
|
||||
FixupBranch exit;
|
||||
bool dr_set = (flags & SAFE_LOADSTORE_DR_ON) || UReg_MSR(MSR).DR;
|
||||
bool fast_check_address = !slowmem && dr_set;
|
||||
if (fast_check_address)
|
||||
{
|
||||
u32 mem_mask = Memory::ADDR_MASK_HW_ACCESS;
|
||||
|
||||
// The following masks the region used by the GC/Wii virtual memory lib
|
||||
mem_mask |= Memory::ADDR_MASK_MEM1;
|
||||
|
||||
slow = CheckIfSafeAddress(reg_value, reg_addr, registersInUse, mem_mask);
|
||||
FixupBranch slow = CheckIfSafeAddress(reg_value, reg_addr, registersInUse);
|
||||
UnsafeWriteRegToReg(reg_value, reg_addr, accessSize, 0, swap);
|
||||
if (farcode.Enabled())
|
||||
SwitchToFarCode();
|
||||
@ -629,7 +613,7 @@ void EmuCodeBlock::SafeWriteRegToReg(OpArg reg_value, X64Reg reg_addr, int acces
|
||||
|
||||
MemoryExceptionCheck();
|
||||
|
||||
if (!slowmem)
|
||||
if (fast_check_address)
|
||||
{
|
||||
if (farcode.Enabled())
|
||||
{
|
||||
|
@ -123,7 +123,7 @@ public:
|
||||
}
|
||||
|
||||
Gen::FixupBranch CheckIfSafeAddress(const Gen::OpArg& reg_value, Gen::X64Reg reg_addr,
|
||||
BitSet32 registers_in_use, u32 mem_mask);
|
||||
BitSet32 registers_in_use);
|
||||
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,
|
||||
@ -154,6 +154,7 @@ public:
|
||||
SAFE_LOADSTORE_CLOBBER_RSCRATCH_INSTEAD_OF_ADDR = 8,
|
||||
// Force slowmem (used when generating fallbacks in trampolines)
|
||||
SAFE_LOADSTORE_FORCE_SLOWMEM = 16,
|
||||
SAFE_LOADSTORE_DR_ON = 32,
|
||||
};
|
||||
|
||||
void SafeLoadToReg(Gen::X64Reg reg_value, const Gen::OpArg& opAddress, int accessSize, s32 offset,
|
||||
|
Reference in New Issue
Block a user