Make address translation respect the CPU translation mode.
The PowerPC CPU has bits in MSR (DR and IR) which control whether addresses are translated. We should respect these instead of mixing physical addresses and translated addresses into the same address space. This is mostly mass-renaming calls to memory accesses APIs from places which expect address translation to use a different version from those which do not expect address translation. This does very little on its own, but it's the first step to a correct BAT implementation.
This commit is contained in:
parent
d9988ee9b5
commit
ac54c6a4e2
|
@ -127,12 +127,12 @@ void MemArena::ReleaseView(void* view, size_t size)
|
|||
}
|
||||
|
||||
|
||||
u8* MemArena::Find4GBBase()
|
||||
u8* MemArena::FindMemoryBase()
|
||||
{
|
||||
#if _ARCH_64
|
||||
#ifdef _WIN32
|
||||
// 64 bit
|
||||
u8* base = (u8*)VirtualAlloc(0, 0xE1000000, MEM_RESERVE, PAGE_READWRITE);
|
||||
u8* base = (u8*)VirtualAlloc(0, 0x400000000, MEM_RESERVE, PAGE_READWRITE);
|
||||
VirtualFree(base, 0, MEM_RELEASE);
|
||||
return base;
|
||||
#else
|
||||
|
@ -250,7 +250,7 @@ u8 *MemoryMap_Setup(MemoryView *views, int num_views, u32 flags, MemArena *arena
|
|||
arena->GrabSHMSegment(total_mem);
|
||||
|
||||
// Now, create views in high memory where there's plenty of space.
|
||||
u8 *base = MemArena::Find4GBBase();
|
||||
u8 *base = MemArena::FindMemoryBase();
|
||||
// This really shouldn't fail - in 64-bit, there will always be enough
|
||||
// address space.
|
||||
if (!Memory_TryBase(base, views, num_views, flags, arena))
|
||||
|
|
|
@ -24,8 +24,8 @@ public:
|
|||
void *CreateView(s64 offset, size_t size, void *base = nullptr);
|
||||
void ReleaseView(void *view, size_t size);
|
||||
|
||||
// This only finds 1 GB in 32-bit
|
||||
static u8 *Find4GBBase();
|
||||
// This finds 1 GB in 32-bit, 16 GB in 64-bit.
|
||||
static u8 *FindMemoryBase();
|
||||
private:
|
||||
|
||||
#ifdef _WIN32
|
||||
|
@ -44,7 +44,7 @@ enum {
|
|||
struct MemoryView
|
||||
{
|
||||
u8** out_ptr;
|
||||
u32 virtual_address;
|
||||
u64 virtual_address;
|
||||
u32 size;
|
||||
u32 flags;
|
||||
void* mapped_ptr;
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
#include "Core/ARDecrypt.h"
|
||||
#include "Core/ConfigManager.h"
|
||||
#include "Core/Core.h"
|
||||
#include "Core/HW/Memmap.h"
|
||||
#include "Core/PowerPC/PowerPC.h"
|
||||
|
||||
namespace ActionReplay
|
||||
{
|
||||
|
@ -320,7 +320,7 @@ static bool Subtype_RamWriteAndFill(const ARAddr& addr, const u32 data)
|
|||
u32 repeat = data >> 8;
|
||||
for (u32 i = 0; i <= repeat; ++i)
|
||||
{
|
||||
Memory::Write_U8(data & 0xFF, new_addr + i);
|
||||
PowerPC::HostWrite_U8(data & 0xFF, new_addr + i);
|
||||
LogInfo("Wrote %08x to address %08x", data & 0xFF, new_addr + i);
|
||||
}
|
||||
LogInfo("--------");
|
||||
|
@ -334,7 +334,7 @@ static bool Subtype_RamWriteAndFill(const ARAddr& addr, const u32 data)
|
|||
u32 repeat = data >> 16;
|
||||
for (u32 i = 0; i <= repeat; ++i)
|
||||
{
|
||||
Memory::Write_U16(data & 0xFFFF, new_addr + i * 2);
|
||||
PowerPC::HostWrite_U16(data & 0xFFFF, new_addr + i * 2);
|
||||
LogInfo("Wrote %08x to address %08x", data & 0xFFFF, new_addr + i * 2);
|
||||
}
|
||||
LogInfo("--------");
|
||||
|
@ -345,7 +345,7 @@ static bool Subtype_RamWriteAndFill(const ARAddr& addr, const u32 data)
|
|||
case DATATYPE_32BIT: // Dword write
|
||||
LogInfo("32-bit Write");
|
||||
LogInfo("--------");
|
||||
Memory::Write_U32(data, new_addr);
|
||||
PowerPC::HostWrite_U32(data, new_addr);
|
||||
LogInfo("Wrote %08x to address %08x", data, new_addr);
|
||||
LogInfo("--------");
|
||||
break;
|
||||
|
@ -364,7 +364,7 @@ static bool Subtype_RamWriteAndFill(const ARAddr& addr, const u32 data)
|
|||
static bool Subtype_WriteToPointer(const ARAddr& addr, const u32 data)
|
||||
{
|
||||
const u32 new_addr = addr.GCAddress();
|
||||
const u32 ptr = Memory::Read_U32(new_addr);
|
||||
const u32 ptr = PowerPC::HostRead_U32(new_addr);
|
||||
|
||||
LogInfo("Hardware Address: %08x", new_addr);
|
||||
LogInfo("Size: %08x", addr.size);
|
||||
|
@ -380,7 +380,7 @@ static bool Subtype_WriteToPointer(const ARAddr& addr, const u32 data)
|
|||
LogInfo("Pointer: %08x", ptr);
|
||||
LogInfo("Byte: %08x", thebyte);
|
||||
LogInfo("Offset: %08x", offset);
|
||||
Memory::Write_U8(thebyte, ptr + offset);
|
||||
PowerPC::HostWrite_U8(thebyte, ptr + offset);
|
||||
LogInfo("Wrote %08x to address %08x", thebyte, ptr + offset);
|
||||
LogInfo("--------");
|
||||
break;
|
||||
|
@ -395,7 +395,7 @@ static bool Subtype_WriteToPointer(const ARAddr& addr, const u32 data)
|
|||
LogInfo("Pointer: %08x", ptr);
|
||||
LogInfo("Byte: %08x", theshort);
|
||||
LogInfo("Offset: %08x", offset);
|
||||
Memory::Write_U16(theshort, ptr + offset);
|
||||
PowerPC::HostWrite_U16(theshort, ptr + offset);
|
||||
LogInfo("Wrote %08x to address %08x", theshort, ptr + offset);
|
||||
LogInfo("--------");
|
||||
break;
|
||||
|
@ -405,7 +405,7 @@ static bool Subtype_WriteToPointer(const ARAddr& addr, const u32 data)
|
|||
case DATATYPE_32BIT:
|
||||
LogInfo("Write 32-bit to pointer");
|
||||
LogInfo("--------");
|
||||
Memory::Write_U32(data, ptr);
|
||||
PowerPC::HostWrite_U32(data, ptr);
|
||||
LogInfo("Wrote %08x to address %08x", data, ptr);
|
||||
LogInfo("--------");
|
||||
break;
|
||||
|
@ -433,24 +433,24 @@ static bool Subtype_AddCode(const ARAddr& addr, const u32 data)
|
|||
case DATATYPE_8BIT:
|
||||
LogInfo("8-bit Add");
|
||||
LogInfo("--------");
|
||||
Memory::Write_U8(Memory::Read_U8(new_addr) + data, new_addr);
|
||||
LogInfo("Wrote %08x to address %08x", Memory::Read_U8(new_addr) + (data & 0xFF), new_addr);
|
||||
PowerPC::HostWrite_U8(PowerPC::HostRead_U8(new_addr) + data, new_addr);
|
||||
LogInfo("Wrote %08x to address %08x", PowerPC::HostRead_U8(new_addr) + (data & 0xFF), new_addr);
|
||||
LogInfo("--------");
|
||||
break;
|
||||
|
||||
case DATATYPE_16BIT:
|
||||
LogInfo("16-bit Add");
|
||||
LogInfo("--------");
|
||||
Memory::Write_U16(Memory::Read_U16(new_addr) + data, new_addr);
|
||||
LogInfo("Wrote %08x to address %08x", Memory::Read_U16(new_addr) + (data & 0xFFFF), new_addr);
|
||||
PowerPC::HostWrite_U16(PowerPC::HostRead_U16(new_addr) + data, new_addr);
|
||||
LogInfo("Wrote %08x to address %08x", PowerPC::HostRead_U16(new_addr) + (data & 0xFFFF), new_addr);
|
||||
LogInfo("--------");
|
||||
break;
|
||||
|
||||
case DATATYPE_32BIT:
|
||||
LogInfo("32-bit Add");
|
||||
LogInfo("--------");
|
||||
Memory::Write_U32(Memory::Read_U32(new_addr) + data, new_addr);
|
||||
LogInfo("Wrote %08x to address %08x", Memory::Read_U32(new_addr) + data, new_addr);
|
||||
PowerPC::HostWrite_U32(PowerPC::HostRead_U32(new_addr) + data, new_addr);
|
||||
LogInfo("Wrote %08x to address %08x", PowerPC::HostRead_U32(new_addr) + data, new_addr);
|
||||
LogInfo("--------");
|
||||
break;
|
||||
|
||||
|
@ -459,10 +459,10 @@ static bool Subtype_AddCode(const ARAddr& addr, const u32 data)
|
|||
LogInfo("32-bit floating Add");
|
||||
LogInfo("--------");
|
||||
|
||||
const u32 read = Memory::Read_U32(new_addr);
|
||||
const u32 read = PowerPC::HostRead_U32(new_addr);
|
||||
const float fread = *((float*)&read) + (float)data; // data contains an integer value
|
||||
const u32 newval = *((u32*)&fread);
|
||||
Memory::Write_U32(newval, new_addr);
|
||||
PowerPC::HostWrite_U32(newval, new_addr);
|
||||
LogInfo("Old Value %08x", read);
|
||||
LogInfo("Increment %08x", data);
|
||||
LogInfo("New value %08x", newval);
|
||||
|
@ -517,7 +517,7 @@ static bool ZeroCode_FillAndSlide(const u32 val_last, const ARAddr& addr, const
|
|||
LogInfo("--------");
|
||||
for (int i = 0; i < write_num; ++i)
|
||||
{
|
||||
Memory::Write_U8(val & 0xFF, curr_addr);
|
||||
PowerPC::HostWrite_U8(val & 0xFF, curr_addr);
|
||||
curr_addr += addr_incr;
|
||||
val += val_incr;
|
||||
LogInfo("Write %08x to address %08x", val & 0xFF, curr_addr);
|
||||
|
@ -533,7 +533,7 @@ static bool ZeroCode_FillAndSlide(const u32 val_last, const ARAddr& addr, const
|
|||
LogInfo("--------");
|
||||
for (int i=0; i < write_num; ++i)
|
||||
{
|
||||
Memory::Write_U16(val & 0xFFFF, curr_addr);
|
||||
PowerPC::HostWrite_U16(val & 0xFFFF, curr_addr);
|
||||
LogInfo("Write %08x to address %08x", val & 0xFFFF, curr_addr);
|
||||
curr_addr += addr_incr * 2;
|
||||
val += val_incr;
|
||||
|
@ -548,7 +548,7 @@ static bool ZeroCode_FillAndSlide(const u32 val_last, const ARAddr& addr, const
|
|||
LogInfo("--------");
|
||||
for (int i = 0; i < write_num; ++i)
|
||||
{
|
||||
Memory::Write_U32(val, curr_addr);
|
||||
PowerPC::HostWrite_U32(val, curr_addr);
|
||||
LogInfo("Write %08x to address %08x", val, curr_addr);
|
||||
curr_addr += addr_incr * 4;
|
||||
val += val_incr;
|
||||
|
@ -586,8 +586,8 @@ static bool ZeroCode_MemoryCopy(const u32 val_last, const ARAddr& addr, const u3
|
|||
LogInfo("--------");
|
||||
for (int i = 0; i < 138; ++i)
|
||||
{
|
||||
Memory::Write_U8(Memory::Read_U8(addr_src + i), addr_dest + i);
|
||||
LogInfo("Wrote %08x to address %08x", Memory::Read_U8(addr_src + i), addr_dest + i);
|
||||
PowerPC::HostWrite_U8(PowerPC::HostRead_U8(addr_src + i), addr_dest + i);
|
||||
LogInfo("Wrote %08x to address %08x", PowerPC::HostRead_U8(addr_src + i), addr_dest + i);
|
||||
}
|
||||
LogInfo("--------");
|
||||
}
|
||||
|
@ -597,8 +597,8 @@ static bool ZeroCode_MemoryCopy(const u32 val_last, const ARAddr& addr, const u3
|
|||
LogInfo("--------");
|
||||
for (int i=0; i < num_bytes; ++i)
|
||||
{
|
||||
Memory::Write_U8(Memory::Read_U8(addr_src + i), addr_dest + i);
|
||||
LogInfo("Wrote %08x to address %08x", Memory::ReadUnchecked_U8(addr_src + i), addr_dest + i);
|
||||
PowerPC::HostWrite_U8(PowerPC::HostRead_U8(addr_src + i), addr_dest + i);
|
||||
LogInfo("Wrote %08x to address %08x", PowerPC::HostRead_U8(addr_src + i), addr_dest + i);
|
||||
}
|
||||
LogInfo("--------");
|
||||
return true;
|
||||
|
@ -709,16 +709,16 @@ static bool ConditionalCode(const ARAddr& addr, const u32 data, int* const pSkip
|
|||
switch (addr.size)
|
||||
{
|
||||
case DATATYPE_8BIT:
|
||||
result = CompareValues((u32)Memory::Read_U8(new_addr), (data & 0xFF), addr.type);
|
||||
result = CompareValues((u32)PowerPC::HostRead_U8(new_addr), (data & 0xFF), addr.type);
|
||||
break;
|
||||
|
||||
case DATATYPE_16BIT:
|
||||
result = CompareValues((u32)Memory::Read_U16(new_addr), (data & 0xFFFF), addr.type);
|
||||
result = CompareValues((u32)PowerPC::HostRead_U16(new_addr), (data & 0xFFFF), addr.type);
|
||||
break;
|
||||
|
||||
case DATATYPE_32BIT_FLOAT:
|
||||
case DATATYPE_32BIT:
|
||||
result = CompareValues(Memory::Read_U32(new_addr), data, addr.type);
|
||||
result = CompareValues(PowerPC::HostRead_U32(new_addr), data, addr.type);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -39,10 +39,10 @@ void CBoot::Load_FST(bool _bIsWii)
|
|||
return;
|
||||
|
||||
// copy first 20 bytes of disc to start of Mem 1
|
||||
VolumeHandler::ReadToPtr(Memory::GetPointer(0x80000000), 0, 0x20, false);
|
||||
DVDInterface::DVDRead(/*offset*/0, /*address*/0, /*length*/0x20, false);
|
||||
|
||||
// copy of game id
|
||||
Memory::Write_U32(Memory::Read_U32(0x80000000), 0x80003180);
|
||||
Memory::Write_U32(Memory::Read_U32(0x0000), 0x3180);
|
||||
|
||||
u32 shift = 0;
|
||||
if (_bIsWii)
|
||||
|
@ -56,7 +56,7 @@ void CBoot::Load_FST(bool _bIsWii)
|
|||
Memory::Write_U32(arenaHigh, 0x00000034);
|
||||
|
||||
// load FST
|
||||
VolumeHandler::ReadToPtr(Memory::GetPointer(arenaHigh), fstOffset, fstSize, _bIsWii);
|
||||
DVDInterface::DVDRead(fstOffset, arenaHigh, fstSize, _bIsWii);
|
||||
Memory::Write_U32(arenaHigh, 0x00000038);
|
||||
Memory::Write_U32(maxFstSize, 0x0000003c);
|
||||
}
|
||||
|
@ -188,9 +188,9 @@ bool CBoot::Load_BS2(const std::string& _rBootROMFilename)
|
|||
// Run the descrambler over the encrypted section containing BS1/BS2
|
||||
CEXIIPL::Descrambler((u8*)data.data()+0x100, 0x1AFE00);
|
||||
|
||||
Memory::CopyToEmu(0x81200000, data.data() + 0x100, 0x700);
|
||||
Memory::CopyToEmu(0x81300000, data.data() + 0x820, 0x1AFE00);
|
||||
PC = 0x81200000;
|
||||
Memory::CopyToEmu(0x01200000, data.data() + 0x100, 0x700);
|
||||
Memory::CopyToEmu(0x01300000, data.data() + 0x820, 0x1AFE00);
|
||||
PC = 0x01200000;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -255,7 +255,7 @@ bool CBoot::BootUp()
|
|||
}
|
||||
|
||||
// Scan for common HLE functions
|
||||
if (_StartupPara.bSkipIdle && !_StartupPara.bEnableDebugging)
|
||||
if (_StartupPara.bSkipIdle && _StartupPara.bHLE_BS2 && !_StartupPara.bEnableDebugging)
|
||||
{
|
||||
PPCAnalyst::FindFunctions(0x80004000, 0x811fffff, &g_symbolDB);
|
||||
SignatureDB db;
|
||||
|
@ -309,6 +309,25 @@ bool CBoot::BootUp()
|
|||
|
||||
if (!BS2Success)
|
||||
{
|
||||
// Set up MSR and the BAT SPR registers.
|
||||
UReg_MSR& m_MSR = ((UReg_MSR&)PowerPC::ppcState.msr);
|
||||
m_MSR.FP = 1;
|
||||
m_MSR.DR = 1;
|
||||
m_MSR.IR = 1;
|
||||
m_MSR.EE = 1;
|
||||
PowerPC::ppcState.spr[SPR_IBAT0U] = 0x80001fff;
|
||||
PowerPC::ppcState.spr[SPR_IBAT0L] = 0x00000002;
|
||||
PowerPC::ppcState.spr[SPR_IBAT4U] = 0x90001fff;
|
||||
PowerPC::ppcState.spr[SPR_IBAT4L] = 0x10000002;
|
||||
PowerPC::ppcState.spr[SPR_DBAT0U] = 0x80001fff;
|
||||
PowerPC::ppcState.spr[SPR_DBAT0L] = 0x00000002;
|
||||
PowerPC::ppcState.spr[SPR_DBAT1U] = 0xc0001fff;
|
||||
PowerPC::ppcState.spr[SPR_DBAT1L] = 0x0000002a;
|
||||
PowerPC::ppcState.spr[SPR_DBAT4U] = 0x90001fff;
|
||||
PowerPC::ppcState.spr[SPR_DBAT4L] = 0x10000002;
|
||||
PowerPC::ppcState.spr[SPR_DBAT5U] = 0xd0001fff;
|
||||
PowerPC::ppcState.spr[SPR_DBAT5L] = 0x1000002a;
|
||||
|
||||
dolLoader.Load();
|
||||
PC = dolLoader.GetEntryPoint();
|
||||
}
|
||||
|
@ -403,7 +422,7 @@ bool CBoot::BootUp()
|
|||
if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableCheats)
|
||||
{
|
||||
HLE::Patch(0x80001800, "HBReload");
|
||||
Memory::CopyToEmu(0x80001804, "STUBHAXX", 8);
|
||||
Memory::CopyToEmu(0x00001804, "STUBHAXX", 8);
|
||||
}
|
||||
|
||||
// Not part of the binary itself, but either we or Gecko OS might insert
|
||||
|
|
|
@ -41,6 +41,9 @@ bool CBoot::EmulatedBS2_GC(bool skipAppLoader)
|
|||
// Set up MSR and the BAT SPR registers.
|
||||
UReg_MSR& m_MSR = ((UReg_MSR&)PowerPC::ppcState.msr);
|
||||
m_MSR.FP = 1;
|
||||
m_MSR.DR = 1;
|
||||
m_MSR.IR = 1;
|
||||
m_MSR.EE = 1;
|
||||
PowerPC::ppcState.spr[SPR_IBAT0U] = 0x80001fff;
|
||||
PowerPC::ppcState.spr[SPR_IBAT0L] = 0x00000002;
|
||||
PowerPC::ppcState.spr[SPR_DBAT0U] = 0x80001fff;
|
||||
|
@ -54,28 +57,28 @@ bool CBoot::EmulatedBS2_GC(bool skipAppLoader)
|
|||
// Write necessary values
|
||||
// Here we write values to memory that the apploader does not take care of. Game info goes
|
||||
// to 0x80000000 according to YAGCD 4.2.
|
||||
DVDInterface::DVDRead(0x00000000, 0x80000000, 0x20, false); // write disc info
|
||||
DVDInterface::DVDRead(/*offset*/0x00000000, /*address*/0x00000000, 0x20, false); // write disc info
|
||||
|
||||
Memory::Write_U32(0x0D15EA5E, 0x80000020); // Booted from bootrom. 0xE5207C22 = booted from jtag
|
||||
Memory::Write_U32(Memory::REALRAM_SIZE, 0x80000028); // Physical Memory Size (24MB on retail)
|
||||
PowerPC::HostWrite_U32(0x0D15EA5E, 0x80000020); // Booted from bootrom. 0xE5207C22 = booted from jtag
|
||||
PowerPC::HostWrite_U32(Memory::REALRAM_SIZE, 0x80000028); // Physical Memory Size (24MB on retail)
|
||||
// TODO determine why some games fail when using a retail ID. (Seem to take different EXI paths, see Ikaruga for example)
|
||||
Memory::Write_U32(0x10000006, 0x8000002C); // Console type - DevKit (retail ID == 0x00000003) see YAGCD 4.2.1.1.2
|
||||
PowerPC::HostWrite_U32(0x10000006, 0x8000002C); // Console type - DevKit (retail ID == 0x00000003) see YAGCD 4.2.1.1.2
|
||||
|
||||
Memory::Write_U32(SConfig::GetInstance().m_LocalCoreStartupParameter.bNTSC
|
||||
PowerPC::HostWrite_U32(SConfig::GetInstance().m_LocalCoreStartupParameter.bNTSC
|
||||
? 0 : 1, 0x800000CC); // Fake the VI Init of the IPL (YAGCD 4.2.1.4)
|
||||
|
||||
Memory::Write_U32(0x01000000, 0x800000d0); // ARAM Size. 16MB main + 4/16/32MB external (retail consoles have no external ARAM)
|
||||
PowerPC::HostWrite_U32(0x01000000, 0x800000d0); // ARAM Size. 16MB main + 4/16/32MB external (retail consoles have no external ARAM)
|
||||
|
||||
Memory::Write_U32(0x09a7ec80, 0x800000F8); // Bus Clock Speed
|
||||
Memory::Write_U32(0x1cf7c580, 0x800000FC); // CPU Clock Speed
|
||||
PowerPC::HostWrite_U32(0x09a7ec80, 0x800000F8); // Bus Clock Speed
|
||||
PowerPC::HostWrite_U32(0x1cf7c580, 0x800000FC); // CPU Clock Speed
|
||||
|
||||
Memory::Write_U32(0x4c000064, 0x80000300); // Write default DFI Handler: rfi
|
||||
Memory::Write_U32(0x4c000064, 0x80000800); // Write default FPU Handler: rfi
|
||||
Memory::Write_U32(0x4c000064, 0x80000C00); // Write default Syscall Handler: rfi
|
||||
PowerPC::HostWrite_U32(0x4c000064, 0x80000300); // Write default DFI Handler: rfi
|
||||
PowerPC::HostWrite_U32(0x4c000064, 0x80000800); // Write default FPU Handler: rfi
|
||||
PowerPC::HostWrite_U32(0x4c000064, 0x80000C00); // Write default Syscall Handler: rfi
|
||||
|
||||
Memory::Write_U64((u64)CEXIIPL::GetGCTime() * (u64)40500000, 0x800030D8); // Preset time base ticks
|
||||
PowerPC::HostWrite_U64((u64)CEXIIPL::GetGCTime() * (u64)40500000, 0x800030D8); // Preset time base ticks
|
||||
// HIO checks this
|
||||
//Memory::Write_U16(0x8200, 0x000030e6); // Console type
|
||||
//PowerPC::HostWrite_U16(0x8200, 0x000030e6); // Console type
|
||||
|
||||
HLE::Patch(0x81300000, "OSReport"); // HLE OSReport for Apploader
|
||||
|
||||
|
@ -89,7 +92,7 @@ bool CBoot::EmulatedBS2_GC(bool skipAppLoader)
|
|||
INFO_LOG(BOOT, "GC BS2: Not running apploader!");
|
||||
return false;
|
||||
}
|
||||
VolumeHandler::ReadToPtr(Memory::GetPointer(0x81200000), iAppLoaderOffset + 0x20, iAppLoaderSize, false);
|
||||
DVDInterface::DVDRead(iAppLoaderOffset + 0x20, 0x01200000, iAppLoaderSize, false);
|
||||
|
||||
// Setup pointers like real BS2 does
|
||||
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bNTSC)
|
||||
|
@ -114,9 +117,9 @@ bool CBoot::EmulatedBS2_GC(bool skipAppLoader)
|
|||
PowerPC::ppcState.gpr[4] = iAppLoaderFuncAddr + 4;
|
||||
PowerPC::ppcState.gpr[5] = iAppLoaderFuncAddr + 8;
|
||||
RunFunction(iAppLoaderEntry);
|
||||
u32 iAppLoaderInit = Memory::ReadUnchecked_U32(iAppLoaderFuncAddr + 0);
|
||||
u32 iAppLoaderMain = Memory::ReadUnchecked_U32(iAppLoaderFuncAddr + 4);
|
||||
u32 iAppLoaderClose = Memory::ReadUnchecked_U32(iAppLoaderFuncAddr + 8);
|
||||
u32 iAppLoaderInit = PowerPC::Read_U32(iAppLoaderFuncAddr + 0);
|
||||
u32 iAppLoaderMain = PowerPC::Read_U32(iAppLoaderFuncAddr + 4);
|
||||
u32 iAppLoaderClose = PowerPC::Read_U32(iAppLoaderFuncAddr + 8);
|
||||
|
||||
// iAppLoaderInit
|
||||
DEBUG_LOG(MASTER_LOG, "Call iAppLoaderInit");
|
||||
|
@ -135,9 +138,9 @@ bool CBoot::EmulatedBS2_GC(bool skipAppLoader)
|
|||
|
||||
RunFunction(iAppLoaderMain);
|
||||
|
||||
u32 iRamAddress = Memory::ReadUnchecked_U32(0x81300004);
|
||||
u32 iLength = Memory::ReadUnchecked_U32(0x81300008);
|
||||
u32 iDVDOffset = Memory::ReadUnchecked_U32(0x8130000c);
|
||||
u32 iRamAddress = PowerPC::Read_U32(0x81300004);
|
||||
u32 iLength = PowerPC::Read_U32(0x81300008);
|
||||
u32 iDVDOffset = PowerPC::Read_U32(0x8130000c);
|
||||
|
||||
INFO_LOG(MASTER_LOG, "DVDRead: offset: %08x memOffset: %08x length: %i", iDVDOffset, iRamAddress, iLength);
|
||||
DVDInterface::DVDRead(iDVDOffset, iRamAddress, iLength, false);
|
||||
|
@ -239,7 +242,7 @@ bool CBoot::SetupWiiMemory(IVolume::ECountry country)
|
|||
0x80000060 Copyright code
|
||||
*/
|
||||
|
||||
DVDInterface::DVDRead(0x00000000, 0x00000000, 0x20, false); // Game Code
|
||||
DVDInterface::DVDRead(0x00000000, 0x00000000, 0x20, false); // Game Code
|
||||
Memory::Write_U32(0x0D15EA5E, 0x00000020); // Another magic word
|
||||
Memory::Write_U32(0x00000001, 0x00000024); // Unknown
|
||||
Memory::Write_U32(Memory::REALRAM_SIZE, 0x00000028); // MEM1 size 24MB
|
||||
|
@ -253,12 +256,12 @@ bool CBoot::SetupWiiMemory(IVolume::ECountry country)
|
|||
Memory::Write_U32(0x8179b500, 0x000000f4); // __start
|
||||
Memory::Write_U32(0x0e7be2c0, 0x000000f8); // Bus speed
|
||||
Memory::Write_U32(0x2B73A840, 0x000000fc); // CPU speed
|
||||
Memory::Write_U16(0x0000, 0x000030e6); // Console type
|
||||
Memory::Write_U16(0x0000, 0x000030e6); // Console type
|
||||
Memory::Write_U32(0x00000000, 0x000030c0); // EXI
|
||||
Memory::Write_U32(0x00000000, 0x000030c4); // EXI
|
||||
Memory::Write_U32(0x00000000, 0x000030dc); // Time
|
||||
Memory::Write_U32(0x00000000, 0x000030d8); // Time
|
||||
Memory::Write_U16(0x8201, 0x000030e6); // Dev console / debug capable
|
||||
Memory::Write_U16(0x8201, 0x000030e6); // Dev console / debug capable
|
||||
Memory::Write_U32(0x00000000, 0x000030f0); // Apploader
|
||||
Memory::Write_U32(0x01800000, 0x00003100); // BAT
|
||||
Memory::Write_U32(0x01800000, 0x00003104); // BAT
|
||||
|
@ -275,7 +278,7 @@ bool CBoot::SetupWiiMemory(IVolume::ECountry country)
|
|||
// 40 is copied from 88 after running apploader
|
||||
Memory::Write_U32(0x00090204, 0x00003140); // IOS revision (IOS9, v2.4)
|
||||
Memory::Write_U32(0x00062507, 0x00003144); // IOS date in USA format (June 25, 2007)
|
||||
Memory::Write_U16(0x0113, 0x0000315e); // Apploader
|
||||
Memory::Write_U16(0x0113, 0x0000315e); // Apploader
|
||||
Memory::Write_U32(0x0000FF16, 0x00003158); // DDR ram vendor code
|
||||
Memory::Write_U32(0x00000000, 0x00003160); // Init semaphore (sysmenu waits for this to clear)
|
||||
Memory::Write_U32(0x00090204, 0x00003188); // Expected IOS revision
|
||||
|
@ -290,7 +293,7 @@ bool CBoot::SetupWiiMemory(IVolume::ECountry country)
|
|||
// Clear exception handler. Why? Don't we begin with only zeros?
|
||||
for (int i = 0x3000; i <= 0x3038; i += 4)
|
||||
{
|
||||
Memory::Write_U32(0x00000000, 0x80000000 + i);
|
||||
Memory::Write_U32(0x00000000, i);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -314,7 +317,7 @@ bool CBoot::EmulatedBS2_Wii()
|
|||
// values as the game boots. This location keep the 4 byte ID for as long
|
||||
// as the game is running. The 6 byte ID at 0x00 is overwritten sometime
|
||||
// after this check during booting.
|
||||
VolumeHandler::ReadToPtr(Memory::GetPointer(0x3180), 0, 4, true);
|
||||
DVDInterface::DVDRead(0, 0x3180, 4, true);
|
||||
|
||||
// Execute the apploader
|
||||
bool apploaderRan = false;
|
||||
|
@ -323,9 +326,12 @@ bool CBoot::EmulatedBS2_Wii()
|
|||
// Set up MSR and the BAT SPR registers.
|
||||
UReg_MSR& m_MSR = ((UReg_MSR&)PowerPC::ppcState.msr);
|
||||
m_MSR.FP = 1;
|
||||
m_MSR.DR = 1;
|
||||
m_MSR.IR = 1;
|
||||
m_MSR.EE = 1;
|
||||
PowerPC::ppcState.spr[SPR_IBAT0U] = 0x80001fff;
|
||||
PowerPC::ppcState.spr[SPR_IBAT0L] = 0x00000002;
|
||||
PowerPC::ppcState.spr[SPR_IBAT4L] = 0x90001fff;
|
||||
PowerPC::ppcState.spr[SPR_IBAT4U] = 0x90001fff;
|
||||
PowerPC::ppcState.spr[SPR_IBAT4L] = 0x10000002;
|
||||
PowerPC::ppcState.spr[SPR_DBAT0U] = 0x80001fff;
|
||||
PowerPC::ppcState.spr[SPR_DBAT0L] = 0x00000002;
|
||||
|
@ -336,9 +342,9 @@ bool CBoot::EmulatedBS2_Wii()
|
|||
PowerPC::ppcState.spr[SPR_DBAT5U] = 0xd0001fff;
|
||||
PowerPC::ppcState.spr[SPR_DBAT5L] = 0x1000002a;
|
||||
|
||||
Memory::Write_U32(0x4c000064, 0x80000300); // Write default DFI Handler: rfi
|
||||
Memory::Write_U32(0x4c000064, 0x80000800); // Write default FPU Handler: rfi
|
||||
Memory::Write_U32(0x4c000064, 0x80000C00); // Write default Syscall Handler: rfi
|
||||
Memory::Write_U32(0x4c000064, 0x00000300); // Write default DSI Handler: rfi
|
||||
Memory::Write_U32(0x4c000064, 0x00000800); // Write default FPU Handler: rfi
|
||||
Memory::Write_U32(0x4c000064, 0x00000C00); // Write default Syscall Handler: rfi
|
||||
|
||||
HLE::Patch(0x81300000, "OSReport"); // HLE OSReport for Apploader
|
||||
|
||||
|
@ -354,7 +360,7 @@ bool CBoot::EmulatedBS2_Wii()
|
|||
ERROR_LOG(BOOT, "Invalid apploader. Probably your image is corrupted.");
|
||||
return false;
|
||||
}
|
||||
VolumeHandler::ReadToPtr(Memory::GetPointer(0x81200000), iAppLoaderOffset + 0x20, iAppLoaderSize, true);
|
||||
DVDInterface::DVDRead(iAppLoaderOffset + 0x20, 0x01200000, iAppLoaderSize, true);
|
||||
|
||||
//call iAppLoaderEntry
|
||||
DEBUG_LOG(BOOT, "Call iAppLoaderEntry");
|
||||
|
@ -364,9 +370,9 @@ bool CBoot::EmulatedBS2_Wii()
|
|||
PowerPC::ppcState.gpr[4] = iAppLoaderFuncAddr + 4;
|
||||
PowerPC::ppcState.gpr[5] = iAppLoaderFuncAddr + 8;
|
||||
RunFunction(iAppLoaderEntry);
|
||||
u32 iAppLoaderInit = Memory::ReadUnchecked_U32(iAppLoaderFuncAddr+0);
|
||||
u32 iAppLoaderMain = Memory::ReadUnchecked_U32(iAppLoaderFuncAddr+4);
|
||||
u32 iAppLoaderClose = Memory::ReadUnchecked_U32(iAppLoaderFuncAddr+8);
|
||||
u32 iAppLoaderInit = PowerPC::Read_U32(iAppLoaderFuncAddr + 0);
|
||||
u32 iAppLoaderMain = PowerPC::Read_U32(iAppLoaderFuncAddr + 4);
|
||||
u32 iAppLoaderClose = PowerPC::Read_U32(iAppLoaderFuncAddr + 8);
|
||||
|
||||
// iAppLoaderInit
|
||||
DEBUG_LOG(BOOT, "Run iAppLoaderInit");
|
||||
|
@ -387,9 +393,9 @@ bool CBoot::EmulatedBS2_Wii()
|
|||
|
||||
RunFunction(iAppLoaderMain);
|
||||
|
||||
u32 iRamAddress = Memory::ReadUnchecked_U32(0x81300004);
|
||||
u32 iLength = Memory::ReadUnchecked_U32(0x81300008);
|
||||
u32 iDVDOffset = Memory::ReadUnchecked_U32(0x8130000c) << 2;
|
||||
u32 iRamAddress = PowerPC::Read_U32(0x81300004);
|
||||
u32 iLength = PowerPC::Read_U32(0x81300008);
|
||||
u32 iDVDOffset = PowerPC::Read_U32(0x8130000c) << 2;
|
||||
|
||||
INFO_LOG(BOOT, "DVDRead: offset: %08x memOffset: %08x length: %i", iDVDOffset, iRamAddress, iLength);
|
||||
DVDInterface::DVDRead(iDVDOffset, iRamAddress, iLength, true);
|
||||
|
@ -404,8 +410,8 @@ bool CBoot::EmulatedBS2_Wii()
|
|||
// Pass the "#002 check"
|
||||
// Apploader writes the IOS version and revision here, we copy it
|
||||
// Fake IOSv9 r2.4 if no version is found (elf loading)
|
||||
u32 firmwareVer = Memory::Read_U32(0x80003188);
|
||||
Memory::Write_U32(firmwareVer ? firmwareVer : 0x00090204, 0x00003140);
|
||||
u32 firmwareVer = PowerPC::Read_U32(0x80003188);
|
||||
PowerPC::Write_U32(firmwareVer ? firmwareVer : 0x00090204, 0x80003140);
|
||||
|
||||
// Load patches and run startup patches
|
||||
PatchEngine::LoadPatches();
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "Core/Boot/Boot_DOL.h"
|
||||
#include "Core/HW/Memmap.h"
|
||||
#include "Core/PowerPC/PowerPC.h"
|
||||
|
||||
CDolLoader::CDolLoader(u8* _pBuffer, u32 _Size)
|
||||
: m_isWii(false)
|
||||
|
|
|
@ -107,7 +107,7 @@ bool CBoot::Boot_WiiWAD(const std::string& _pFilename)
|
|||
pDolLoader = std::make_unique<CDolLoader>(pContent->m_Filename);
|
||||
}
|
||||
pDolLoader->Load();
|
||||
PC = pDolLoader->GetEntryPoint() | 0x80000000;
|
||||
PC = pDolLoader->GetEntryPoint();
|
||||
|
||||
// Pass the "#002 check"
|
||||
// Apploader should write the IOS version and revision to 0x3140, and compare it
|
||||
|
|
|
@ -109,7 +109,6 @@ set(SRCS ActionReplay.cpp
|
|||
HW/GPFifo.cpp
|
||||
HW/HW.cpp
|
||||
HW/Memmap.cpp
|
||||
HW/MemmapFunctions.cpp
|
||||
HW/MemoryInterface.cpp
|
||||
HW/MMIO.cpp
|
||||
HW/ProcessorInterface.cpp
|
||||
|
@ -153,6 +152,7 @@ set(SRCS ActionReplay.cpp
|
|||
IPC_HLE/WII_IPC_HLE_Device_usb_kbd.cpp
|
||||
IPC_HLE/WII_IPC_HLE_WiiMote.cpp
|
||||
IPC_HLE/WiiMote_HID_Attr.cpp
|
||||
PowerPC/MMU.cpp
|
||||
PowerPC/PowerPC.cpp
|
||||
PowerPC/PPCAnalyst.cpp
|
||||
PowerPC/PPCCache.cpp
|
||||
|
|
|
@ -140,7 +140,6 @@
|
|||
<ClCompile Include="HW\GPFifo.cpp" />
|
||||
<ClCompile Include="HW\HW.cpp" />
|
||||
<ClCompile Include="HW\Memmap.cpp" />
|
||||
<ClCompile Include="HW\MemmapFunctions.cpp" />
|
||||
<ClCompile Include="HW\MemoryInterface.cpp" />
|
||||
<ClCompile Include="HW\MMIO.cpp" />
|
||||
<ClCompile Include="HW\ProcessorInterface.cpp" />
|
||||
|
@ -245,6 +244,7 @@
|
|||
<ClCompile Include="PowerPC\JitCommon\Jit_Util.cpp" />
|
||||
<ClCompile Include="PowerPC\JitCommon\TrampolineCache.cpp" />
|
||||
<ClCompile Include="PowerPC\JitInterface.cpp" />
|
||||
<ClCompile Include="PowerPC\MMU.cpp" />
|
||||
<ClCompile Include="PowerPC\PowerPC.cpp" />
|
||||
<ClCompile Include="PowerPC\PPCAnalyst.cpp" />
|
||||
<ClCompile Include="PowerPC\PPCCache.cpp" />
|
||||
|
|
|
@ -512,9 +512,6 @@
|
|||
<ClCompile Include="HW\Memmap.cpp">
|
||||
<Filter>HW %28Flipper/Hollywood%29</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="HW\MemmapFunctions.cpp">
|
||||
<Filter>HW %28Flipper/Hollywood%29</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="HW\MMIO.cpp">
|
||||
<Filter>HW %28Flipper/Hollywood%29</Filter>
|
||||
</ClCompile>
|
||||
|
@ -726,6 +723,8 @@
|
|||
</ClCompile>
|
||||
<ClCompile Include="HW\GCKeyboard.cpp">
|
||||
<Filter>HW %28Flipper/Hollywood%29\GCKeyboard</Filter>
|
||||
<ClCompile Include="PowerPC\MMU.cpp">
|
||||
<Filter>PowerPC</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
|
|
@ -39,27 +39,27 @@ void AddAutoBreakpoints()
|
|||
// Returns true if the address is not a valid RAM address or NULL.
|
||||
static bool IsStackBottom(u32 addr)
|
||||
{
|
||||
return !addr || !Memory::IsRAMAddress(addr);
|
||||
return !addr || !PowerPC::HostIsRAMAddress(addr);
|
||||
}
|
||||
|
||||
static void WalkTheStack(const std::function<void(u32)>& stack_step)
|
||||
{
|
||||
if (!IsStackBottom(PowerPC::ppcState.gpr[1]))
|
||||
{
|
||||
u32 addr = Memory::ReadUnchecked_U32(PowerPC::ppcState.gpr[1]); // SP
|
||||
u32 addr = PowerPC::HostRead_U32(PowerPC::ppcState.gpr[1]); // SP
|
||||
|
||||
// Walk the stack chain
|
||||
for (int count = 0;
|
||||
!IsStackBottom(addr + 4) && (count++ < 20);
|
||||
++count)
|
||||
{
|
||||
u32 func_addr = Memory::ReadUnchecked_U32(addr + 4);
|
||||
u32 func_addr = PowerPC::HostRead_U32(addr + 4);
|
||||
stack_step(func_addr);
|
||||
|
||||
if (IsStackBottom(addr))
|
||||
break;
|
||||
|
||||
addr = Memory::ReadUnchecked_U32(addr);
|
||||
addr = PowerPC::HostRead_U32(addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ static void WalkTheStack(const std::function<void(u32)>& stack_step)
|
|||
// instead of "pointing ahead"
|
||||
bool GetCallstack(std::vector<CallstackEntry> &output)
|
||||
{
|
||||
if (!Core::IsRunning() || !Memory::IsRAMAddress(PowerPC::ppcState.gpr[1]))
|
||||
if (!Core::IsRunning() || !PowerPC::HostIsRAMAddress(PowerPC::ppcState.gpr[1]))
|
||||
return false;
|
||||
|
||||
if (LR == 0)
|
||||
|
|
|
@ -19,26 +19,22 @@
|
|||
|
||||
std::string PPCDebugInterface::Disassemble(unsigned int address)
|
||||
{
|
||||
// Memory::ReadUnchecked_U32 seemed to crash on shutdown
|
||||
// PowerPC::HostRead_U32 seemed to crash on shutdown
|
||||
if (PowerPC::GetState() == PowerPC::CPU_POWERDOWN)
|
||||
return "";
|
||||
|
||||
if (Core::GetState() != Core::CORE_UNINITIALIZED)
|
||||
if (Core::GetState() == Core::CORE_PAUSE)
|
||||
{
|
||||
if (!Memory::IsRAMAddress(address, true, true))
|
||||
if (!PowerPC::HostIsRAMAddress(address))
|
||||
{
|
||||
if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bMMU || !((address & JIT_ICACHE_VMEM_BIT) &&
|
||||
Memory::TranslateAddress<Memory::FLAG_NO_EXCEPTION>(address)))
|
||||
{
|
||||
return "(No RAM here)";
|
||||
}
|
||||
return "(No RAM here)";
|
||||
}
|
||||
|
||||
u32 op = Memory::Read_Instruction(address);
|
||||
u32 op = PowerPC::HostRead_Instruction(address);
|
||||
std::string disasm = GekkoDisassembler::Disassemble(op, address);
|
||||
|
||||
UGeckoInstruction inst;
|
||||
inst.hex = Memory::ReadUnchecked_U32(address);
|
||||
inst.hex = PowerPC::HostRead_U32(address);
|
||||
|
||||
if (inst.OPCD == 1)
|
||||
{
|
||||
|
@ -57,7 +53,7 @@ void PPCDebugInterface::GetRawMemoryString(int memory, unsigned int address, cha
|
|||
{
|
||||
if (Core::GetState() != Core::CORE_UNINITIALIZED)
|
||||
{
|
||||
if (memory || Memory::IsRAMAddress(address, true, true))
|
||||
if (memory || PowerPC::HostIsRAMAddress(address))
|
||||
{
|
||||
snprintf(dest, max_size, "%08X%s", ReadExtraMemory(memory, address), memory ? " (ARAM)" : "");
|
||||
}
|
||||
|
@ -74,7 +70,7 @@ void PPCDebugInterface::GetRawMemoryString(int memory, unsigned int address, cha
|
|||
|
||||
unsigned int PPCDebugInterface::ReadMemory(unsigned int address)
|
||||
{
|
||||
return Memory::ReadUnchecked_U32(address);
|
||||
return PowerPC::HostRead_U32(address);
|
||||
}
|
||||
|
||||
unsigned int PPCDebugInterface::ReadExtraMemory(int memory, unsigned int address)
|
||||
|
@ -82,7 +78,7 @@ unsigned int PPCDebugInterface::ReadExtraMemory(int memory, unsigned int address
|
|||
switch (memory)
|
||||
{
|
||||
case 0:
|
||||
return Memory::ReadUnchecked_U32(address);
|
||||
return PowerPC::HostRead_U32(address);
|
||||
case 1:
|
||||
return (DSP::ReadARAM(address) << 24) |
|
||||
(DSP::ReadARAM(address + 1) << 16) |
|
||||
|
@ -95,7 +91,7 @@ unsigned int PPCDebugInterface::ReadExtraMemory(int memory, unsigned int address
|
|||
|
||||
unsigned int PPCDebugInterface::ReadInstruction(unsigned int address)
|
||||
{
|
||||
return Memory::Read_Instruction(address);
|
||||
return PowerPC::HostRead_Instruction(address);
|
||||
}
|
||||
|
||||
bool PPCDebugInterface::IsAlive()
|
||||
|
@ -170,7 +166,7 @@ void PPCDebugInterface::ToggleMemCheck(unsigned int address)
|
|||
|
||||
void PPCDebugInterface::InsertBLR(unsigned int address, unsigned int value)
|
||||
{
|
||||
Memory::Write_U32(value, address);
|
||||
PowerPC::HostWrite_U32(value, address);
|
||||
}
|
||||
|
||||
void PPCDebugInterface::BreakNow()
|
||||
|
@ -184,7 +180,9 @@ void PPCDebugInterface::BreakNow()
|
|||
// -------------
|
||||
int PPCDebugInterface::GetColor(unsigned int address)
|
||||
{
|
||||
if (!Memory::IsRAMAddress(address, true, true))
|
||||
if (!IsAlive())
|
||||
return 0xFFFFFF;
|
||||
if (!PowerPC::HostIsRAMAddress(address))
|
||||
return 0xeeeeee;
|
||||
static const int colors[6] =
|
||||
{
|
||||
|
|
|
@ -348,6 +348,17 @@ void FifoPlayer::SetupFifo()
|
|||
|
||||
void FifoPlayer::LoadMemory()
|
||||
{
|
||||
UReg_MSR newMSR;
|
||||
newMSR.DR = 1;
|
||||
newMSR.IR = 1;
|
||||
MSR = newMSR.Hex;
|
||||
PowerPC::ppcState.spr[SPR_IBAT0U] = 0x80001fff;
|
||||
PowerPC::ppcState.spr[SPR_IBAT0L] = 0x00000002;
|
||||
PowerPC::ppcState.spr[SPR_DBAT0U] = 0x80001fff;
|
||||
PowerPC::ppcState.spr[SPR_DBAT0L] = 0x00000002;
|
||||
PowerPC::ppcState.spr[SPR_DBAT1U] = 0xc0001fff;
|
||||
PowerPC::ppcState.spr[SPR_DBAT1L] = 0x0000002a;
|
||||
|
||||
Memory::Clear();
|
||||
|
||||
SetupFifo();
|
||||
|
@ -391,12 +402,12 @@ void FifoPlayer::LoadMemory()
|
|||
|
||||
void FifoPlayer::WriteCP(u32 address, u16 value)
|
||||
{
|
||||
Memory::Write_U16(value, 0xCC000000 | address);
|
||||
PowerPC::Write_U16(value, 0xCC000000 | address);
|
||||
}
|
||||
|
||||
void FifoPlayer::WritePI(u32 address, u32 value)
|
||||
{
|
||||
Memory::Write_U32(value, 0xCC003000 | address);
|
||||
PowerPC::Write_U32(value, 0xCC003000 | address);
|
||||
}
|
||||
|
||||
void FifoPlayer::FlushWGP()
|
||||
|
|
|
@ -90,16 +90,17 @@ static bool InstallCodeHandler()
|
|||
}
|
||||
|
||||
// Install code handler
|
||||
Memory::CopyToEmu(INSTALLER_BASE_ADDRESS, data.data(), data.length());
|
||||
for (size_t i = 0, e = data.length(); i < e; ++i)
|
||||
PowerPC::HostWrite_U8(data[i], (u32)(INSTALLER_BASE_ADDRESS + i));
|
||||
|
||||
// Patch the code handler to the system starting up
|
||||
for (unsigned int h = 0; h < data.length(); h += 4)
|
||||
{
|
||||
// Patch MMIO address
|
||||
if (Memory::ReadUnchecked_U32(INSTALLER_BASE_ADDRESS + h) == (0x3f000000u | ((mmioAddr ^ 1) << 8)))
|
||||
if (PowerPC::HostRead_U32(INSTALLER_BASE_ADDRESS + h) == (0x3f000000u | ((mmioAddr ^ 1) << 8)))
|
||||
{
|
||||
NOTICE_LOG(ACTIONREPLAY, "Patching MMIO access at %08x", INSTALLER_BASE_ADDRESS + h);
|
||||
Memory::Write_U32(0x3f000000u | mmioAddr << 8, INSTALLER_BASE_ADDRESS + h);
|
||||
PowerPC::HostWrite_U32(0x3f000000u | mmioAddr << 8, INSTALLER_BASE_ADDRESS + h);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -107,11 +108,11 @@ static bool InstallCodeHandler()
|
|||
u32 codelist_end_address = INSTALLER_END_ADDRESS;
|
||||
|
||||
// Write a magic value to 'gameid' (codehandleronly does not actually read this).
|
||||
Memory::Write_U32(0xd01f1bad, INSTALLER_BASE_ADDRESS);
|
||||
PowerPC::HostWrite_U32(0xd01f1bad, INSTALLER_BASE_ADDRESS);
|
||||
|
||||
// Create GCT in memory
|
||||
Memory::Write_U32(0x00d0c0de, codelist_base_address);
|
||||
Memory::Write_U32(0x00d0c0de, codelist_base_address + 4);
|
||||
PowerPC::HostWrite_U32(0x00d0c0de, codelist_base_address);
|
||||
PowerPC::HostWrite_U32(0x00d0c0de, codelist_base_address + 4);
|
||||
|
||||
std::lock_guard<std::mutex> lk(active_codes_lock);
|
||||
|
||||
|
@ -126,19 +127,19 @@ static bool InstallCodeHandler()
|
|||
// Make sure we have enough memory to hold the code list
|
||||
if ((codelist_base_address + 24 + i) < codelist_end_address)
|
||||
{
|
||||
Memory::Write_U32(code.address, codelist_base_address + 8 + i);
|
||||
Memory::Write_U32(code.data, codelist_base_address + 12 + i);
|
||||
PowerPC::HostWrite_U32(code.address, codelist_base_address + 8 + i);
|
||||
PowerPC::HostWrite_U32(code.data, codelist_base_address + 12 + i);
|
||||
i += 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Memory::Write_U32(0xff000000, codelist_base_address + 8 + i);
|
||||
Memory::Write_U32(0x00000000, codelist_base_address + 12 + i);
|
||||
PowerPC::HostWrite_U32(0xff000000, codelist_base_address + 8 + i);
|
||||
PowerPC::HostWrite_U32(0x00000000, codelist_base_address + 12 + i);
|
||||
|
||||
// Turn on codes
|
||||
Memory::Write_U8(1, INSTALLER_BASE_ADDRESS + 7);
|
||||
PowerPC::HostWrite_U8(1, INSTALLER_BASE_ADDRESS + 7);
|
||||
|
||||
// Invalidate the icache and any asm codes
|
||||
for (unsigned int j = 0; j < (INSTALLER_END_ADDRESS - INSTALLER_BASE_ADDRESS); j += 32)
|
||||
|
@ -156,7 +157,7 @@ void RunCodeHandler()
|
|||
{
|
||||
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableCheats && active_codes.size() > 0)
|
||||
{
|
||||
if (!code_handler_installed || Memory::Read_U32(INSTALLER_BASE_ADDRESS) - 0xd01f1bad > 5)
|
||||
if (!code_handler_installed || PowerPC::HostRead_U32(INSTALLER_BASE_ADDRESS) - 0xd01f1bad > 5)
|
||||
code_handler_installed = InstallCodeHandler();
|
||||
|
||||
if (!code_handler_installed)
|
||||
|
|
|
@ -63,7 +63,7 @@ void HLEGeckoCodehandler()
|
|||
// robust alternative would be to actually detect memory writes, but that
|
||||
// would be even uglier.)
|
||||
u32 magic = 0xd01f1bad;
|
||||
u32 existing = Memory::Read_U32(0x80001800);
|
||||
u32 existing = PowerPC::HostRead_U32(0x80001800);
|
||||
if (existing - magic == 5)
|
||||
{
|
||||
return;
|
||||
|
@ -72,7 +72,7 @@ void HLEGeckoCodehandler()
|
|||
{
|
||||
existing = magic;
|
||||
}
|
||||
Memory::Write_U32(existing + 1, 0x80001800);
|
||||
PowerPC::HostWrite_U32(existing + 1, 0x80001800);
|
||||
PowerPC::ppcState.iCache.Reset();
|
||||
}
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ void HLE_OSPanic()
|
|||
void HLE_GeneralDebugPrint()
|
||||
{
|
||||
std::string ReportMessage;
|
||||
if (Memory::Read_U32(GPR(3)) > 0x80000000)
|
||||
if (PowerPC::HostRead_U32(GPR(3)) > 0x80000000)
|
||||
{
|
||||
GetStringVA(ReportMessage, 4);
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ void GetStringVA(std::string& _rOutBuffer, u32 strReg)
|
|||
std::string ArgumentBuffer = "";
|
||||
u32 ParameterCounter = strReg+1;
|
||||
u32 FloatingParameterCounter = 1;
|
||||
std::string string = Memory::GetString(GPR(strReg));
|
||||
std::string string = PowerPC::HostGetString(GPR(strReg));
|
||||
|
||||
for(u32 i = 0; i < string.size(); i++)
|
||||
{
|
||||
|
@ -84,7 +84,7 @@ void GetStringVA(std::string& _rOutBuffer, u32 strReg)
|
|||
u64 Parameter;
|
||||
if (ParameterCounter > 10)
|
||||
{
|
||||
Parameter = Memory::Read_U32(GPR(1) + 0x8 + ((ParameterCounter - 11) * 4));
|
||||
Parameter = PowerPC::HostRead_U32(GPR(1) + 0x8 + ((ParameterCounter - 11) * 4));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -101,7 +101,7 @@ void GetStringVA(std::string& _rOutBuffer, u32 strReg)
|
|||
switch (string[i])
|
||||
{
|
||||
case 's':
|
||||
_rOutBuffer += StringFromFormat(ArgumentBuffer.c_str(), Memory::GetString((u32)Parameter).c_str());
|
||||
_rOutBuffer += StringFromFormat(ArgumentBuffer.c_str(), PowerPC::HostGetString((u32)Parameter).c_str());
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
|
@ -135,7 +135,7 @@ void GetStringVA(std::string& _rOutBuffer, u32 strReg)
|
|||
_rOutBuffer += string[i];
|
||||
}
|
||||
}
|
||||
if (_rOutBuffer[_rOutBuffer.length() - 1] == '\n')
|
||||
if (!_rOutBuffer.empty() && _rOutBuffer[_rOutBuffer.length() - 1] == '\n')
|
||||
_rOutBuffer.resize(_rOutBuffer.length() - 1);
|
||||
}
|
||||
|
||||
|
|
|
@ -58,12 +58,12 @@ void DSPDebugInterface::GetRawMemoryString(int memory, unsigned int address, cha
|
|||
|
||||
unsigned int DSPDebugInterface::ReadMemory(unsigned int address)
|
||||
{
|
||||
return 0; //Memory::ReadUnchecked_U32(address);
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int DSPDebugInterface::ReadInstruction(unsigned int address)
|
||||
{
|
||||
return 0; //Memory::Read_Instruction(address);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool DSPDebugInterface::IsAlive()
|
||||
|
|
|
@ -185,7 +185,9 @@ bool DSPLLE::Initialize(bool bWii, bool bDSPThread)
|
|||
return false;
|
||||
|
||||
// DSPLLE directly accesses the fastmem arena.
|
||||
g_dsp.cpu_ram = Memory::base;
|
||||
// TODO: The fastmem arena is only supposed to be used by the JIT:
|
||||
// among other issues, its size is only 1GB on 32-bit targets.
|
||||
g_dsp.cpu_ram = Memory::physical_base;
|
||||
DSPCore_Reset();
|
||||
|
||||
InitInstructionTable();
|
||||
|
|
|
@ -470,7 +470,7 @@ void SetLidOpen(bool _bOpen)
|
|||
|
||||
bool DVDRead(u64 _iDVDOffset, u32 _iRamAddress, u32 _iLength, bool decrypt)
|
||||
{
|
||||
return VolumeHandler::ReadToPtr(Memory::GetPointer(_iRamAddress), _iDVDOffset, _iLength, decrypt);
|
||||
return VolumeHandler::ReadToPtr(Memory::GetPointer(_iRamAddress), _iDVDOffset, _iLength, decrypt);
|
||||
}
|
||||
|
||||
void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
|
||||
|
|
|
@ -53,7 +53,8 @@ static bool bMMU = false;
|
|||
// Init() declarations
|
||||
// ----------------
|
||||
// Store the MemArena here
|
||||
u8* base = nullptr;
|
||||
u8* physical_base = nullptr;
|
||||
u8* logical_base = nullptr;
|
||||
|
||||
// The MemArena class
|
||||
static MemArena g_arena;
|
||||
|
@ -106,13 +107,14 @@ bool IsInitialized()
|
|||
static MemoryView views[] =
|
||||
{
|
||||
{&m_pRAM, 0x00000000, RAM_SIZE, 0},
|
||||
{nullptr, 0x80000000, RAM_SIZE, MV_MIRROR_PREVIOUS},
|
||||
{nullptr, 0xC0000000, RAM_SIZE, MV_MIRROR_PREVIOUS},
|
||||
{&m_pL1Cache, 0xE0000000, L1_CACHE_SIZE, 0},
|
||||
{&m_pFakeVMEM, 0x7E000000, FAKEVMEM_SIZE, MV_FAKE_VMEM},
|
||||
{nullptr, 0x200000000, RAM_SIZE, MV_MIRROR_PREVIOUS},
|
||||
{nullptr, 0x280000000, RAM_SIZE, MV_MIRROR_PREVIOUS},
|
||||
{nullptr, 0x2C0000000, RAM_SIZE, MV_MIRROR_PREVIOUS},
|
||||
{&m_pL1Cache, 0x2E0000000, L1_CACHE_SIZE, 0},
|
||||
{&m_pFakeVMEM, 0x27E000000, FAKEVMEM_SIZE, MV_FAKE_VMEM},
|
||||
{&m_pEXRAM, 0x10000000, EXRAM_SIZE, MV_WII_ONLY},
|
||||
{nullptr, 0x90000000, EXRAM_SIZE, MV_WII_ONLY | MV_MIRROR_PREVIOUS},
|
||||
{nullptr, 0xD0000000, EXRAM_SIZE, MV_WII_ONLY | MV_MIRROR_PREVIOUS},
|
||||
{nullptr, 0x290000000, EXRAM_SIZE, MV_WII_ONLY | MV_MIRROR_PREVIOUS},
|
||||
{nullptr, 0x2D0000000, EXRAM_SIZE, MV_WII_ONLY | MV_MIRROR_PREVIOUS},
|
||||
};
|
||||
static const int num_views = sizeof(views) / sizeof(MemoryView);
|
||||
|
||||
|
@ -129,7 +131,10 @@ void Init()
|
|||
u32 flags = 0;
|
||||
if (wii) flags |= MV_WII_ONLY;
|
||||
if (bFakeVMEM) flags |= MV_FAKE_VMEM;
|
||||
base = MemoryMap_Setup(views, num_views, flags, &g_arena);
|
||||
physical_base = MemoryMap_Setup(views, num_views, flags, &g_arena);
|
||||
#ifndef _ARCH_32
|
||||
logical_base = physical_base + 0x200000000;
|
||||
#endif
|
||||
|
||||
mmio_mapping = new MMIO::Mapping();
|
||||
|
||||
|
@ -164,7 +169,8 @@ void Shutdown()
|
|||
if (bFakeVMEM) flags |= MV_FAKE_VMEM;
|
||||
MemoryMap_Shutdown(views, num_views, flags, &g_arena);
|
||||
g_arena.ReleaseSHMSegment();
|
||||
base = nullptr;
|
||||
physical_base = nullptr;
|
||||
logical_base = nullptr;
|
||||
delete mmio_mapping;
|
||||
INFO_LOG(MEMMAP, "Memory system shut down.");
|
||||
}
|
||||
|
@ -188,12 +194,6 @@ bool AreMemoryBreakpointsActivated()
|
|||
#endif
|
||||
}
|
||||
|
||||
u32 Read_Instruction(const u32 address)
|
||||
{
|
||||
UGeckoInstruction inst = ReadUnchecked_U32(address);
|
||||
return inst.hex;
|
||||
}
|
||||
|
||||
static inline bool ValidCopyRange(u32 address, size_t size)
|
||||
{
|
||||
return (GetPointer(address) != nullptr &&
|
||||
|
@ -228,19 +228,6 @@ void Memset(const u32 _Address, const u8 _iValue, const u32 _iLength)
|
|||
{
|
||||
memset(ptr,_iValue,_iLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (u32 i = 0; i < _iLength; i++)
|
||||
Write_U8(_iValue, _Address + i);
|
||||
}
|
||||
}
|
||||
|
||||
void ClearCacheLine(const u32 address)
|
||||
{
|
||||
// FIXME: does this do the right thing if dcbz is run on hardware memory, e.g.
|
||||
// the FIFO? Do games even do that? Probably not, but we should try to be correct...
|
||||
for (u32 i = 0; i < 32; i += 8)
|
||||
Write_U64(0, address + i);
|
||||
}
|
||||
|
||||
std::string GetString(u32 em_address, size_t size)
|
||||
|
@ -260,93 +247,73 @@ std::string GetString(u32 em_address, size_t size)
|
|||
}
|
||||
}
|
||||
|
||||
// GetPointer must always return an address in the bottom 32 bits of address space, so that 64-bit
|
||||
// programs don't have problems directly addressing any part of memory.
|
||||
// TODO re-think with respect to other BAT setups...
|
||||
u8* GetPointer(const u32 address)
|
||||
u8* GetPointer(u32 address)
|
||||
{
|
||||
switch (address >> 28)
|
||||
// TODO: Should we be masking off more bits here? Can all devices access
|
||||
// EXRAM?
|
||||
address &= 0x3FFFFFFF;
|
||||
if (address < REALRAM_SIZE)
|
||||
return m_pRAM + address;
|
||||
|
||||
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bWii)
|
||||
{
|
||||
case 0x0:
|
||||
case 0x8:
|
||||
if ((address & 0xfffffff) < REALRAM_SIZE)
|
||||
return m_pRAM + (address & RAM_MASK);
|
||||
break;
|
||||
case 0xc:
|
||||
switch (address >> 24)
|
||||
{
|
||||
case 0xcc:
|
||||
case 0xcd:
|
||||
_dbg_assert_msg_(MEMMAP, 0, "GetPointer from IO Bridge doesnt work");
|
||||
break;
|
||||
case 0xc8:
|
||||
// EFB. We don't want to return a pointer here since we have no memory mapped for it.
|
||||
break;
|
||||
|
||||
default:
|
||||
if ((address & 0xfffffff) < REALRAM_SIZE)
|
||||
return m_pRAM + (address & RAM_MASK);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x1:
|
||||
case 0x9:
|
||||
case 0xd:
|
||||
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bWii)
|
||||
{
|
||||
if ((address & 0xfffffff) < EXRAM_SIZE)
|
||||
return m_pEXRAM + (address & EXRAM_MASK);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xe:
|
||||
if (address < (0xE0000000 + L1_CACHE_SIZE))
|
||||
return m_pL1Cache + (address & L1_CACHE_MASK);
|
||||
else
|
||||
break;
|
||||
|
||||
default:
|
||||
if (bFakeVMEM)
|
||||
return m_pFakeVMEM + (address & FAKEVMEM_MASK);
|
||||
break;
|
||||
if ((address >> 28) == 0x1 && (address & 0x0fffffff) < EXRAM_SIZE)
|
||||
return m_pEXRAM + (address & EXRAM_MASK);
|
||||
}
|
||||
|
||||
ERROR_LOG(MEMMAP, "Unknown Pointer %#8x PC %#8x LR %#8x", address, PC, LR);
|
||||
PanicAlert("Unknown Pointer 0x%08x PC 0x%08x LR 0x%08x", address, PC, LR);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool IsRAMAddress(const u32 address, bool allow_locked_cache, bool allow_fake_vmem)
|
||||
u8 Read_U8(u32 address)
|
||||
{
|
||||
switch ((address >> 24) & 0xFC)
|
||||
{
|
||||
case 0x00:
|
||||
case 0x80:
|
||||
case 0xC0:
|
||||
if ((address & 0x1FFFFFFF) < RAM_SIZE)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
case 0x10:
|
||||
case 0x90:
|
||||
case 0xD0:
|
||||
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bWii && (address & 0x0FFFFFFF) < EXRAM_SIZE)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
case 0xE0:
|
||||
if (allow_locked_cache && address - 0xE0000000 < L1_CACHE_SIZE)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
case 0x7C:
|
||||
if (allow_fake_vmem && bFakeVMEM && address >= 0x7E000000)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return *GetPointer(address);
|
||||
}
|
||||
|
||||
u16 Read_U16(u32 address)
|
||||
{
|
||||
return Common::swap16(GetPointer(address));
|
||||
}
|
||||
|
||||
u32 Read_U32(u32 address)
|
||||
{
|
||||
return Common::swap32(GetPointer(address));
|
||||
}
|
||||
|
||||
u64 Read_U64(u32 address)
|
||||
{
|
||||
return Common::swap64(GetPointer(address));
|
||||
}
|
||||
|
||||
void Write_U8(u8 value, u32 address)
|
||||
{
|
||||
*GetPointer(address) = value;
|
||||
}
|
||||
|
||||
void Write_U16(u16 value, u32 address)
|
||||
{
|
||||
*(u16*)GetPointer(address) = Common::swap16(value);
|
||||
}
|
||||
|
||||
void Write_U32(u32 value, u32 address)
|
||||
{
|
||||
*(u32*)GetPointer(address) = Common::swap32(value);
|
||||
}
|
||||
|
||||
void Write_U64(u64 value, u32 address)
|
||||
{
|
||||
*(u64*)GetPointer(address) = Common::swap64(value);
|
||||
}
|
||||
|
||||
void Write_U32_Swap(u32 value, u32 address)
|
||||
{
|
||||
*(u32*)GetPointer(address) = value;
|
||||
}
|
||||
|
||||
void Write_U64_Swap(u64 value, u32 address)
|
||||
{
|
||||
*(u64*)GetPointer(address) = value;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -27,7 +27,8 @@ namespace Memory
|
|||
|
||||
// In 64-bit, this might point to "high memory" (above the 32-bit limit),
|
||||
// so be sure to load it into a 64-bit register.
|
||||
extern u8* base;
|
||||
extern u8* physical_base;
|
||||
extern u8* logical_base;
|
||||
|
||||
// These are guaranteed to point to "low memory" addresses (sub-32-bit).
|
||||
extern u8* m_pRAM;
|
||||
|
@ -73,70 +74,22 @@ void DoState(PointerWrap &p);
|
|||
void Clear();
|
||||
bool AreMemoryBreakpointsActivated();
|
||||
|
||||
// ONLY for use by GUI
|
||||
u8 ReadUnchecked_U8(const u32 address);
|
||||
u32 ReadUnchecked_U32(const u32 address);
|
||||
|
||||
void WriteUnchecked_U8(const u8 var, const u32 address);
|
||||
void WriteUnchecked_U32(const u32 var, const u32 address);
|
||||
|
||||
bool IsRAMAddress(const u32 address, bool allow_locked_cache = false, bool allow_fake_vmem = false);
|
||||
|
||||
// used by interpreter to read instructions, uses iCache
|
||||
u32 Read_Opcode(const u32 address);
|
||||
// this is used by Debugger a lot.
|
||||
// For now, just reads from memory!
|
||||
u32 Read_Instruction(const u32 address);
|
||||
|
||||
|
||||
// For use by emulator
|
||||
|
||||
// Routines to access physically addressed memory, designed for use by
|
||||
// emulated hardware outside the CPU. Use "Device_" prefix.
|
||||
std::string GetString(u32 em_address, size_t size = 0);
|
||||
u8* GetPointer(const u32 address);
|
||||
void CopyFromEmu(void* data, u32 address, size_t size);
|
||||
void CopyToEmu(u32 address, const void* data, size_t size);
|
||||
void Memset(const u32 address, const u8 var, const u32 length);
|
||||
u8 Read_U8(const u32 address);
|
||||
u16 Read_U16(const u32 address);
|
||||
u32 Read_U32(const u32 address);
|
||||
u64 Read_U64(const u32 address);
|
||||
|
||||
// Useful helper functions, used by ARM JIT
|
||||
float Read_F32(const u32 address);
|
||||
double Read_F64(const u32 address);
|
||||
|
||||
// used by JIT. Return zero-extended 32bit values
|
||||
u32 Read_U8_ZX(const u32 address);
|
||||
u32 Read_U16_ZX(const u32 address);
|
||||
|
||||
void Write_U8(const u8 var, const u32 address);
|
||||
void Write_U16(const u16 var, const u32 address);
|
||||
void Write_U32(const u32 var, const u32 address);
|
||||
void Write_U64(const u64 var, const u32 address);
|
||||
|
||||
void Write_U16_Swap(const u16 var, const u32 address);
|
||||
void Write_U32_Swap(const u32 var, const u32 address);
|
||||
void Write_U64_Swap(const u64 var, const u32 address);
|
||||
|
||||
// Useful helper functions, used by ARM JIT
|
||||
void Write_F64(const double var, const u32 address);
|
||||
|
||||
std::string GetString(u32 em_address, size_t size = 0);
|
||||
|
||||
u8* GetPointer(const u32 address);
|
||||
void DMA_LCToMemory(const u32 memAddr, const u32 cacheAddr, const u32 numBlocks);
|
||||
void DMA_MemoryToLC(const u32 cacheAddr, const u32 memAddr, const u32 numBlocks);
|
||||
void CopyFromEmu(void* data, u32 address, size_t size);
|
||||
void CopyToEmu(u32 address, const void* data, size_t size);
|
||||
void Memset(const u32 address, const u8 var, const u32 length);
|
||||
void ClearCacheLine(const u32 address); // Zeroes 32 bytes; address should be 32-byte-aligned
|
||||
|
||||
// TLB functions
|
||||
void SDRUpdated();
|
||||
enum XCheckTLBFlag
|
||||
{
|
||||
FLAG_NO_EXCEPTION,
|
||||
FLAG_READ,
|
||||
FLAG_WRITE,
|
||||
FLAG_OPCODE,
|
||||
};
|
||||
template <const XCheckTLBFlag flag> u32 TranslateAddress(const u32 address);
|
||||
void InvalidateTLBEntry(u32 address);
|
||||
extern u32 pagetable_base;
|
||||
extern u32 pagetable_hashmask;
|
||||
}
|
||||
|
|
|
@ -194,7 +194,6 @@ static void PatchEngineCallback(u64 userdata, int cyclesLate)
|
|||
{
|
||||
// Patch mem and run the Action Replay
|
||||
PatchEngine::ApplyFramePatches();
|
||||
PatchEngine::ApplyARPatches();
|
||||
CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerFrame() - cyclesLate, et_PatchEngine);
|
||||
}
|
||||
|
||||
|
|
|
@ -925,7 +925,7 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
|
|||
pDolLoader = std::make_unique<CDolLoader>(pContent->m_Filename);
|
||||
}
|
||||
pDolLoader->Load(); // TODO: Check why sysmenu does not load the DOL correctly
|
||||
PC = pDolLoader->GetEntryPoint() | 0x80000000;
|
||||
PC = pDolLoader->GetEntryPoint();
|
||||
IOSv = ContentLoader.GetIosVersion();
|
||||
bSuccess = true;
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
#include "Core/GeckoCode.h"
|
||||
#include "Core/GeckoCodeConfig.h"
|
||||
#include "Core/PatchEngine.h"
|
||||
#include "Core/HW/Memmap.h"
|
||||
#include "Core/PowerPC/PowerPC.h"
|
||||
|
||||
using namespace Common;
|
||||
|
||||
|
@ -188,13 +188,13 @@ static void ApplyPatches(const std::vector<Patch> &patches)
|
|||
switch (entry.type)
|
||||
{
|
||||
case PATCH_8BIT:
|
||||
Memory::Write_U8((u8)value, addr);
|
||||
PowerPC::HostWrite_U8((u8)value, addr);
|
||||
break;
|
||||
case PATCH_16BIT:
|
||||
Memory::Write_U16((u16)value, addr);
|
||||
PowerPC::HostWrite_U16((u16)value, addr);
|
||||
break;
|
||||
case PATCH_32BIT:
|
||||
Memory::Write_U32(value, addr);
|
||||
PowerPC::HostWrite_U32(value, addr);
|
||||
break;
|
||||
default:
|
||||
//unknown patchtype
|
||||
|
@ -207,15 +207,20 @@ static void ApplyPatches(const std::vector<Patch> &patches)
|
|||
|
||||
void ApplyFramePatches()
|
||||
{
|
||||
// TODO: Messing with MSR this way is really, really, evil; we should
|
||||
// probably be using some sort of Gecko OS-style hooking mechanism
|
||||
// so the emulated CPU is in a predictable state when we process cheats.
|
||||
u32 oldMSR = MSR;
|
||||
UReg_MSR newMSR = oldMSR;
|
||||
newMSR.IR = 1;
|
||||
newMSR.DR = 1;
|
||||
MSR = newMSR.Hex;
|
||||
ApplyPatches(onFrame);
|
||||
|
||||
// Run the Gecko code handler
|
||||
Gecko::RunCodeHandler();
|
||||
}
|
||||
|
||||
void ApplyARPatches()
|
||||
{
|
||||
ActionReplay::RunAllActive();
|
||||
MSR = oldMSR;
|
||||
}
|
||||
|
||||
void Shutdown()
|
||||
|
|
|
@ -45,7 +45,6 @@ void LoadPatchSection(const std::string& section, std::vector<Patch> &patches,
|
|||
IniFile &globalIni, IniFile &localIni);
|
||||
void LoadPatches();
|
||||
void ApplyFramePatches();
|
||||
void ApplyARPatches();
|
||||
void Shutdown();
|
||||
|
||||
inline int GetPatchTypeCharLength(PatchType type)
|
||||
|
|
|
@ -107,7 +107,7 @@ int Interpreter::SingleStepInner()
|
|||
#endif
|
||||
|
||||
NPC = PC + sizeof(UGeckoInstruction);
|
||||
instCode.hex = Memory::Read_Opcode(PC);
|
||||
instCode.hex = PowerPC::Read_Opcode(PC);
|
||||
|
||||
// Uncomment to trace the interpreter
|
||||
//if ((PC & 0xffffff)>=0x0ab54c && (PC & 0xffffff)<=0x0ab624)
|
||||
|
@ -283,7 +283,7 @@ void Interpreter::unknown_instruction(UGeckoInstruction _inst)
|
|||
{
|
||||
if (_inst.hex != 0)
|
||||
{
|
||||
std::string disasm = GekkoDisassembler::Disassemble(Memory::ReadUnchecked_U32(last_pc), last_pc);
|
||||
std::string disasm = GekkoDisassembler::Disassemble(PowerPC::HostRead_U32(last_pc), last_pc);
|
||||
NOTICE_LOG(POWERPC, "Last PC = %08x : %s", last_pc, disasm.c_str());
|
||||
Dolphin_Debugger::PrintCallstack();
|
||||
_assert_msg_(POWERPC, 0, "\nIntCPU: Unknown instruction %08x at PC = %08x last_PC = %08x LR = %08x\n", _inst.hex, PC, last_pc, LR);
|
||||
|
|
|
@ -36,7 +36,7 @@ u32 Interpreter::Helper_Get_EA_UX(const UGeckoInstruction _inst)
|
|||
|
||||
void Interpreter::lbz(UGeckoInstruction _inst)
|
||||
{
|
||||
u32 temp = (u32)Memory::Read_U8(Helper_Get_EA(_inst));
|
||||
u32 temp = (u32)PowerPC::Read_U8(Helper_Get_EA(_inst));
|
||||
if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
|
||||
rGPR[_inst.RD] = temp;
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ void Interpreter::lbz(UGeckoInstruction _inst)
|
|||
void Interpreter::lbzu(UGeckoInstruction _inst)
|
||||
{
|
||||
u32 uAddress = Helper_Get_EA_U(_inst);
|
||||
u32 temp = (u32)Memory::Read_U8(uAddress);
|
||||
u32 temp = (u32)PowerPC::Read_U8(uAddress);
|
||||
if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
|
||||
{
|
||||
rGPR[_inst.RD] = temp;
|
||||
|
@ -54,7 +54,7 @@ void Interpreter::lbzu(UGeckoInstruction _inst)
|
|||
|
||||
void Interpreter::lfd(UGeckoInstruction _inst)
|
||||
{
|
||||
u64 temp = Memory::Read_U64(Helper_Get_EA(_inst));
|
||||
u64 temp = PowerPC::Read_U64(Helper_Get_EA(_inst));
|
||||
if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
|
||||
riPS0(_inst.FD) = temp;
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ void Interpreter::lfd(UGeckoInstruction _inst)
|
|||
void Interpreter::lfdu(UGeckoInstruction _inst)
|
||||
{
|
||||
u32 uAddress = Helper_Get_EA_U(_inst);
|
||||
u64 temp = Memory::Read_U64(uAddress);
|
||||
u64 temp = PowerPC::Read_U64(uAddress);
|
||||
if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
|
||||
{
|
||||
riPS0(_inst.FD) = temp;
|
||||
|
@ -73,7 +73,7 @@ void Interpreter::lfdu(UGeckoInstruction _inst)
|
|||
void Interpreter::lfdux(UGeckoInstruction _inst)
|
||||
{
|
||||
u32 uAddress = Helper_Get_EA_UX(_inst);
|
||||
u64 temp = Memory::Read_U64(uAddress);
|
||||
u64 temp = PowerPC::Read_U64(uAddress);
|
||||
if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
|
||||
{
|
||||
riPS0(_inst.FD) = temp;
|
||||
|
@ -83,14 +83,14 @@ void Interpreter::lfdux(UGeckoInstruction _inst)
|
|||
|
||||
void Interpreter::lfdx(UGeckoInstruction _inst)
|
||||
{
|
||||
u64 temp = Memory::Read_U64(Helper_Get_EA_X(_inst));
|
||||
u64 temp = PowerPC::Read_U64(Helper_Get_EA_X(_inst));
|
||||
if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
|
||||
riPS0(_inst.FD) = temp;
|
||||
}
|
||||
|
||||
void Interpreter::lfs(UGeckoInstruction _inst)
|
||||
{
|
||||
u32 uTemp = Memory::Read_U32(Helper_Get_EA(_inst));
|
||||
u32 uTemp = PowerPC::Read_U32(Helper_Get_EA(_inst));
|
||||
if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
|
||||
{
|
||||
u64 value = ConvertToDouble(uTemp);
|
||||
|
@ -102,7 +102,7 @@ void Interpreter::lfs(UGeckoInstruction _inst)
|
|||
void Interpreter::lfsu(UGeckoInstruction _inst)
|
||||
{
|
||||
u32 uAddress = Helper_Get_EA_U(_inst);
|
||||
u32 uTemp = Memory::Read_U32(uAddress);
|
||||
u32 uTemp = PowerPC::Read_U32(uAddress);
|
||||
if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
|
||||
{
|
||||
u64 value = ConvertToDouble(uTemp);
|
||||
|
@ -116,7 +116,7 @@ void Interpreter::lfsu(UGeckoInstruction _inst)
|
|||
void Interpreter::lfsux(UGeckoInstruction _inst)
|
||||
{
|
||||
u32 uAddress = Helper_Get_EA_UX(_inst);
|
||||
u32 uTemp = Memory::Read_U32(uAddress);
|
||||
u32 uTemp = PowerPC::Read_U32(uAddress);
|
||||
if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
|
||||
{
|
||||
u64 value = ConvertToDouble(uTemp);
|
||||
|
@ -128,7 +128,7 @@ void Interpreter::lfsux(UGeckoInstruction _inst)
|
|||
|
||||
void Interpreter::lfsx(UGeckoInstruction _inst)
|
||||
{
|
||||
u32 uTemp = Memory::Read_U32(Helper_Get_EA_X(_inst));
|
||||
u32 uTemp = PowerPC::Read_U32(Helper_Get_EA_X(_inst));
|
||||
if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
|
||||
{
|
||||
u64 value = ConvertToDouble(uTemp);
|
||||
|
@ -139,7 +139,7 @@ void Interpreter::lfsx(UGeckoInstruction _inst)
|
|||
|
||||
void Interpreter::lha(UGeckoInstruction _inst)
|
||||
{
|
||||
u32 temp = (u32)(s32)(s16)Memory::Read_U16(Helper_Get_EA(_inst));
|
||||
u32 temp = (u32)(s32)(s16)PowerPC::Read_U16(Helper_Get_EA(_inst));
|
||||
if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
|
||||
{
|
||||
rGPR[_inst.RD] = temp;
|
||||
|
@ -149,7 +149,7 @@ void Interpreter::lha(UGeckoInstruction _inst)
|
|||
void Interpreter::lhau(UGeckoInstruction _inst)
|
||||
{
|
||||
u32 uAddress = Helper_Get_EA_U(_inst);
|
||||
u32 temp = (u32)(s32)(s16)Memory::Read_U16(uAddress);
|
||||
u32 temp = (u32)(s32)(s16)PowerPC::Read_U16(uAddress);
|
||||
if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
|
||||
{
|
||||
rGPR[_inst.RD] = temp;
|
||||
|
@ -159,7 +159,7 @@ void Interpreter::lhau(UGeckoInstruction _inst)
|
|||
|
||||
void Interpreter::lhz(UGeckoInstruction _inst)
|
||||
{
|
||||
u32 temp = (u32)(u16)Memory::Read_U16(Helper_Get_EA(_inst));
|
||||
u32 temp = (u32)(u16)PowerPC::Read_U16(Helper_Get_EA(_inst));
|
||||
if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
|
||||
{
|
||||
rGPR[_inst.RD] = temp;
|
||||
|
@ -169,7 +169,7 @@ void Interpreter::lhz(UGeckoInstruction _inst)
|
|||
void Interpreter::lhzu(UGeckoInstruction _inst)
|
||||
{
|
||||
u32 uAddress = Helper_Get_EA_U(_inst);
|
||||
u32 temp = (u32)(u16)Memory::Read_U16(uAddress);
|
||||
u32 temp = (u32)(u16)PowerPC::Read_U16(uAddress);
|
||||
if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
|
||||
{
|
||||
rGPR[_inst.RD] = temp;
|
||||
|
@ -183,7 +183,7 @@ void Interpreter::lmw(UGeckoInstruction _inst)
|
|||
u32 uAddress = Helper_Get_EA(_inst);
|
||||
for (int iReg = _inst.RD; iReg <= 31; iReg++, uAddress += 4)
|
||||
{
|
||||
u32 TempReg = Memory::Read_U32(uAddress);
|
||||
u32 TempReg = PowerPC::Read_U32(uAddress);
|
||||
if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI)
|
||||
{
|
||||
PanicAlert("DSI exception in lmw");
|
||||
|
@ -203,7 +203,7 @@ void Interpreter::stmw(UGeckoInstruction _inst)
|
|||
u32 uAddress = Helper_Get_EA(_inst);
|
||||
for (int iReg = _inst.RS; iReg <= 31; iReg++, uAddress+=4)
|
||||
{
|
||||
Memory::Write_U32(rGPR[iReg], uAddress);
|
||||
PowerPC::Write_U32(rGPR[iReg], uAddress);
|
||||
if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI)
|
||||
{
|
||||
PanicAlert("DSI exception in stmw");
|
||||
|
@ -216,7 +216,7 @@ void Interpreter::stmw(UGeckoInstruction _inst)
|
|||
void Interpreter::lwz(UGeckoInstruction _inst)
|
||||
{
|
||||
u32 uAddress = Helper_Get_EA(_inst);
|
||||
u32 temp = Memory::Read_U32(uAddress);
|
||||
u32 temp = PowerPC::Read_U32(uAddress);
|
||||
if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
|
||||
{
|
||||
rGPR[_inst.RD] = temp;
|
||||
|
@ -226,7 +226,7 @@ void Interpreter::lwz(UGeckoInstruction _inst)
|
|||
void Interpreter::lwzu(UGeckoInstruction _inst)
|
||||
{
|
||||
u32 uAddress = Helper_Get_EA_U(_inst);
|
||||
u32 temp = Memory::Read_U32(uAddress);
|
||||
u32 temp = PowerPC::Read_U32(uAddress);
|
||||
if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
|
||||
{
|
||||
rGPR[_inst.RD] = temp;
|
||||
|
@ -236,13 +236,13 @@ void Interpreter::lwzu(UGeckoInstruction _inst)
|
|||
|
||||
void Interpreter::stb(UGeckoInstruction _inst)
|
||||
{
|
||||
Memory::Write_U8((u8)rGPR[_inst.RS], Helper_Get_EA(_inst));
|
||||
PowerPC::Write_U8((u8)rGPR[_inst.RS], Helper_Get_EA(_inst));
|
||||
}
|
||||
|
||||
void Interpreter::stbu(UGeckoInstruction _inst)
|
||||
{
|
||||
u32 uAddress = Helper_Get_EA_U(_inst);
|
||||
Memory::Write_U8((u8)rGPR[_inst.RS], uAddress);
|
||||
PowerPC::Write_U8((u8)rGPR[_inst.RS], uAddress);
|
||||
if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
|
||||
{
|
||||
rGPR[_inst.RA] = uAddress;
|
||||
|
@ -251,13 +251,13 @@ void Interpreter::stbu(UGeckoInstruction _inst)
|
|||
|
||||
void Interpreter::stfd(UGeckoInstruction _inst)
|
||||
{
|
||||
Memory::Write_U64(riPS0(_inst.FS), Helper_Get_EA(_inst));
|
||||
PowerPC::Write_U64(riPS0(_inst.FS), Helper_Get_EA(_inst));
|
||||
}
|
||||
|
||||
void Interpreter::stfdu(UGeckoInstruction _inst)
|
||||
{
|
||||
u32 uAddress = Helper_Get_EA_U(_inst);
|
||||
Memory::Write_U64(riPS0(_inst.FS), uAddress);
|
||||
PowerPC::Write_U64(riPS0(_inst.FS), uAddress);
|
||||
if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
|
||||
{
|
||||
rGPR[_inst.RA] = uAddress;
|
||||
|
@ -266,13 +266,13 @@ void Interpreter::stfdu(UGeckoInstruction _inst)
|
|||
|
||||
void Interpreter::stfs(UGeckoInstruction _inst)
|
||||
{
|
||||
Memory::Write_U32(ConvertToSingle(riPS0(_inst.FS)), Helper_Get_EA(_inst));
|
||||
PowerPC::Write_U32(ConvertToSingle(riPS0(_inst.FS)), Helper_Get_EA(_inst));
|
||||
}
|
||||
|
||||
void Interpreter::stfsu(UGeckoInstruction _inst)
|
||||
{
|
||||
u32 uAddress = Helper_Get_EA_U(_inst);
|
||||
Memory::Write_U32(ConvertToSingle(riPS0(_inst.FS)), uAddress);
|
||||
PowerPC::Write_U32(ConvertToSingle(riPS0(_inst.FS)), uAddress);
|
||||
if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
|
||||
{
|
||||
rGPR[_inst.RA] = uAddress;
|
||||
|
@ -281,13 +281,13 @@ void Interpreter::stfsu(UGeckoInstruction _inst)
|
|||
|
||||
void Interpreter::sth(UGeckoInstruction _inst)
|
||||
{
|
||||
Memory::Write_U16((u16)rGPR[_inst.RS], Helper_Get_EA(_inst));
|
||||
PowerPC::Write_U16((u16)rGPR[_inst.RS], Helper_Get_EA(_inst));
|
||||
}
|
||||
|
||||
void Interpreter::sthu(UGeckoInstruction _inst)
|
||||
{
|
||||
u32 uAddress = Helper_Get_EA_U(_inst);
|
||||
Memory::Write_U16((u16)rGPR[_inst.RS], uAddress);
|
||||
PowerPC::Write_U16((u16)rGPR[_inst.RS], uAddress);
|
||||
if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
|
||||
{
|
||||
rGPR[_inst.RA] = uAddress;
|
||||
|
@ -296,13 +296,13 @@ void Interpreter::sthu(UGeckoInstruction _inst)
|
|||
|
||||
void Interpreter::stw(UGeckoInstruction _inst)
|
||||
{
|
||||
Memory::Write_U32(rGPR[_inst.RS], Helper_Get_EA(_inst));
|
||||
PowerPC::Write_U32(rGPR[_inst.RS], Helper_Get_EA(_inst));
|
||||
}
|
||||
|
||||
void Interpreter::stwu(UGeckoInstruction _inst)
|
||||
{
|
||||
u32 uAddress = Helper_Get_EA_U(_inst);
|
||||
Memory::Write_U32(rGPR[_inst.RS], uAddress);
|
||||
PowerPC::Write_U32(rGPR[_inst.RS], uAddress);
|
||||
if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
|
||||
{
|
||||
rGPR[_inst.RA] = uAddress;
|
||||
|
@ -318,8 +318,8 @@ void Interpreter::dcbf(UGeckoInstruction _inst)
|
|||
{
|
||||
//This should tell GFX backend to throw out any cached data here
|
||||
// !!! SPEEDUP HACK for OSProtectRange !!!
|
||||
/* u32 tmp1 = Memory::Read_U32(PC+4);
|
||||
u32 tmp2 = Memory::Read_U32(PC+8);
|
||||
/* u32 tmp1 = PowerPC::HostRead_U32(PC+4);
|
||||
u32 tmp2 = PowerPC::HostRead_U32(PC+8);
|
||||
|
||||
if ((tmp1 == 0x38630020) &&
|
||||
(tmp2 == 0x4200fff8))
|
||||
|
@ -377,7 +377,7 @@ void Interpreter::dcbz(UGeckoInstruction _inst)
|
|||
{
|
||||
// HACK but works... we think
|
||||
if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bDCBZOFF)
|
||||
Memory::ClearCacheLine(Helper_Get_EA_X(_inst) & (~31));
|
||||
PowerPC::ClearCacheLine(Helper_Get_EA_X(_inst) & (~31));
|
||||
if (!JitInterface::GetCore())
|
||||
PowerPC::CheckExceptions();
|
||||
}
|
||||
|
@ -403,7 +403,7 @@ void Interpreter::eciwx(UGeckoInstruction _inst)
|
|||
// _assert_msg_(POWERPC,0,"eciwx - fill r%i with word @ %08x from device %02x",
|
||||
// _inst.RS, EA, PowerPC::ppcState.spr[SPR_EAR] & 0x1f);
|
||||
|
||||
rGPR[_inst.RS] = Memory::Read_U32(EA);
|
||||
rGPR[_inst.RS] = PowerPC::Read_U32(EA);
|
||||
}
|
||||
|
||||
void Interpreter::ecowx(UGeckoInstruction _inst)
|
||||
|
@ -425,7 +425,7 @@ void Interpreter::ecowx(UGeckoInstruction _inst)
|
|||
// _assert_msg_(POWERPC,0,"ecowx - send stw request (%08x@%08x) to device %02x",
|
||||
// rGPR[_inst.RS], EA, PowerPC::ppcState.spr[SPR_EAR] & 0x1f);
|
||||
|
||||
Memory::Write_U32(rGPR[_inst.RS], EA);
|
||||
PowerPC::Write_U32(rGPR[_inst.RS], EA);
|
||||
}
|
||||
|
||||
void Interpreter::eieio(UGeckoInstruction _inst)
|
||||
|
@ -445,7 +445,7 @@ void Interpreter::icbi(UGeckoInstruction _inst)
|
|||
void Interpreter::lbzux(UGeckoInstruction _inst)
|
||||
{
|
||||
u32 uAddress = Helper_Get_EA_UX(_inst);
|
||||
u32 temp = (u32)Memory::Read_U8(uAddress);
|
||||
u32 temp = (u32)PowerPC::Read_U8(uAddress);
|
||||
if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
|
||||
{
|
||||
rGPR[_inst.RD] = temp;
|
||||
|
@ -455,7 +455,7 @@ void Interpreter::lbzux(UGeckoInstruction _inst)
|
|||
|
||||
void Interpreter::lbzx(UGeckoInstruction _inst)
|
||||
{
|
||||
u32 temp = (u32)Memory::Read_U8(Helper_Get_EA_X(_inst));
|
||||
u32 temp = (u32)PowerPC::Read_U8(Helper_Get_EA_X(_inst));
|
||||
if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
|
||||
{
|
||||
rGPR[_inst.RD] = temp;
|
||||
|
@ -465,7 +465,7 @@ void Interpreter::lbzx(UGeckoInstruction _inst)
|
|||
void Interpreter::lhaux(UGeckoInstruction _inst)
|
||||
{
|
||||
u32 uAddress = Helper_Get_EA_UX(_inst);
|
||||
s32 temp = (s32)(s16)Memory::Read_U16(uAddress);
|
||||
s32 temp = (s32)(s16)PowerPC::Read_U16(uAddress);
|
||||
if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
|
||||
{
|
||||
rGPR[_inst.RD] = temp;
|
||||
|
@ -475,7 +475,7 @@ void Interpreter::lhaux(UGeckoInstruction _inst)
|
|||
|
||||
void Interpreter::lhax(UGeckoInstruction _inst)
|
||||
{
|
||||
s32 temp = (s32)(s16)Memory::Read_U16(Helper_Get_EA_X(_inst));
|
||||
s32 temp = (s32)(s16)PowerPC::Read_U16(Helper_Get_EA_X(_inst));
|
||||
if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
|
||||
{
|
||||
rGPR[_inst.RD] = temp;
|
||||
|
@ -484,7 +484,7 @@ void Interpreter::lhax(UGeckoInstruction _inst)
|
|||
|
||||
void Interpreter::lhbrx(UGeckoInstruction _inst)
|
||||
{
|
||||
u32 temp = (u32)Common::swap16(Memory::Read_U16(Helper_Get_EA_X(_inst)));
|
||||
u32 temp = (u32)Common::swap16(PowerPC::Read_U16(Helper_Get_EA_X(_inst)));
|
||||
if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
|
||||
{
|
||||
rGPR[_inst.RD] = temp;
|
||||
|
@ -494,7 +494,7 @@ void Interpreter::lhbrx(UGeckoInstruction _inst)
|
|||
void Interpreter::lhzux(UGeckoInstruction _inst)
|
||||
{
|
||||
u32 uAddress = Helper_Get_EA_UX(_inst);
|
||||
u32 temp = (u32)Memory::Read_U16(uAddress);
|
||||
u32 temp = (u32)PowerPC::Read_U16(uAddress);
|
||||
if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
|
||||
{
|
||||
rGPR[_inst.RD] = temp;
|
||||
|
@ -504,7 +504,7 @@ void Interpreter::lhzux(UGeckoInstruction _inst)
|
|||
|
||||
void Interpreter::lhzx(UGeckoInstruction _inst)
|
||||
{
|
||||
u32 temp = (u32)Memory::Read_U16(Helper_Get_EA_X(_inst));
|
||||
u32 temp = (u32)PowerPC::Read_U16(Helper_Get_EA_X(_inst));
|
||||
if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
|
||||
{
|
||||
rGPR[_inst.RD] = temp;
|
||||
|
@ -525,7 +525,7 @@ void Interpreter::lswx(UGeckoInstruction _inst)
|
|||
rGPR[r] = 0;
|
||||
do
|
||||
{
|
||||
u32 TempValue = Memory::Read_U8(EA) << (24 - i);
|
||||
u32 TempValue = PowerPC::Read_U8(EA) << (24 - i);
|
||||
if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI)
|
||||
{
|
||||
PanicAlert("DSI exception in lswx.");
|
||||
|
@ -549,7 +549,7 @@ void Interpreter::lswx(UGeckoInstruction _inst)
|
|||
|
||||
void Interpreter::lwbrx(UGeckoInstruction _inst)
|
||||
{
|
||||
u32 temp = Common::swap32(Memory::Read_U32(Helper_Get_EA_X(_inst)));
|
||||
u32 temp = Common::swap32(PowerPC::Read_U32(Helper_Get_EA_X(_inst)));
|
||||
if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
|
||||
{
|
||||
rGPR[_inst.RD] = temp;
|
||||
|
@ -559,7 +559,7 @@ void Interpreter::lwbrx(UGeckoInstruction _inst)
|
|||
void Interpreter::lwzux(UGeckoInstruction _inst)
|
||||
{
|
||||
u32 uAddress = Helper_Get_EA_UX(_inst);
|
||||
u32 temp = Memory::Read_U32(uAddress);
|
||||
u32 temp = PowerPC::Read_U32(uAddress);
|
||||
if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
|
||||
{
|
||||
rGPR[_inst.RD] = temp;
|
||||
|
@ -570,7 +570,7 @@ void Interpreter::lwzux(UGeckoInstruction _inst)
|
|||
void Interpreter::lwzx(UGeckoInstruction _inst)
|
||||
{
|
||||
u32 uAddress = Helper_Get_EA_X(_inst);
|
||||
u32 temp = Memory::Read_U32(uAddress);
|
||||
u32 temp = PowerPC::Read_U32(uAddress);
|
||||
if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
|
||||
{
|
||||
rGPR[_inst.RD] = temp;
|
||||
|
@ -580,7 +580,7 @@ void Interpreter::lwzx(UGeckoInstruction _inst)
|
|||
void Interpreter::stbux(UGeckoInstruction _inst)
|
||||
{
|
||||
u32 uAddress = Helper_Get_EA_UX(_inst);
|
||||
Memory::Write_U8((u8)rGPR[_inst.RS], uAddress);
|
||||
PowerPC::Write_U8((u8)rGPR[_inst.RS], uAddress);
|
||||
if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
|
||||
{
|
||||
rGPR[_inst.RA] = uAddress;
|
||||
|
@ -589,13 +589,13 @@ void Interpreter::stbux(UGeckoInstruction _inst)
|
|||
|
||||
void Interpreter::stbx(UGeckoInstruction _inst)
|
||||
{
|
||||
Memory::Write_U8((u8)rGPR[_inst.RS], Helper_Get_EA_X(_inst));
|
||||
PowerPC::Write_U8((u8)rGPR[_inst.RS], Helper_Get_EA_X(_inst));
|
||||
}
|
||||
|
||||
void Interpreter::stfdux(UGeckoInstruction _inst)
|
||||
{
|
||||
u32 uAddress = Helper_Get_EA_UX(_inst);
|
||||
Memory::Write_U64(riPS0(_inst.FS), uAddress);
|
||||
PowerPC::Write_U64(riPS0(_inst.FS), uAddress);
|
||||
if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
|
||||
{
|
||||
rGPR[_inst.RA] = uAddress;
|
||||
|
@ -604,7 +604,7 @@ void Interpreter::stfdux(UGeckoInstruction _inst)
|
|||
|
||||
void Interpreter::stfdx(UGeckoInstruction _inst)
|
||||
{
|
||||
Memory::Write_U64(riPS0(_inst.FS), Helper_Get_EA_X(_inst));
|
||||
PowerPC::Write_U64(riPS0(_inst.FS), Helper_Get_EA_X(_inst));
|
||||
}
|
||||
|
||||
// Stores Floating points into Integers indeXed
|
||||
|
@ -612,14 +612,14 @@ void Interpreter::stfiwx(UGeckoInstruction _inst)
|
|||
{
|
||||
u32 uAddress = Helper_Get_EA_X(_inst);
|
||||
|
||||
Memory::Write_U32((u32)riPS0(_inst.FS), uAddress);
|
||||
PowerPC::Write_U32((u32)riPS0(_inst.FS), uAddress);
|
||||
}
|
||||
|
||||
|
||||
void Interpreter::stfsux(UGeckoInstruction _inst)
|
||||
{
|
||||
u32 uAddress = Helper_Get_EA_UX(_inst);
|
||||
Memory::Write_U32(ConvertToSingle(riPS0(_inst.FS)), uAddress);
|
||||
PowerPC::Write_U32(ConvertToSingle(riPS0(_inst.FS)), uAddress);
|
||||
if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
|
||||
{
|
||||
rGPR[_inst.RA] = uAddress;
|
||||
|
@ -628,18 +628,18 @@ void Interpreter::stfsux(UGeckoInstruction _inst)
|
|||
|
||||
void Interpreter::stfsx(UGeckoInstruction _inst)
|
||||
{
|
||||
Memory::Write_U32(ConvertToSingle(riPS0(_inst.FS)), Helper_Get_EA_X(_inst));
|
||||
PowerPC::Write_U32(ConvertToSingle(riPS0(_inst.FS)), Helper_Get_EA_X(_inst));
|
||||
}
|
||||
|
||||
void Interpreter::sthbrx(UGeckoInstruction _inst)
|
||||
{
|
||||
Memory::Write_U16(Common::swap16((u16)rGPR[_inst.RS]), Helper_Get_EA_X(_inst));
|
||||
PowerPC::Write_U16(Common::swap16((u16)rGPR[_inst.RS]), Helper_Get_EA_X(_inst));
|
||||
}
|
||||
|
||||
void Interpreter::sthux(UGeckoInstruction _inst)
|
||||
{
|
||||
u32 uAddress = Helper_Get_EA_UX(_inst);
|
||||
Memory::Write_U16((u16)rGPR[_inst.RS], uAddress);
|
||||
PowerPC::Write_U16((u16)rGPR[_inst.RS], uAddress);
|
||||
if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
|
||||
{
|
||||
rGPR[_inst.RA] = uAddress;
|
||||
|
@ -648,7 +648,7 @@ void Interpreter::sthux(UGeckoInstruction _inst)
|
|||
|
||||
void Interpreter::sthx(UGeckoInstruction _inst)
|
||||
{
|
||||
Memory::Write_U16((u16)rGPR[_inst.RS], Helper_Get_EA_X(_inst));
|
||||
PowerPC::Write_U16((u16)rGPR[_inst.RS], Helper_Get_EA_X(_inst));
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
|
@ -679,7 +679,7 @@ void Interpreter::lswi(UGeckoInstruction _inst)
|
|||
rGPR[r] = 0;
|
||||
}
|
||||
|
||||
u32 TempValue = Memory::Read_U8(EA) << (24 - i);
|
||||
u32 TempValue = PowerPC::Read_U8(EA) << (24 - i);
|
||||
if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI)
|
||||
{
|
||||
PanicAlert("DSI exception in lsw.");
|
||||
|
@ -723,7 +723,7 @@ void Interpreter::stswi(UGeckoInstruction _inst)
|
|||
r++;
|
||||
r &= 31;
|
||||
}
|
||||
Memory::Write_U8((rGPR[r] >> (24 - i)) & 0xFF, EA);
|
||||
PowerPC::Write_U8((rGPR[r] >> (24 - i)) & 0xFF, EA);
|
||||
if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI)
|
||||
{
|
||||
return;
|
||||
|
@ -747,7 +747,7 @@ void Interpreter::stswx(UGeckoInstruction _inst)
|
|||
|
||||
while (n > 0)
|
||||
{
|
||||
Memory::Write_U8((rGPR[r] >> (24 - i)) & 0xFF, EA);
|
||||
PowerPC::Write_U8((rGPR[r] >> (24 - i)) & 0xFF, EA);
|
||||
|
||||
EA++;
|
||||
n--;
|
||||
|
@ -763,7 +763,7 @@ void Interpreter::stswx(UGeckoInstruction _inst)
|
|||
void Interpreter::stwbrx(UGeckoInstruction _inst)
|
||||
{
|
||||
u32 uAddress = Helper_Get_EA_X(_inst);
|
||||
Memory::Write_U32(Common::swap32(rGPR[_inst.RS]), uAddress);
|
||||
PowerPC::Write_U32(Common::swap32(rGPR[_inst.RS]), uAddress);
|
||||
}
|
||||
|
||||
|
||||
|
@ -773,7 +773,7 @@ void Interpreter::stwbrx(UGeckoInstruction _inst)
|
|||
void Interpreter::lwarx(UGeckoInstruction _inst)
|
||||
{
|
||||
u32 uAddress = Helper_Get_EA_X(_inst);
|
||||
u32 temp = Memory::Read_U32(uAddress);
|
||||
u32 temp = PowerPC::Read_U32(uAddress);
|
||||
if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
|
||||
{
|
||||
rGPR[_inst.RD] = temp;
|
||||
|
@ -792,7 +792,7 @@ void Interpreter::stwcxd(UGeckoInstruction _inst)
|
|||
|
||||
if (uAddress == g_reserveAddr)
|
||||
{
|
||||
Memory::Write_U32(rGPR[_inst.RS], uAddress);
|
||||
PowerPC::Write_U32(rGPR[_inst.RS], uAddress);
|
||||
if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
|
||||
{
|
||||
g_bReserve = false;
|
||||
|
@ -808,7 +808,7 @@ void Interpreter::stwcxd(UGeckoInstruction _inst)
|
|||
void Interpreter::stwux(UGeckoInstruction _inst)
|
||||
{
|
||||
u32 uAddress = Helper_Get_EA_UX(_inst);
|
||||
Memory::Write_U32(rGPR[_inst.RS], uAddress);
|
||||
PowerPC::Write_U32(rGPR[_inst.RS], uAddress);
|
||||
if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
|
||||
{
|
||||
rGPR[_inst.RA] = uAddress;
|
||||
|
@ -818,7 +818,7 @@ void Interpreter::stwux(UGeckoInstruction _inst)
|
|||
void Interpreter::stwx(UGeckoInstruction _inst)
|
||||
{
|
||||
u32 uAddress = Helper_Get_EA_X(_inst);
|
||||
Memory::Write_U32(rGPR[_inst.RS], uAddress);
|
||||
PowerPC::Write_U32(rGPR[_inst.RS], uAddress);
|
||||
}
|
||||
|
||||
void Interpreter::sync(UGeckoInstruction _inst)
|
||||
|
@ -838,7 +838,7 @@ void Interpreter::tlbie(UGeckoInstruction _inst)
|
|||
{
|
||||
// Invalidate TLB entry
|
||||
u32 _Address = rGPR[_inst.RB];
|
||||
Memory::InvalidateTLBEntry(_Address);
|
||||
PowerPC::InvalidateTLBEntry(_Address);
|
||||
}
|
||||
|
||||
void Interpreter::tlbsync(UGeckoInstruction _inst)
|
||||
|
|
|
@ -53,7 +53,7 @@ void Interpreter::Helper_Quantize(const u32 _Addr, const double _fValue, const E
|
|||
switch (_quantizeType)
|
||||
{
|
||||
case QUANTIZE_FLOAT:
|
||||
Memory::Write_U32(ConvertToSingleFTZ(*(u64*)&_fValue), _Addr);
|
||||
PowerPC::Write_U32(ConvertToSingleFTZ(*(u64*)&_fValue), _Addr);
|
||||
break;
|
||||
|
||||
// used for THP player
|
||||
|
@ -61,7 +61,7 @@ void Interpreter::Helper_Quantize(const u32 _Addr, const double _fValue, const E
|
|||
{
|
||||
float fResult = (float)_fValue * m_quantizeTable[_uScale];
|
||||
MathUtil::Clamp(&fResult, 0.0f, 255.0f);
|
||||
Memory::Write_U8((u8)fResult, _Addr);
|
||||
PowerPC::Write_U8((u8)fResult, _Addr);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -69,7 +69,7 @@ void Interpreter::Helper_Quantize(const u32 _Addr, const double _fValue, const E
|
|||
{
|
||||
float fResult = (float)_fValue * m_quantizeTable[_uScale];
|
||||
MathUtil::Clamp(&fResult, 0.0f, 65535.0f);
|
||||
Memory::Write_U16((u16)fResult, _Addr);
|
||||
PowerPC::Write_U16((u16)fResult, _Addr);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -77,7 +77,7 @@ void Interpreter::Helper_Quantize(const u32 _Addr, const double _fValue, const E
|
|||
{
|
||||
float fResult = (float)_fValue * m_quantizeTable[_uScale];
|
||||
MathUtil::Clamp(&fResult, -128.0f, 127.0f);
|
||||
Memory::Write_U8((u8)(s8)fResult, _Addr);
|
||||
PowerPC::Write_U8((u8)(s8)fResult, _Addr);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -85,7 +85,7 @@ void Interpreter::Helper_Quantize(const u32 _Addr, const double _fValue, const E
|
|||
{
|
||||
float fResult = (float)_fValue * m_quantizeTable[_uScale];
|
||||
MathUtil::Clamp(&fResult, -32768.0f, 32767.0f);
|
||||
Memory::Write_U16((u16)(s16)fResult, _Addr);
|
||||
PowerPC::Write_U16((u16)(s16)fResult, _Addr);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -103,26 +103,26 @@ float Interpreter::Helper_Dequantize(const u32 _Addr, const EQuantizeType _quant
|
|||
{
|
||||
case QUANTIZE_FLOAT:
|
||||
{
|
||||
u32 dwValue = Memory::Read_U32(_Addr);
|
||||
u32 dwValue = PowerPC::Read_U32(_Addr);
|
||||
fResult = *(float*)&dwValue;
|
||||
}
|
||||
break;
|
||||
|
||||
case QUANTIZE_U8:
|
||||
fResult = static_cast<float>(Memory::Read_U8(_Addr)) * m_dequantizeTable[_uScale];
|
||||
fResult = static_cast<float>(PowerPC::Read_U8(_Addr)) * m_dequantizeTable[_uScale];
|
||||
break;
|
||||
|
||||
case QUANTIZE_U16:
|
||||
fResult = static_cast<float>(Memory::Read_U16(_Addr)) * m_dequantizeTable[_uScale];
|
||||
fResult = static_cast<float>(PowerPC::Read_U16(_Addr)) * m_dequantizeTable[_uScale];
|
||||
break;
|
||||
|
||||
case QUANTIZE_S8:
|
||||
fResult = static_cast<float>((s8)Memory::Read_U8(_Addr)) * m_dequantizeTable[_uScale];
|
||||
fResult = static_cast<float>((s8)PowerPC::Read_U8(_Addr)) * m_dequantizeTable[_uScale];
|
||||
break;
|
||||
|
||||
// used for THP player
|
||||
case QUANTIZE_S16:
|
||||
fResult = static_cast<float>((s16)Memory::Read_U16(_Addr)) * m_dequantizeTable[_uScale];
|
||||
fResult = static_cast<float>((s16)PowerPC::Read_U16(_Addr)) * m_dequantizeTable[_uScale];
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -425,5 +425,5 @@ void Interpreter::ps_cmpo1(UGeckoInstruction _inst)
|
|||
void Interpreter::dcbz_l(UGeckoInstruction _inst)
|
||||
{
|
||||
//FAKE: clear memory instead of clearing the cache block
|
||||
Memory::Memset(Helper_Get_EA_X(_inst) & (~31), 0, 32);
|
||||
PowerPC::ClearCacheLine(Helper_Get_EA_X(_inst) & (~31));
|
||||
}
|
||||
|
|
|
@ -329,9 +329,9 @@ void Interpreter::mtspr(UGeckoInstruction _inst)
|
|||
if (iLength == 0)
|
||||
iLength = 128;
|
||||
if (DMAL.DMA_LD)
|
||||
Memory::DMA_MemoryToLC(dwCacheAddress, dwMemAddress, iLength);
|
||||
PowerPC::DMA_MemoryToLC(dwCacheAddress, dwMemAddress, iLength);
|
||||
else
|
||||
Memory::DMA_LCToMemory(dwMemAddress, dwCacheAddress, iLength);
|
||||
PowerPC::DMA_LCToMemory(dwMemAddress, dwCacheAddress, iLength);
|
||||
}
|
||||
DMAL.DMA_T = 0;
|
||||
break;
|
||||
|
@ -351,7 +351,7 @@ void Interpreter::mtspr(UGeckoInstruction _inst)
|
|||
|
||||
// Page table base etc
|
||||
case SPR_SDR:
|
||||
Memory::SDRUpdated();
|
||||
PowerPC::SDRUpdated();
|
||||
break;
|
||||
|
||||
case SPR_XER:
|
||||
|
|
|
@ -180,6 +180,7 @@ void Jit64::Init()
|
|||
jo.accurateSinglePrecision = true;
|
||||
js.memcheck = SConfig::GetInstance().m_LocalCoreStartupParameter.bMMU;
|
||||
js.fastmemLoadStore = NULL;
|
||||
js.compilerPC = 0;
|
||||
|
||||
gpr.SetEmitter(this);
|
||||
fpr.SetEmitter(this);
|
||||
|
@ -539,6 +540,7 @@ void Jit64::Jit(u32 em_address)
|
|||
NPC = nextPC;
|
||||
PowerPC::ppcState.Exceptions |= EXCEPTION_ISI;
|
||||
PowerPC::CheckExceptions();
|
||||
WARN_LOG(POWERPC, "ISI exception at 0x%08x", nextPC);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ void Jit64AsmRoutineManager::Generate()
|
|||
MOV(64, MDisp(RSP, 8), Imm32((u32)-1));
|
||||
|
||||
// Two statically allocated registers.
|
||||
MOV(64, R(RMEM), Imm64((u64)Memory::base));
|
||||
//MOV(64, R(RMEM), Imm64((u64)Memory::physical_base));
|
||||
MOV(64, R(RPPCSTATE), Imm64((u64)&PowerPC::ppcState + 0x80));
|
||||
|
||||
const u8* outerLoop = GetCodePtr();
|
||||
|
@ -83,8 +83,26 @@ void Jit64AsmRoutineManager::Generate()
|
|||
SetJumpTarget(skipToRealDispatch);
|
||||
|
||||
dispatcherNoCheck = GetCodePtr();
|
||||
|
||||
// Switch to the correct memory base, in case MSR.DR has changed.
|
||||
// TODO: Is there a more efficient place to put this? We don't
|
||||
// need to do this for indirect jumps, just exceptions etc.
|
||||
TEST(32, PPCSTATE(msr), Imm32(1 << (31 - 27)));
|
||||
FixupBranch physmem = J_CC(CC_NZ);
|
||||
MOV(64, R(RMEM), Imm64((u64)Memory::physical_base));
|
||||
FixupBranch membaseend = J();
|
||||
SetJumpTarget(physmem);
|
||||
MOV(64, R(RMEM), Imm64((u64)Memory::logical_base));
|
||||
SetJumpTarget(membaseend);
|
||||
|
||||
MOV(32, R(RSCRATCH), PPCSTATE(pc));
|
||||
|
||||
// TODO: We need to handle code which executes the same PC with
|
||||
// different values of MSR.IR. It probably makes sense to handle
|
||||
// MSR.DR here too, to allow IsOptimizableRAMAddress-based
|
||||
// optimizations safe, because IR and DR are usually set/cleared together.
|
||||
// TODO: Branching based on the 20 most significant bits of instruction
|
||||
// addresses without translating them is wrong.
|
||||
u64 icache = (u64)jit->GetBlockCache()->iCache.data();
|
||||
u64 icacheVmem = (u64)jit->GetBlockCache()->iCacheVMEM.data();
|
||||
u64 icacheEx = (u64)jit->GetBlockCache()->iCacheEx.data();
|
||||
|
@ -251,5 +269,5 @@ void Jit64AsmRoutineManager::GenerateCommon()
|
|||
ADD(32, 1, M(&m_gatherPipeCount));
|
||||
RET();
|
||||
SetJumpTarget(skip_fast_write);
|
||||
CALL((void *)&Memory::Write_U8);*/
|
||||
CALL((void *)&PowerPC::Write_U8);*/
|
||||
}
|
||||
|
|
|
@ -108,6 +108,8 @@ void Jit64::lXXx(UGeckoInstruction inst)
|
|||
// (mb2): I agree,
|
||||
// IMHO those Idles should always be skipped and replaced by a more controllable "native" Idle methode
|
||||
// ... maybe the throttle one already do that :p
|
||||
// TODO: We shouldn't use a debug read here. It should be possible to get
|
||||
// the following instructions out of the JIT state.
|
||||
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bSkipIdle &&
|
||||
PowerPC::GetState() != PowerPC::CPU_STEPPING &&
|
||||
inst.OPCD == 32 &&
|
||||
|
@ -335,7 +337,7 @@ void Jit64::dcbz(UGeckoInstruction inst)
|
|||
MOV(32, M(&PC), Imm32(jit->js.compilerPC));
|
||||
BitSet32 registersInUse = CallerSavedRegistersInUse();
|
||||
ABI_PushRegistersAndAdjustStack(registersInUse, 0);
|
||||
ABI_CallFunctionR((void *)&Memory::ClearCacheLine, RSCRATCH);
|
||||
ABI_CallFunctionR((void *)&PowerPC::ClearCacheLine, RSCRATCH);
|
||||
ABI_PopRegistersAndAdjustStack(registersInUse, 0);
|
||||
FixupBranch exit = J(true);
|
||||
|
||||
|
|
|
@ -380,9 +380,8 @@ void Jit64::mtmsr(UGeckoInstruction inst)
|
|||
SetJumpTarget(noExceptionsPending);
|
||||
SetJumpTarget(eeDisabled);
|
||||
|
||||
WriteExit(js.compilerPC + 4);
|
||||
|
||||
js.firstFPInstructionFound = false;
|
||||
MOV(32, R(RSCRATCH), Imm32(js.compilerPC + 4));
|
||||
WriteExitDestInRSCRATCH();
|
||||
}
|
||||
|
||||
void Jit64::mfmsr(UGeckoInstruction inst)
|
||||
|
|
|
@ -500,7 +500,7 @@ static void regMarkMemAddress(RegInfo& RI, InstLoc I, InstLoc AI, unsigned OpNum
|
|||
if (isImm(*AI))
|
||||
{
|
||||
unsigned addr = RI.Build->GetImmValue(AI);
|
||||
if (Memory::IsRAMAddress(addr))
|
||||
if (PowerPC::IsOptimizableRAMAddress(addr))
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -520,7 +520,7 @@ static std::pair<OpArg, u32> regBuildMemAddress(RegInfo& RI, InstLoc I, InstLoc
|
|||
if (isImm(*AI))
|
||||
{
|
||||
unsigned addr = RI.Build->GetImmValue(AI);
|
||||
if (Memory::IsRAMAddress(addr))
|
||||
if (PowerPC::IsOptimizableRAMAddress(addr))
|
||||
{
|
||||
if (dest)
|
||||
*dest = regFindFreeReg(RI);
|
||||
|
|
|
@ -521,6 +521,7 @@ void JitIL::Jit(u32 em_address)
|
|||
NPC = nextPC;
|
||||
PowerPC::ppcState.Exceptions |= EXCEPTION_ISI;
|
||||
PowerPC::CheckExceptions();
|
||||
WARN_LOG(POWERPC, "ISI exception at 0x%08x", nextPC);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -189,7 +189,7 @@ bool JitArm::DisasmLoadStore(const u8* ptr, u32* flags, ARMReg* rD, ARMReg* V1)
|
|||
|
||||
bool JitArm::HandleFault(uintptr_t access_address, SContext* ctx)
|
||||
{
|
||||
if (access_address < (uintptr_t)Memory::base)
|
||||
if (access_address < (uintptr_t)Memory::physical_base)
|
||||
PanicAlertT("Exception handler - access below memory space. 0x%08x", access_address);
|
||||
return BackPatch(ctx);
|
||||
}
|
||||
|
@ -323,12 +323,12 @@ u32 JitArm::EmitBackpatchRoutine(ARMXEmitter* emit, u32 flags, bool fastmem, boo
|
|||
emit->MOV(R1, addr);
|
||||
emit->VCVT(S0, RS, 0);
|
||||
emit->VMOV(R0, S0);
|
||||
emit->MOVI2R(temp, (u32)&Memory::Write_U32);
|
||||
emit->MOVI2R(temp, (u32)&PowerPC::Write_U32);
|
||||
emit->BL(temp);
|
||||
}
|
||||
else
|
||||
{
|
||||
emit->MOVI2R(temp, (u32)&Memory::Write_F64);
|
||||
emit->MOVI2R(temp, (u32)&PowerPC::Write_F64);
|
||||
#if !defined(__ARM_PCS_VFP) // SoftFP returns in R0 and R1
|
||||
emit->VMOV(R0, RS);
|
||||
emit->MOV(R2, addr);
|
||||
|
@ -347,7 +347,7 @@ u32 JitArm::EmitBackpatchRoutine(ARMXEmitter* emit, u32 flags, bool fastmem, boo
|
|||
emit->MOV(R0, addr);
|
||||
if (flags & BackPatchInfo::FLAG_SIZE_F32)
|
||||
{
|
||||
emit->MOVI2R(temp, (u32)&Memory::Read_U32);
|
||||
emit->MOVI2R(temp, (u32)&PowerPC::Read_U32);
|
||||
emit->BL(temp);
|
||||
emit->VMOV(S0, R0);
|
||||
emit->VCVT(RS, S0, 0);
|
||||
|
@ -355,7 +355,7 @@ u32 JitArm::EmitBackpatchRoutine(ARMXEmitter* emit, u32 flags, bool fastmem, boo
|
|||
}
|
||||
else
|
||||
{
|
||||
emit->MOVI2R(temp, (u32)&Memory::Read_F64);
|
||||
emit->MOVI2R(temp, (u32)&PowerPC::Read_F64);
|
||||
emit->BL(temp);
|
||||
|
||||
#if !defined(__ARM_PCS_VFP) // SoftFP returns in R0 and R1
|
||||
|
@ -373,11 +373,11 @@ u32 JitArm::EmitBackpatchRoutine(ARMXEmitter* emit, u32 flags, bool fastmem, boo
|
|||
emit->MOV(R1, addr);
|
||||
|
||||
if (flags & BackPatchInfo::FLAG_SIZE_32)
|
||||
emit->MOVI2R(temp, (u32)&Memory::Write_U32);
|
||||
emit->MOVI2R(temp, (u32)&PowerPC::Write_U32);
|
||||
else if (flags & BackPatchInfo::FLAG_SIZE_16)
|
||||
emit->MOVI2R(temp, (u32)&Memory::Write_U16);
|
||||
emit->MOVI2R(temp, (u32)&PowerPC::Write_U16);
|
||||
else
|
||||
emit->MOVI2R(temp, (u32)&Memory::Write_U8);
|
||||
emit->MOVI2R(temp, (u32)&PowerPC::Write_U8);
|
||||
|
||||
emit->BL(temp);
|
||||
emit->POP(4, R0, R1, R2, R3);
|
||||
|
@ -388,11 +388,11 @@ u32 JitArm::EmitBackpatchRoutine(ARMXEmitter* emit, u32 flags, bool fastmem, boo
|
|||
emit->MOV(R0, addr);
|
||||
|
||||
if (flags & BackPatchInfo::FLAG_SIZE_32)
|
||||
emit->MOVI2R(temp, (u32)&Memory::Read_U32);
|
||||
emit->MOVI2R(temp, (u32)&PowerPC::Read_U32);
|
||||
else if (flags & BackPatchInfo::FLAG_SIZE_16)
|
||||
emit->MOVI2R(temp, (u32)&Memory::Read_U16);
|
||||
emit->MOVI2R(temp, (u32)&PowerPC::Read_U16);
|
||||
else if (flags & BackPatchInfo::FLAG_SIZE_8)
|
||||
emit->MOVI2R(temp, (u32)&Memory::Read_U8);
|
||||
emit->MOVI2R(temp, (u32)&PowerPC::Read_U8);
|
||||
|
||||
emit->BL(temp);
|
||||
emit->MOV(temp, R0);
|
||||
|
|
|
@ -145,7 +145,7 @@ void JitArm::SafeStoreFromReg(s32 dest, u32 value, s32 regOffset, int accessSize
|
|||
STR(R11, R14);
|
||||
jit->js.fifoBytesThisBlock += accessSize >> 3;
|
||||
}
|
||||
else if (Memory::IsRAMAddress(imm_addr))
|
||||
else if (PowerPC::IsOptimizableRAMAddress(imm_addr))
|
||||
{
|
||||
MOVI2R(rA, imm_addr);
|
||||
EmitBackpatchRoutine(this, flags, SConfig::GetInstance().m_LocalCoreStartupParameter.bFastmem, true, RS);
|
||||
|
@ -450,9 +450,9 @@ void JitArm::lXX(UGeckoInstruction inst)
|
|||
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bSkipIdle &&
|
||||
inst.OPCD == 32 &&
|
||||
(inst.hex & 0xFFFF0000) == 0x800D0000 &&
|
||||
(Memory::ReadUnchecked_U32(js.compilerPC + 4) == 0x28000000 ||
|
||||
(SConfig::GetInstance().m_LocalCoreStartupParameter.bWii && Memory::ReadUnchecked_U32(js.compilerPC + 4) == 0x2C000000)) &&
|
||||
Memory::ReadUnchecked_U32(js.compilerPC + 8) == 0x4182fff8)
|
||||
(PowerPC::HostRead_U32(js.compilerPC + 4) == 0x28000000 ||
|
||||
(SConfig::GetInstance().m_LocalCoreStartupParameter.bWii && PowerPC::HostRead_U32(js.compilerPC + 4) == 0x2C000000)) &&
|
||||
PowerPC::HostRead_U32(js.compilerPC + 8) == 0x4182fff8)
|
||||
{
|
||||
// if it's still 0, we can wait until the next event
|
||||
TST(RD, RD);
|
||||
|
@ -536,7 +536,7 @@ void JitArm::dcbst(UGeckoInstruction inst)
|
|||
// memory location. Do not invalidate the JIT cache in this case as the memory
|
||||
// will be the same.
|
||||
// dcbt = 0x7c00022c
|
||||
FALLBACK_IF((Memory::ReadUnchecked_U32(js.compilerPC - 4) & 0x7c00022c) != 0x7c00022c);
|
||||
FALLBACK_IF((PowerPC::HostRead_U32(js.compilerPC - 4) & 0x7c00022c) != 0x7c00022c);
|
||||
}
|
||||
|
||||
void JitArm::icbi(UGeckoInstruction inst)
|
||||
|
|
|
@ -183,7 +183,7 @@ void JitArm::lfXX(UGeckoInstruction inst)
|
|||
|
||||
EmitBackpatchRoutine(this, flags,
|
||||
SConfig::GetInstance().m_LocalCoreStartupParameter.bFastmem,
|
||||
!(is_immediate && Memory::IsRAMAddress(imm_addr)), v0, v1);
|
||||
!(is_immediate && PowerPC::IsOptimizableRAMAddress(imm_addr)), v0, v1);
|
||||
|
||||
SetJumpTarget(DoNotLoad);
|
||||
}
|
||||
|
@ -384,7 +384,7 @@ void JitArm::stfXX(UGeckoInstruction inst)
|
|||
jit->js.fifoBytesThisBlock += accessSize >> 3;
|
||||
|
||||
}
|
||||
else if (Memory::IsRAMAddress(imm_addr))
|
||||
else if (PowerPC::IsOptimizableRAMAddress(imm_addr))
|
||||
{
|
||||
MOVI2R(addr, imm_addr);
|
||||
EmitBackpatchRoutine(this, flags, SConfig::GetInstance().m_LocalCoreStartupParameter.bFastmem, false, v0);
|
||||
|
|
|
@ -29,20 +29,20 @@ JitArmAsmRoutineManager asm_routines;
|
|||
|
||||
static void WriteDual32(u32 value1, u32 value2, u32 address)
|
||||
{
|
||||
Memory::Write_U32(value1, address);
|
||||
Memory::Write_U32(value2, address + 4);
|
||||
PowerPC::Write_U32(value1, address);
|
||||
PowerPC::Write_U32(value2, address + 4);
|
||||
}
|
||||
|
||||
static void WriteDual16(u32 value1, u32 value2, u32 address)
|
||||
{
|
||||
Memory::Write_U16(value1, address);
|
||||
Memory::Write_U16(value2, address + 2);
|
||||
PowerPC::Write_U16(value1, address);
|
||||
PowerPC::Write_U16(value2, address + 2);
|
||||
}
|
||||
|
||||
static void WriteDual8(u32 value1, u32 value2, u32 address)
|
||||
{
|
||||
Memory::Write_U8(value1, address);
|
||||
Memory::Write_U8(value2, address + 1);
|
||||
PowerPC::Write_U8(value1, address);
|
||||
PowerPC::Write_U8(value2, address + 1);
|
||||
}
|
||||
|
||||
void JitArmAsmRoutineManager::Generate()
|
||||
|
@ -56,7 +56,7 @@ void JitArmAsmRoutineManager::Generate()
|
|||
SUB(_SP, _SP, 4);
|
||||
|
||||
MOVI2R(R9, (u32)&PowerPC::ppcState.spr[0]);
|
||||
MOVI2R(R8, (u32)Memory::base);
|
||||
MOVI2R(R8, (u32)Memory::physical_base);
|
||||
|
||||
FixupBranch skipToRealDispatcher = B();
|
||||
dispatcher = GetCodePtr();
|
||||
|
@ -465,7 +465,7 @@ void JitArmAsmRoutineManager::GenerateCommon()
|
|||
PUSH(5, R0, R1, R2, R3, _LR);
|
||||
VMOV(R0, S0);
|
||||
MOV(R1, R10);
|
||||
MOVI2R(R10, (u32)&Memory::Write_U32);
|
||||
MOVI2R(R10, (u32)&PowerPC::Write_U32);
|
||||
BL(R10);
|
||||
|
||||
POP(5, R0, R1, R2, R3, _PC);
|
||||
|
@ -493,7 +493,7 @@ void JitArmAsmRoutineManager::GenerateCommon()
|
|||
PUSH(5, R0, R1, R2, R3, _LR);
|
||||
VMOV(R0, S0);
|
||||
MOV(R1, R10);
|
||||
MOVI2R(R10, (u32)&Memory::Write_U8);
|
||||
MOVI2R(R10, (u32)&PowerPC::Write_U8);
|
||||
BL(R10);
|
||||
POP(5, R0, R1, R2, R3, _PC);
|
||||
}
|
||||
|
@ -521,7 +521,7 @@ void JitArmAsmRoutineManager::GenerateCommon()
|
|||
PUSH(5, R0, R1, R2, R3, _LR);
|
||||
VMOV(R0, S0);
|
||||
MOV(R1, R10);
|
||||
MOVI2R(R10, (u32)&Memory::Write_U16);
|
||||
MOVI2R(R10, (u32)&PowerPC::Write_U16);
|
||||
BL(R10);
|
||||
|
||||
POP(5, R0, R1, R2, R3, _PC);
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "Common/StringUtil.h"
|
||||
|
||||
#include "Core/HW/Memmap.h"
|
||||
#include "Core/PowerPC/PowerPC.h"
|
||||
#include "Core/PowerPC/JitArm64/Jit.h"
|
||||
#include "Core/PowerPC/JitArmCommon/BackPatch.h"
|
||||
|
||||
|
@ -127,7 +128,8 @@ u32 JitArm64::EmitBackpatchRoutine(ARM64XEmitter* emit, u32 flags, bool fastmem,
|
|||
|
||||
if (fastmem)
|
||||
{
|
||||
MOVK(addr, ((u64)Memory::base >> 32) & 0xFFFF, SHIFT_32);
|
||||
u8* base = UReg_MSR(MSR).DR ? Memory::logical_base : Memory::physical_base;
|
||||
MOVK(addr, ((u64)base >> 32) & 0xFFFF, SHIFT_32);
|
||||
|
||||
if (flags & BackPatchInfo::FLAG_STORE &&
|
||||
flags & (BackPatchInfo::FLAG_SIZE_F32 | BackPatchInfo::FLAG_SIZE_F64))
|
||||
|
@ -249,22 +251,22 @@ u32 JitArm64::EmitBackpatchRoutine(ARM64XEmitter* emit, u32 flags, bool fastmem,
|
|||
emit->MOV(W0, RS);
|
||||
|
||||
if (flags & BackPatchInfo::FLAG_SIZE_32)
|
||||
emit->MOVI2R(X30, (u64)&Memory::Write_U32);
|
||||
emit->MOVI2R(X30, (u64)&PowerPC::Write_U32);
|
||||
else if (flags & BackPatchInfo::FLAG_SIZE_16)
|
||||
emit->MOVI2R(X30, (u64)&Memory::Write_U16);
|
||||
emit->MOVI2R(X30, (u64)&PowerPC::Write_U16);
|
||||
else
|
||||
emit->MOVI2R(X30, (u64)&Memory::Write_U8);
|
||||
emit->MOVI2R(X30, (u64)&PowerPC::Write_U8);
|
||||
|
||||
emit->BLR(X30);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (flags & BackPatchInfo::FLAG_SIZE_32)
|
||||
emit->MOVI2R(X30, (u64)&Memory::Read_U32);
|
||||
emit->MOVI2R(X30, (u64)&PowerPC::Read_U32);
|
||||
else if (flags & BackPatchInfo::FLAG_SIZE_16)
|
||||
emit->MOVI2R(X30, (u64)&Memory::Read_U16);
|
||||
emit->MOVI2R(X30, (u64)&PowerPC::Read_U16);
|
||||
else if (flags & BackPatchInfo::FLAG_SIZE_8)
|
||||
emit->MOVI2R(X30, (u64)&Memory::Read_U8);
|
||||
emit->MOVI2R(X30, (u64)&PowerPC::Read_U8);
|
||||
|
||||
emit->BLR(X30);
|
||||
|
||||
|
@ -302,9 +304,10 @@ u32 JitArm64::EmitBackpatchRoutine(ARM64XEmitter* emit, u32 flags, bool fastmem,
|
|||
|
||||
bool JitArm64::HandleFault(uintptr_t access_address, SContext* ctx)
|
||||
{
|
||||
if (access_address < (uintptr_t)Memory::base)
|
||||
if (!(access_address >= (uintptr_t)Memory::physical_base && access_address < (uintptr_t)Memory::physical_base + 0x100010000) &&
|
||||
!(access_address >= (uintptr_t)Memory::logical_base && access_address < (uintptr_t)Memory::logical_base + 0x100010000))
|
||||
{
|
||||
ERROR_LOG(DYNA_REC, "Exception handler - access below memory space. PC: 0x%016llx 0x%016lx < 0x%016lx", ctx->CTX_PC, access_address, (uintptr_t)Memory::base);
|
||||
ERROR_LOG(DYNA_REC, "Exception handler - access below memory space. PC: 0x%016llx 0x%016lx < 0x%016lx", ctx->CTX_PC, access_address, (uintptr_t)Memory::physical_base);
|
||||
|
||||
DoBacktrace(access_address, ctx);
|
||||
return false;
|
||||
|
|
|
@ -147,7 +147,7 @@ void JitArm64::SafeLoadToReg(u32 dest, s32 addr, s32 offsetReg, u32 flags, s32 o
|
|||
if (update)
|
||||
MOV(gpr.R(addr), addr_reg);
|
||||
|
||||
if (is_immediate && Memory::IsRAMAddress(imm_addr))
|
||||
if (is_immediate && PowerPC::IsOptimizableRAMAddress(imm_addr))
|
||||
{
|
||||
EmitBackpatchRoutine(this, flags, true, false, dest_reg, XA);
|
||||
}
|
||||
|
@ -288,7 +288,7 @@ void JitArm64::SafeStoreFromReg(s32 dest, u32 value, s32 regOffset, u32 flags, s
|
|||
|
||||
ARM64Reg XA = EncodeRegTo64(addr_reg);
|
||||
|
||||
if (is_immediate && Memory::IsRAMAddress(imm_addr))
|
||||
if (is_immediate && PowerPC::IsOptimizableRAMAddress(imm_addr))
|
||||
{
|
||||
MOVI2R(XA, imm_addr);
|
||||
|
||||
|
@ -401,9 +401,9 @@ void JitArm64::lXX(UGeckoInstruction inst)
|
|||
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bSkipIdle &&
|
||||
inst.OPCD == 32 &&
|
||||
(inst.hex & 0xFFFF0000) == 0x800D0000 &&
|
||||
(Memory::ReadUnchecked_U32(js.compilerPC + 4) == 0x28000000 ||
|
||||
(SConfig::GetInstance().m_LocalCoreStartupParameter.bWii && Memory::ReadUnchecked_U32(js.compilerPC + 4) == 0x2C000000)) &&
|
||||
Memory::ReadUnchecked_U32(js.compilerPC + 8) == 0x4182fff8)
|
||||
(PowerPC::HostRead_U32(js.compilerPC + 4) == 0x28000000 ||
|
||||
(SConfig::GetInstance().m_LocalCoreStartupParameter.bWii && PowerPC::HostRead_U32(js.compilerPC + 4) == 0x2C000000)) &&
|
||||
PowerPC::HostRead_U32(js.compilerPC + 8) == 0x4182fff8)
|
||||
{
|
||||
// if it's still 0, we can wait until the next event
|
||||
FixupBranch noIdle = CBNZ(gpr.R(d));
|
||||
|
|
|
@ -30,8 +30,11 @@ static void BackPatchError(const std::string &text, u8 *codePtr, u32 emAddress)
|
|||
bool Jitx86Base::HandleFault(uintptr_t access_address, SContext* ctx)
|
||||
{
|
||||
// TODO: do we properly handle off-the-end?
|
||||
if (access_address >= (uintptr_t)Memory::base && access_address < (uintptr_t)Memory::base + 0x100010000)
|
||||
return BackPatch((u32)(access_address - (uintptr_t)Memory::base), ctx);
|
||||
if (access_address >= (uintptr_t)Memory::physical_base && access_address < (uintptr_t)Memory::physical_base + 0x100010000)
|
||||
return BackPatch((u32)(access_address - (uintptr_t)Memory::physical_base), ctx);
|
||||
if (access_address >= (uintptr_t)Memory::logical_base && access_address < (uintptr_t)Memory::logical_base + 0x100010000)
|
||||
return BackPatch((u32)(access_address - (uintptr_t)Memory::logical_base), ctx);
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -71,12 +71,12 @@ u8 *EmuCodeBlock::UnsafeLoadToReg(X64Reg reg_value, OpArg opAddress, int accessS
|
|||
opAddress = R(reg_value);
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
memOperand = MComplex(RMEM, opAddress.GetSimpleReg(), SCALE_1, offset);
|
||||
}
|
||||
else if (opAddress.IsImm())
|
||||
{
|
||||
memOperand = MDisp(RMEM, (opAddress.offset + offset) & 0x3FFFFFFF);
|
||||
MOV(32, R(reg_value), Imm32((u32)(opAddress.offset + offset)));
|
||||
memOperand = MRegSum(RMEM, reg_value);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -308,9 +308,9 @@ void EmuCodeBlock::SafeLoadToReg(X64Reg reg_value, const Gen::OpArg & opAddress,
|
|||
// access the RAM buffer and load from there).
|
||||
// 2. If the address is in the MMIO range, find the appropriate
|
||||
// MMIO handler and generate the code to load using the handler.
|
||||
// 3. Otherwise, just generate a call to Memory::Read_* with the
|
||||
// 3. Otherwise, just generate a call to PowerPC::Read_* with the
|
||||
// address hardcoded.
|
||||
if (Memory::IsRAMAddress(address))
|
||||
if (PowerPC::IsOptimizableRAMAddress(address))
|
||||
{
|
||||
UnsafeLoadToReg(reg_value, opAddress, accessSize, offset, signExtend);
|
||||
}
|
||||
|
@ -324,10 +324,10 @@ void EmuCodeBlock::SafeLoadToReg(X64Reg reg_value, const Gen::OpArg & opAddress,
|
|||
ABI_PushRegistersAndAdjustStack(registersInUse, 0);
|
||||
switch (accessSize)
|
||||
{
|
||||
case 64: ABI_CallFunctionC((void *)&Memory::Read_U64, address); break;
|
||||
case 32: ABI_CallFunctionC((void *)&Memory::Read_U32, address); break;
|
||||
case 16: ABI_CallFunctionC((void *)&Memory::Read_U16_ZX, address); break;
|
||||
case 8: ABI_CallFunctionC((void *)&Memory::Read_U8_ZX, address); break;
|
||||
case 64: ABI_CallFunctionC((void *)&PowerPC::Read_U64, address); break;
|
||||
case 32: ABI_CallFunctionC((void *)&PowerPC::Read_U32, address); break;
|
||||
case 16: ABI_CallFunctionC((void *)&PowerPC::Read_U16_ZX, address); break;
|
||||
case 8: ABI_CallFunctionC((void *)&PowerPC::Read_U8_ZX, address); break;
|
||||
}
|
||||
ABI_PopRegistersAndAdjustStack(registersInUse, 0);
|
||||
|
||||
|
@ -366,16 +366,16 @@ void EmuCodeBlock::SafeLoadToReg(X64Reg reg_value, const Gen::OpArg & opAddress,
|
|||
switch (accessSize)
|
||||
{
|
||||
case 64:
|
||||
ABI_CallFunctionR((void *)&Memory::Read_U64, reg_addr);
|
||||
ABI_CallFunctionR((void *)&PowerPC::Read_U64, reg_addr);
|
||||
break;
|
||||
case 32:
|
||||
ABI_CallFunctionR((void *)&Memory::Read_U32, reg_addr);
|
||||
ABI_CallFunctionR((void *)&PowerPC::Read_U32, reg_addr);
|
||||
break;
|
||||
case 16:
|
||||
ABI_CallFunctionR((void *)&Memory::Read_U16_ZX, reg_addr);
|
||||
ABI_CallFunctionR((void *)&PowerPC::Read_U16_ZX, reg_addr);
|
||||
break;
|
||||
case 8:
|
||||
ABI_CallFunctionR((void *)&Memory::Read_U8_ZX, reg_addr);
|
||||
ABI_CallFunctionR((void *)&PowerPC::Read_U8_ZX, reg_addr);
|
||||
break;
|
||||
}
|
||||
ABI_PopRegistersAndAdjustStack(registersInUse, rsp_alignment);
|
||||
|
@ -490,7 +490,7 @@ bool EmuCodeBlock::WriteToConstAddress(int accessSize, OpArg arg, u32 address, B
|
|||
UnsafeWriteGatherPipe(accessSize);
|
||||
return false;
|
||||
}
|
||||
else if (Memory::IsRAMAddress(address))
|
||||
else if (PowerPC::IsOptimizableRAMAddress(address))
|
||||
{
|
||||
WriteToConstRamAddress(accessSize, arg, address);
|
||||
return false;
|
||||
|
@ -504,16 +504,16 @@ bool EmuCodeBlock::WriteToConstAddress(int accessSize, OpArg arg, u32 address, B
|
|||
switch (accessSize)
|
||||
{
|
||||
case 64:
|
||||
ABI_CallFunctionAC(64, (void *)&Memory::Write_U64, arg, address);
|
||||
ABI_CallFunctionAC(64, (void *)&PowerPC::Write_U64, arg, address);
|
||||
break;
|
||||
case 32:
|
||||
ABI_CallFunctionAC(32, (void *)&Memory::Write_U32, arg, address);
|
||||
ABI_CallFunctionAC(32, (void *)&PowerPC::Write_U32, arg, address);
|
||||
break;
|
||||
case 16:
|
||||
ABI_CallFunctionAC(16, (void *)&Memory::Write_U16, arg, address);
|
||||
ABI_CallFunctionAC(16, (void *)&PowerPC::Write_U16, arg, address);
|
||||
break;
|
||||
case 8:
|
||||
ABI_CallFunctionAC(8, (void *)&Memory::Write_U8, arg, address);
|
||||
ABI_CallFunctionAC(8, (void *)&PowerPC::Write_U8, arg, address);
|
||||
break;
|
||||
}
|
||||
ABI_PopRegistersAndAdjustStack(registersInUse, 0);
|
||||
|
@ -599,16 +599,16 @@ void EmuCodeBlock::SafeWriteRegToReg(OpArg reg_value, X64Reg reg_addr, int acces
|
|||
switch (accessSize)
|
||||
{
|
||||
case 64:
|
||||
ABI_CallFunctionRR(swap ? ((void *)&Memory::Write_U64) : ((void *)&Memory::Write_U64_Swap), reg, reg_addr);
|
||||
ABI_CallFunctionRR(swap ? ((void *)&PowerPC::Write_U64) : ((void *)&PowerPC::Write_U64_Swap), reg, reg_addr);
|
||||
break;
|
||||
case 32:
|
||||
ABI_CallFunctionRR(swap ? ((void *)&Memory::Write_U32) : ((void *)&Memory::Write_U32_Swap), reg, reg_addr);
|
||||
ABI_CallFunctionRR(swap ? ((void *)&PowerPC::Write_U32) : ((void *)&PowerPC::Write_U32_Swap), reg, reg_addr);
|
||||
break;
|
||||
case 16:
|
||||
ABI_CallFunctionRR(swap ? ((void *)&Memory::Write_U16) : ((void *)&Memory::Write_U16_Swap), reg, reg_addr);
|
||||
ABI_CallFunctionRR(swap ? ((void *)&PowerPC::Write_U16) : ((void *)&PowerPC::Write_U16_Swap), reg, reg_addr);
|
||||
break;
|
||||
case 8:
|
||||
ABI_CallFunctionRR((void *)&Memory::Write_U8, reg, reg_addr);
|
||||
ABI_CallFunctionRR((void *)&PowerPC::Write_U8, reg, reg_addr);
|
||||
break;
|
||||
}
|
||||
ABI_PopRegistersAndAdjustStack(registersInUse, rsp_alignment);
|
||||
|
@ -626,7 +626,8 @@ void EmuCodeBlock::WriteToConstRamAddress(int accessSize, OpArg arg, u32 address
|
|||
if (arg.IsImm())
|
||||
{
|
||||
arg = SwapImmediate(accessSize, arg);
|
||||
MOV(accessSize, MDisp(RMEM, address & 0x3FFFFFFF), arg);
|
||||
MOV(32, R(RSCRATCH), Imm32(address));
|
||||
MOV(accessSize, MRegSum(RMEM, RSCRATCH), arg);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -640,10 +641,11 @@ void EmuCodeBlock::WriteToConstRamAddress(int accessSize, OpArg arg, u32 address
|
|||
reg = arg.GetSimpleReg();
|
||||
}
|
||||
|
||||
MOV(32, R(RSCRATCH2), Imm32(address));
|
||||
if (swap)
|
||||
SwapAndStore(accessSize, MDisp(RMEM, address & 0x3FFFFFFF), reg);
|
||||
SwapAndStore(accessSize, MRegSum(RMEM, RSCRATCH2), reg);
|
||||
else
|
||||
MOV(accessSize, MDisp(RMEM, address & 0x3FFFFFFF), R(reg));
|
||||
MOV(accessSize, MRegSum(RMEM, RSCRATCH2), R(reg));
|
||||
}
|
||||
|
||||
void EmuCodeBlock::ForceSinglePrecisionS(X64Reg output, X64Reg input)
|
||||
|
|
|
@ -66,16 +66,16 @@ const u8* TrampolineCache::GenerateReadTrampoline(const InstructionInfo &info, B
|
|||
switch (info.operandSize)
|
||||
{
|
||||
case 8:
|
||||
CALL((void *)&Memory::Read_U64);
|
||||
CALL((void*)&PowerPC::Read_U64);
|
||||
break;
|
||||
case 4:
|
||||
CALL((void *)&Memory::Read_U32);
|
||||
CALL((void*)&PowerPC::Read_U32);
|
||||
break;
|
||||
case 2:
|
||||
CALL((void *)&Memory::Read_U16);
|
||||
CALL((void*)&PowerPC::Read_U16);
|
||||
break;
|
||||
case 1:
|
||||
CALL((void *)&Memory::Read_U8);
|
||||
CALL((void*)&PowerPC::Read_U8);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -154,16 +154,16 @@ const u8* TrampolineCache::GenerateWriteTrampoline(const InstructionInfo &info,
|
|||
switch (info.operandSize)
|
||||
{
|
||||
case 8:
|
||||
CALL((void *)&Memory::Write_U64);
|
||||
CALL((void *)&PowerPC::Write_U64);
|
||||
break;
|
||||
case 4:
|
||||
CALL((void *)&Memory::Write_U32);
|
||||
CALL((void *)&PowerPC::Write_U32);
|
||||
break;
|
||||
case 2:
|
||||
CALL((void *)&Memory::Write_U16);
|
||||
CALL((void *)&PowerPC::Write_U16);
|
||||
break;
|
||||
case 1:
|
||||
CALL((void *)&Memory::Write_U8);
|
||||
CALL((void *)&PowerPC::Write_U8);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -142,11 +142,12 @@ void JitILBase::bcx(UGeckoInstruction inst)
|
|||
// The main Idle skipping is done in the LoadStore code, but there is an optimization here.
|
||||
// If idle skipping is enabled, then this branch will only be reached when the branch is not
|
||||
// taken.
|
||||
// TODO: We shouldn't use debug reads here.
|
||||
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bSkipIdle &&
|
||||
inst.hex == 0x4182fff8 &&
|
||||
(Memory::ReadUnchecked_U32(js.compilerPC - 8) & 0xFFFF0000) == 0x800D0000 &&
|
||||
(Memory::ReadUnchecked_U32(js.compilerPC - 4) == 0x28000000 ||
|
||||
(SConfig::GetInstance().m_LocalCoreStartupParameter.bWii && Memory::ReadUnchecked_U32(js.compilerPC - 4) == 0x2C000000))
|
||||
(PowerPC::HostRead_U32(js.compilerPC - 8) & 0xFFFF0000) == 0x800D0000 &&
|
||||
(PowerPC::HostRead_U32(js.compilerPC - 4) == 0x28000000 ||
|
||||
(SConfig::GetInstance().m_LocalCoreStartupParameter.bWii && PowerPC::HostRead_U32(js.compilerPC - 4) == 0x2C000000))
|
||||
)
|
||||
{
|
||||
// Uh, Do nothing.
|
||||
|
|
|
@ -34,15 +34,17 @@ void JitILBase::lXz(UGeckoInstruction inst)
|
|||
|
||||
IREmitter::InstLoc val;
|
||||
|
||||
// Idle Skipping. This really should be done somewhere else.
|
||||
// Either lower in the IR or higher in PPCAnalyist
|
||||
// Idle Skipping.
|
||||
// TODO: This really should be done somewhere else. Either lower in the IR
|
||||
// or higher in PPCAnalyst
|
||||
// TODO: We shouldn't use debug reads here.
|
||||
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bSkipIdle &&
|
||||
PowerPC::GetState() != PowerPC::CPU_STEPPING &&
|
||||
inst.OPCD == 32 && // Lwx
|
||||
(inst.hex & 0xFFFF0000) == 0x800D0000 &&
|
||||
(Memory::ReadUnchecked_U32(js.compilerPC + 4) == 0x28000000 ||
|
||||
(SConfig::GetInstance().m_LocalCoreStartupParameter.bWii && Memory::ReadUnchecked_U32(js.compilerPC + 4) == 0x2C000000)) &&
|
||||
Memory::ReadUnchecked_U32(js.compilerPC + 8) == 0x4182fff8)
|
||||
(PowerPC::HostRead_U32(js.compilerPC + 4) == 0x28000000 ||
|
||||
(SConfig::GetInstance().m_LocalCoreStartupParameter.bWii && PowerPC::HostRead_U32(js.compilerPC + 4) == 0x2C000000)) &&
|
||||
PowerPC::HostRead_U32(js.compilerPC + 8) == 0x4182fff8)
|
||||
{
|
||||
val = ibuild.EmitLoad32(addr);
|
||||
ibuild.EmitIdleBranch(val, ibuild.EmitIntConst(js.compilerPC));
|
||||
|
@ -138,7 +140,9 @@ void JitILBase::dcbst(UGeckoInstruction inst)
|
|||
// memory location. Do not invalidate the JIT cache in this case as the memory
|
||||
// will be the same.
|
||||
// dcbt = 0x7c00022c
|
||||
FALLBACK_IF((Memory::ReadUnchecked_U32(js.compilerPC - 4) & 0x7c00022c) != 0x7c00022c);
|
||||
// TODO: We shouldn't use a debug read here; it should be possible to get the
|
||||
// previous instruction from the JIT state.
|
||||
FALLBACK_IF((PowerPC::HostRead_U32(js.compilerPC - 4) & 0x7c00022c) != 0x7c00022c);
|
||||
}
|
||||
|
||||
// Zero cache line.
|
||||
|
|
|
@ -207,27 +207,6 @@ namespace JitInterface
|
|||
jit->GetBlockCache()->InvalidateICache(address, size, forced);
|
||||
}
|
||||
|
||||
u32 ReadOpcodeJIT(u32 _Address)
|
||||
{
|
||||
if (bMMU && !bFakeVMEM && (_Address & Memory::ADDR_MASK_MEM1))
|
||||
{
|
||||
_Address = Memory::TranslateAddress<Memory::FLAG_OPCODE>(_Address);
|
||||
if (_Address == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
u32 inst;
|
||||
// Bypass the icache for the external interrupt exception handler
|
||||
// -- this is stupid, should respect HID0
|
||||
if ( (_Address & 0x0FFFFF00) == 0x00000500 )
|
||||
inst = Memory::ReadUnchecked_U32(_Address);
|
||||
else
|
||||
inst = PowerPC::ppcState.iCache.ReadInstruction(_Address);
|
||||
return inst;
|
||||
}
|
||||
|
||||
void CompileExceptionCheck(ExceptionType type)
|
||||
{
|
||||
if (!jit)
|
||||
|
@ -250,7 +229,7 @@ namespace JitInterface
|
|||
if (type == ExceptionType::EXCEPTIONS_FIFO_WRITE)
|
||||
{
|
||||
// Check in case the code has been replaced since: do we need to do this?
|
||||
int optype = GetOpInfo(Memory::ReadUnchecked_U32(PC))->type;
|
||||
int optype = GetOpInfo(PowerPC::HostRead_U32(PC))->type;
|
||||
if (optype != OPTYPE_STORE && optype != OPTYPE_STOREFP && (optype != OPTYPE_STOREPS))
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -29,9 +29,6 @@ namespace JitInterface
|
|||
// Memory Utilities
|
||||
bool HandleFault(uintptr_t access_address, SContext* ctx);
|
||||
|
||||
// used by JIT to read instructions
|
||||
u32 ReadOpcodeJIT(const u32 _Address);
|
||||
|
||||
// Clearing CodeCache
|
||||
void ClearCache();
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
#include "Core/PowerPC/GDBStub.h"
|
||||
#endif
|
||||
|
||||
namespace Memory
|
||||
namespace PowerPC
|
||||
{
|
||||
|
||||
#define HW_PAGE_SIZE 4096
|
||||
|
@ -66,6 +66,14 @@ inline u32 bswap(u32 val) { return Common::swap32(val); }
|
|||
inline u64 bswap(u64 val) { return Common::swap64(val); }
|
||||
// =================
|
||||
|
||||
enum XCheckTLBFlag
|
||||
{
|
||||
FLAG_NO_EXCEPTION,
|
||||
FLAG_READ,
|
||||
FLAG_WRITE,
|
||||
FLAG_OPCODE,
|
||||
};
|
||||
template <const XCheckTLBFlag flag> static u32 TranslateAddress(const u32 address);
|
||||
|
||||
// Nasty but necessary. Super Mario Galaxy pointer relies on this stuff.
|
||||
static u32 EFB_Read(const u32 addr)
|
||||
|
@ -111,39 +119,62 @@ static void EFB_Write(u32 data, u32 addr)
|
|||
static void GenerateDSIException(u32 _EffectiveAddress, bool _bWrite);
|
||||
|
||||
template <XCheckTLBFlag flag, typename T>
|
||||
__forceinline T ReadFromHardware(const u32 em_address)
|
||||
__forceinline static T ReadFromHardware(const u32 em_address)
|
||||
{
|
||||
int segment = em_address >> 28;
|
||||
bool performTranslation = UReg_MSR(MSR).DR;
|
||||
|
||||
// Quick check for an address that can't meet any of the following conditions,
|
||||
// to speed up the MMU path.
|
||||
if (!BitSet32(0xCFC)[segment])
|
||||
if (!BitSet32(0xCFC)[segment] && performTranslation)
|
||||
{
|
||||
// TODO: Figure out the fastest order of tests for both read and write (they are probably different).
|
||||
if ((em_address & 0xC8000000) == 0xC8000000)
|
||||
if (flag == FLAG_READ && (em_address & 0xF8000000) == 0xC8000000)
|
||||
{
|
||||
if (em_address < 0xcc000000)
|
||||
return EFB_Read(em_address);
|
||||
else
|
||||
return (T)mmio_mapping->Read<typename std::make_unsigned<T>::type>(em_address);
|
||||
return (T)Memory::mmio_mapping->Read<typename std::make_unsigned<T>::type>(em_address);
|
||||
}
|
||||
else if (segment == 0x8 || segment == 0xC || segment == 0x0)
|
||||
if ((segment == 0x0 || segment == 0x8 || segment == 0xC) && (em_address & 0x0FFFFFFF) < Memory::REALRAM_SIZE)
|
||||
{
|
||||
return bswap((*(const T*)&m_pRAM[em_address & RAM_MASK]));
|
||||
return bswap((*(const T*)&Memory::m_pRAM[em_address & 0x0FFFFFFF]));
|
||||
}
|
||||
else if (m_pEXRAM && (segment == 0x9 || segment == 0xD || segment == 0x1))
|
||||
if (Memory::m_pEXRAM && (segment == 0x9 || segment == 0xD) && (em_address & 0x0FFFFFFF) < Memory::EXRAM_SIZE)
|
||||
{
|
||||
return bswap((*(const T*)&m_pEXRAM[em_address & EXRAM_MASK]));
|
||||
return bswap((*(const T*)&Memory::m_pEXRAM[em_address & 0x0FFFFFFF]));
|
||||
}
|
||||
else if (segment == 0xE && (em_address < (0xE0000000 + L1_CACHE_SIZE)))
|
||||
if (segment == 0xE && (em_address < (0xE0000000 + Memory::L1_CACHE_SIZE)))
|
||||
{
|
||||
return bswap((*(const T*)&m_pL1Cache[em_address & L1_CACHE_MASK]));
|
||||
return bswap((*(const T*)&Memory::m_pL1Cache[em_address & 0x0FFFFFFF]));
|
||||
}
|
||||
}
|
||||
|
||||
if (bFakeVMEM && (segment == 0x7 || segment == 0x4))
|
||||
if (Memory::bFakeVMEM && performTranslation && (segment == 0x7 || segment == 0x4))
|
||||
{
|
||||
// fake VMEM
|
||||
return bswap((*(const T*)&m_pFakeVMEM[em_address & FAKEVMEM_MASK]));
|
||||
return bswap((*(const T*)&Memory::m_pFakeVMEM[em_address & Memory::FAKEVMEM_MASK]));
|
||||
}
|
||||
|
||||
if (!performTranslation)
|
||||
{
|
||||
if (flag == FLAG_READ && (em_address & 0xF8000000) == 0x08000000)
|
||||
{
|
||||
if (em_address < 0x0c000000)
|
||||
return EFB_Read(em_address);
|
||||
else
|
||||
return (T)Memory::mmio_mapping->Read<typename std::make_unsigned<T>::type>(em_address | 0xC0000000);
|
||||
}
|
||||
if (em_address < Memory::REALRAM_SIZE)
|
||||
{
|
||||
return bswap((*(const T*)&Memory::m_pRAM[em_address]));
|
||||
}
|
||||
if (Memory::m_pEXRAM && segment == 0x1 && (em_address & 0x0FFFFFFF) < Memory::EXRAM_SIZE)
|
||||
{
|
||||
return bswap((*(const T*)&Memory::m_pEXRAM[em_address & 0x0FFFFFFF]));
|
||||
}
|
||||
PanicAlert("Unable to resolve read address %x PC %x", em_address, PC);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// MMU: Do page table translation
|
||||
|
@ -177,27 +208,29 @@ __forceinline T ReadFromHardware(const u32 em_address)
|
|||
{
|
||||
if (addr == em_address_next_page)
|
||||
tlb_addr = tlb_addr_next_page;
|
||||
var = (var << 8) | Memory::base[tlb_addr];
|
||||
var = (var << 8) | Memory::physical_base[tlb_addr];
|
||||
}
|
||||
return var;
|
||||
}
|
||||
|
||||
// The easy case!
|
||||
return bswap(*(const T*)&Memory::base[tlb_addr]);
|
||||
return bswap(*(const T*)&Memory::physical_base[tlb_addr]);
|
||||
}
|
||||
|
||||
|
||||
template <XCheckTLBFlag flag, typename T>
|
||||
__forceinline void WriteToHardware(u32 em_address, const T data)
|
||||
__forceinline static void WriteToHardware(u32 em_address, const T data)
|
||||
{
|
||||
int segment = em_address >> 28;
|
||||
// Quick check for an address that can't meet any of the following conditions,
|
||||
// to speed up the MMU path.
|
||||
if (!BitSet32(0xCFC)[segment])
|
||||
bool performTranslation = UReg_MSR(MSR).DR;
|
||||
|
||||
if (!BitSet32(0xCFC)[segment] && performTranslation)
|
||||
{
|
||||
// First, let's check for FIFO writes, since they are probably the most common
|
||||
// reason we end up in this function:
|
||||
if ((em_address & 0xFFFFF000) == 0xCC008000)
|
||||
if (flag == FLAG_WRITE && (em_address & 0xFFFFF000) == 0xCC008000)
|
||||
{
|
||||
switch (sizeof(T))
|
||||
{
|
||||
|
@ -207,7 +240,7 @@ __forceinline void WriteToHardware(u32 em_address, const T data)
|
|||
case 8: GPFifo::Write64((u64)data, em_address); return;
|
||||
}
|
||||
}
|
||||
if ((em_address & 0xC8000000) == 0xC8000000)
|
||||
if (flag == FLAG_WRITE && (em_address & 0xF8000000) == 0xC8000000)
|
||||
{
|
||||
if (em_address < 0xcc000000)
|
||||
{
|
||||
|
@ -217,31 +250,71 @@ __forceinline void WriteToHardware(u32 em_address, const T data)
|
|||
}
|
||||
else
|
||||
{
|
||||
mmio_mapping->Write(em_address, data);
|
||||
Memory::mmio_mapping->Write(em_address, data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (segment == 0x8 || segment == 0xC || segment == 0x0)
|
||||
if ((segment == 0x8 || segment == 0xC) && (em_address & 0x0FFFFFFF) < Memory::REALRAM_SIZE)
|
||||
{
|
||||
*(T*)&m_pRAM[em_address & RAM_MASK] = bswap(data);
|
||||
*(T*)&Memory::m_pRAM[em_address & 0x0FFFFFFF] = bswap(data);
|
||||
return;
|
||||
}
|
||||
else if (m_pEXRAM && (segment == 0x9 || segment == 0xD || segment == 0x1))
|
||||
if (Memory::m_pEXRAM && (segment == 0x9 || segment == 0xD) && (em_address & 0x0FFFFFFF) < Memory::EXRAM_SIZE)
|
||||
{
|
||||
*(T*)&m_pEXRAM[em_address & EXRAM_MASK] = bswap(data);
|
||||
*(T*)&Memory::m_pEXRAM[em_address & 0x0FFFFFFF] = bswap(data);
|
||||
return;
|
||||
}
|
||||
else if (segment == 0xE && (em_address < (0xE0000000 + L1_CACHE_SIZE)))
|
||||
if (segment == 0xE && (em_address < (0xE0000000 + Memory::L1_CACHE_SIZE)))
|
||||
{
|
||||
*(T*)&m_pL1Cache[em_address & L1_CACHE_MASK] = bswap(data);
|
||||
*(T*)&Memory::m_pL1Cache[em_address & 0x0FFFFFFF] = bswap(data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (bFakeVMEM && (segment == 0x7 || segment == 0x4))
|
||||
if (Memory::bFakeVMEM && performTranslation && (segment == 0x7 || segment == 0x4))
|
||||
{
|
||||
// fake VMEM
|
||||
*(T*)&m_pFakeVMEM[em_address & FAKEVMEM_MASK] = bswap(data);
|
||||
*(T*)&Memory::m_pFakeVMEM[em_address & Memory::FAKEVMEM_MASK] = bswap(data);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!performTranslation)
|
||||
{
|
||||
if (flag == FLAG_WRITE && (em_address & 0xFFFFF000) == 0x0C008000)
|
||||
{
|
||||
switch (sizeof(T))
|
||||
{
|
||||
case 1: GPFifo::Write8((u8)data, em_address); return;
|
||||
case 2: GPFifo::Write16((u16)data, em_address); return;
|
||||
case 4: GPFifo::Write32((u32)data, em_address); return;
|
||||
case 8: GPFifo::Write64((u64)data, em_address); return;
|
||||
}
|
||||
}
|
||||
if (flag == FLAG_WRITE && (em_address & 0xF8000000) == 0x08000000)
|
||||
{
|
||||
if (em_address < 0x0c000000)
|
||||
{
|
||||
// TODO: This only works correctly for 32-bit writes.
|
||||
EFB_Write((u32)data, em_address);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
Memory::mmio_mapping->Write(em_address | 0xC0000000, data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (em_address < Memory::REALRAM_SIZE)
|
||||
{
|
||||
*(T*)&Memory::m_pRAM[em_address] = bswap(data);
|
||||
return;
|
||||
}
|
||||
if (Memory::m_pEXRAM && segment == 0x1 && (em_address & 0x0FFFFFFF) < Memory::EXRAM_SIZE)
|
||||
{
|
||||
*(T*)&Memory::m_pEXRAM[em_address & 0x0FFFFFFF] = bswap(data);
|
||||
return;
|
||||
}
|
||||
PanicAlert("Unable to resolve write address %x PC %x", em_address, PC);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -272,13 +345,13 @@ __forceinline void WriteToHardware(u32 em_address, const T data)
|
|||
{
|
||||
if (addr == em_address_next_page)
|
||||
tlb_addr = tlb_addr_next_page;
|
||||
Memory::base[tlb_addr] = (u8)val;
|
||||
Memory::physical_base[tlb_addr] = (u8)val;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// The easy case!
|
||||
*(T*)&Memory::base[tlb_addr] = bswap(data);
|
||||
*(T*)&Memory::physical_base[tlb_addr] = bswap(data);
|
||||
}
|
||||
// =====================
|
||||
|
||||
|
@ -292,30 +365,59 @@ static void GenerateISIException(u32 effective_address);
|
|||
|
||||
u32 Read_Opcode(u32 address)
|
||||
{
|
||||
if (address == 0x00000000)
|
||||
TryReadInstResult result = TryReadInstruction(address);
|
||||
if (!result.valid)
|
||||
{
|
||||
// FIXME use assert?
|
||||
PanicAlert("Program tried to read an opcode from [00000000]. It has crashed.");
|
||||
return 0x00000000;
|
||||
GenerateISIException(address);
|
||||
return 0;
|
||||
}
|
||||
return result.hex;
|
||||
}
|
||||
|
||||
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bMMU &&
|
||||
(address & ADDR_MASK_MEM1))
|
||||
TryReadInstResult TryReadInstruction(u32 address)
|
||||
{
|
||||
bool from_bat = true;
|
||||
if (UReg_MSR(MSR).IR)
|
||||
{
|
||||
// TODO: Check for MSR instruction address translation flag before translating
|
||||
u32 tlb_addr = TranslateAddress<FLAG_OPCODE>(address);
|
||||
if (tlb_addr == 0)
|
||||
// TODO: Use real translation.
|
||||
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bMMU && (address & Memory::ADDR_MASK_MEM1))
|
||||
{
|
||||
GenerateISIException(address);
|
||||
return 0;
|
||||
u32 tlb_addr = TranslateAddress<FLAG_OPCODE>(address);
|
||||
if (tlb_addr == 0)
|
||||
{
|
||||
return TryReadInstResult{ false, false, 0 };
|
||||
}
|
||||
else
|
||||
{
|
||||
address = tlb_addr;
|
||||
from_bat = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
address = tlb_addr;
|
||||
int segment = address >> 28;
|
||||
if ((segment == 0x8 || segment == 0x0) && (address & 0x0FFFFFFF) < Memory::REALRAM_SIZE)
|
||||
address = address & 0x3FFFFFFF;
|
||||
else if (segment == 0x9 && (address & 0x0FFFFFFF) < Memory::EXRAM_SIZE)
|
||||
address = address & 0x3FFFFFFF;
|
||||
else
|
||||
return TryReadInstResult{ false, false, 0 };
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (address & 0xC0000000)
|
||||
ERROR_LOG(MEMMAP, "Strange program counter with address translation off: 0x%08x", address);
|
||||
}
|
||||
|
||||
return PowerPC::ppcState.iCache.ReadInstruction(address);
|
||||
u32 hex = PowerPC::ppcState.iCache.ReadInstruction(address);
|
||||
return TryReadInstResult{ true, from_bat, hex };
|
||||
}
|
||||
|
||||
u32 HostRead_Instruction(const u32 address)
|
||||
{
|
||||
UGeckoInstruction inst = HostRead_U32(address);
|
||||
return inst.hex;
|
||||
}
|
||||
|
||||
static __forceinline void Memcheck(u32 address, u32 var, bool write, int size)
|
||||
|
@ -442,30 +544,103 @@ void Write_F64(const double var, const u32 address)
|
|||
cvt.d = var;
|
||||
Write_U64(cvt.i, address);
|
||||
}
|
||||
u8 ReadUnchecked_U8(const u32 address)
|
||||
|
||||
u8 HostRead_U8(const u32 address)
|
||||
{
|
||||
u8 var = ReadFromHardware<FLAG_NO_EXCEPTION, u8>(address);
|
||||
return var;
|
||||
}
|
||||
|
||||
u16 HostRead_U16(const u32 address)
|
||||
{
|
||||
u16 var = ReadFromHardware<FLAG_NO_EXCEPTION, u16>(address);
|
||||
return var;
|
||||
}
|
||||
|
||||
u32 ReadUnchecked_U32(const u32 address)
|
||||
u32 HostRead_U32(const u32 address)
|
||||
{
|
||||
u32 var = ReadFromHardware<FLAG_NO_EXCEPTION, u32>(address);
|
||||
return var;
|
||||
}
|
||||
|
||||
void WriteUnchecked_U8(const u8 var, const u32 address)
|
||||
void HostWrite_U8(const u8 var, const u32 address)
|
||||
{
|
||||
WriteToHardware<FLAG_NO_EXCEPTION, u8>(address, var);
|
||||
}
|
||||
|
||||
void HostWrite_U16(const u16 var, const u32 address)
|
||||
{
|
||||
WriteToHardware<FLAG_NO_EXCEPTION, u16>(address, var);
|
||||
}
|
||||
|
||||
void WriteUnchecked_U32(const u32 var, const u32 address)
|
||||
void HostWrite_U32(const u32 var, const u32 address)
|
||||
{
|
||||
WriteToHardware<FLAG_NO_EXCEPTION, u32>(address, var);
|
||||
}
|
||||
|
||||
void HostWrite_U64(const u64 var, const u32 address)
|
||||
{
|
||||
WriteToHardware<FLAG_NO_EXCEPTION, u64>(address, var);
|
||||
}
|
||||
|
||||
std::string HostGetString(u32 address, size_t size)
|
||||
{
|
||||
std::string s;
|
||||
do
|
||||
{
|
||||
if (!HostIsRAMAddress(address))
|
||||
break;
|
||||
u8 res = HostRead_U8(address);
|
||||
if (!res)
|
||||
break;
|
||||
++address;
|
||||
} while (size == 0 || s.length() < size);
|
||||
return s;
|
||||
}
|
||||
|
||||
bool IsOptimizableRAMAddress(const u32 address)
|
||||
{
|
||||
if (!UReg_MSR(MSR).DR)
|
||||
return false;
|
||||
|
||||
int segment = address >> 28;
|
||||
|
||||
return (((segment == 0x8 || segment == 0xC || segment == 0x0) && (address & 0x0FFFFFFF) < Memory::REALRAM_SIZE) ||
|
||||
(Memory::m_pEXRAM && (segment == 0x9 || segment == 0xD) && (address & 0x0FFFFFFF) < Memory::EXRAM_SIZE) ||
|
||||
(segment == 0xE && (address < (0xE0000000 + Memory::L1_CACHE_SIZE))));
|
||||
}
|
||||
|
||||
bool HostIsRAMAddress(u32 address)
|
||||
{
|
||||
// TODO: This needs to be rewritten; it makes incorrect assumptions
|
||||
// about BATs and page tables.
|
||||
bool performTranslation = UReg_MSR(MSR).DR;
|
||||
int segment = address >> 28;
|
||||
if (performTranslation)
|
||||
{
|
||||
if ((segment == 0x8 || segment == 0xC || segment == 0x0) && (address & 0x0FFFFFFF) < Memory::REALRAM_SIZE)
|
||||
return true;
|
||||
else if (Memory::m_pEXRAM && (segment == 0x9 || segment == 0xD) && (address & 0x0FFFFFFF) < Memory::EXRAM_SIZE)
|
||||
return true;
|
||||
else if (Memory::bFakeVMEM && (segment == 0x7 || segment == 0x4))
|
||||
return true;
|
||||
else if (segment == 0xE && (address < (0xE0000000 + Memory::L1_CACHE_SIZE)))
|
||||
return true;
|
||||
|
||||
address = TranslateAddress<FLAG_NO_EXCEPTION>(address);
|
||||
if (!address)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (segment == 0x0 && (address & 0x0FFFFFFF) < Memory::REALRAM_SIZE)
|
||||
return true;
|
||||
else if (Memory::m_pEXRAM && segment == 0x1 && (address & 0x0FFFFFFF) < Memory::EXRAM_SIZE)
|
||||
return true;
|
||||
return false;
|
||||
|
||||
|
||||
}
|
||||
|
||||
void DMA_LCToMemory(const u32 memAddr, const u32 cacheAddr, const u32 numBlocks)
|
||||
{
|
||||
// TODO: It's not completely clear this is the right spot for this code;
|
||||
|
@ -475,7 +650,7 @@ void DMA_LCToMemory(const u32 memAddr, const u32 cacheAddr, const u32 numBlocks)
|
|||
// Avatar: The Last Airbender (GC) uses this for videos.
|
||||
if ((memAddr & 0x0F000000) == 0x08000000)
|
||||
{
|
||||
for (u32 i = 0; i < 32 * numBlocks; i+=4)
|
||||
for (u32 i = 0; i < 32 * numBlocks; i += 4)
|
||||
{
|
||||
u32 data = bswap(*(u32*)(Memory::m_pL1Cache + ((cacheAddr + i) & 0x3FFFF)));
|
||||
EFB_Write(data, memAddr + i);
|
||||
|
@ -490,7 +665,7 @@ void DMA_LCToMemory(const u32 memAddr, const u32 cacheAddr, const u32 numBlocks)
|
|||
for (u32 i = 0; i < 32 * numBlocks; i += 4)
|
||||
{
|
||||
u32 data = bswap(*(u32*)(Memory::m_pL1Cache + ((cacheAddr + i) & 0x3FFFF)));
|
||||
mmio_mapping->Write(memAddr + i, data);
|
||||
Memory::mmio_mapping->Write(memAddr + i, data);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -526,7 +701,7 @@ void DMA_MemoryToLC(const u32 cacheAddr, const u32 memAddr, const u32 numBlocks)
|
|||
{
|
||||
for (u32 i = 0; i < 32 * numBlocks; i += 4)
|
||||
{
|
||||
u32 data = mmio_mapping->Read<u32>(memAddr + i);
|
||||
u32 data = Memory::mmio_mapping->Read<u32>(memAddr + i);
|
||||
*(u32*)(Memory::m_pL1Cache + ((cacheAddr + i) & 0x3FFFF)) = bswap(data);
|
||||
}
|
||||
return;
|
||||
|
@ -538,6 +713,14 @@ void DMA_MemoryToLC(const u32 cacheAddr, const u32 memAddr, const u32 numBlocks)
|
|||
memcpy(dst, src, 32 * numBlocks);
|
||||
}
|
||||
|
||||
void ClearCacheLine(const u32 address)
|
||||
{
|
||||
// FIXME: does this do the right thing if dcbz is run on hardware memory, e.g.
|
||||
// the FIFO? Do games even do that? Probably not, but we should try to be correct...
|
||||
for (u32 i = 0; i < 32; i += 8)
|
||||
Write_U64(0, address + i);
|
||||
}
|
||||
|
||||
// *********************************************************************************
|
||||
// Warning: Test Area
|
||||
//
|
||||
|
@ -785,10 +968,6 @@ static __forceinline u32 TranslatePageAddress(const u32 address, const XCheckTLB
|
|||
u32 VSID = SR_VSID(sr); // 24 bit
|
||||
u32 api = EA_API(address); // 6 bit (part of page_index)
|
||||
|
||||
// Direct access to the fastmem Arena
|
||||
// FIXME: is this the best idea for clean code?
|
||||
u8* base_mem = Memory::base;
|
||||
|
||||
// hash function no 1 "xor" .360
|
||||
u32 hash = (VSID ^ page_index);
|
||||
u32 pte1 = bswap((VSID << 7) | api | PTE1_V);
|
||||
|
@ -806,10 +985,10 @@ static __forceinline u32 TranslatePageAddress(const u32 address, const XCheckTLB
|
|||
|
||||
for (int i = 0; i < 8; i++, pteg_addr += 8)
|
||||
{
|
||||
if (pte1 == *(u32*)&base_mem[pteg_addr])
|
||||
if (pte1 == *(u32*)&Memory::physical_base[pteg_addr])
|
||||
{
|
||||
UPTE2 PTE2;
|
||||
PTE2.Hex = bswap((*(u32*)&base_mem[(pteg_addr + 4)]));
|
||||
PTE2.Hex = bswap((*(u32*)&Memory::physical_base[pteg_addr + 4]));
|
||||
|
||||
// set the access bits
|
||||
switch (flag)
|
||||
|
@ -821,7 +1000,7 @@ static __forceinline u32 TranslatePageAddress(const u32 address, const XCheckTLB
|
|||
}
|
||||
|
||||
if (flag != FLAG_NO_EXCEPTION)
|
||||
*(u32*)&base_mem[(pteg_addr + 4)] = bswap(PTE2.Hex);
|
||||
*(u32*)&Memory::physical_base[pteg_addr + 4] = bswap(PTE2.Hex);
|
||||
|
||||
// We already updated the TLB entry if this was caused by a C bit.
|
||||
if (res != TLB_UPDATE_C)
|
||||
|
@ -895,16 +1074,12 @@ static u32 TranslateBlockAddress(const u32 address, const XCheckTLBFlag flag)
|
|||
|
||||
// Translate effective address using BAT or PAT. Returns 0 if the address cannot be translated.
|
||||
template <const XCheckTLBFlag flag>
|
||||
u32 TranslateAddress(const u32 address)
|
||||
__forceinline u32 TranslateAddress(const u32 address)
|
||||
{
|
||||
// Check MSR[IR] bit before translating instruction addresses. Rogue Leader clears IR and DR??
|
||||
//if ((_Flag == FLAG_OPCODE) && !(MSR & (1 << (31 - 26)))) return _Address;
|
||||
|
||||
// Check MSR[DR] bit before translating data addresses
|
||||
//if (((_Flag == FLAG_READ) || (_Flag == FLAG_WRITE)) && !(MSR & (1 << (31 - 27)))) return _Address;
|
||||
|
||||
// Technically we should do this, but almost no games, even heavy MMU ones, use any custom BATs whatsoever,
|
||||
// so only do it where it's really needed.
|
||||
// TODO: bBAT in theory should allow dynamic changes to the BAT registers.
|
||||
// In reality, the option is mostly useless at the moment because we don't
|
||||
// always translate addresses when we should. ReadFromHardware/WriteFromHardware,
|
||||
// fastmem, the JIT cache, and some misc code in the JIT assume default BATs.
|
||||
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bBAT)
|
||||
{
|
||||
u32 tlb_addr = TranslateBlockAddress(address, flag);
|
||||
|
@ -914,8 +1089,4 @@ u32 TranslateAddress(const u32 address)
|
|||
return TranslatePageAddress(address, flag);
|
||||
}
|
||||
|
||||
template u32 TranslateAddress<Memory::FLAG_NO_EXCEPTION>(const u32 address);
|
||||
template u32 TranslateAddress<Memory::FLAG_READ>(const u32 address);
|
||||
template u32 TranslateAddress<Memory::FLAG_WRITE>(const u32 address);
|
||||
template u32 TranslateAddress<Memory::FLAG_OPCODE>(const u32 address);
|
||||
} // namespace
|
|
@ -96,7 +96,7 @@ bool AnalyzeFunction(u32 startAddr, Symbol &func, int max_size)
|
|||
if (func.size >= CODEBUFFER_SIZE * 4) //weird
|
||||
return false;
|
||||
|
||||
UGeckoInstruction instr = (UGeckoInstruction)Memory::ReadUnchecked_U32(addr);
|
||||
UGeckoInstruction instr = (UGeckoInstruction)PowerPC::HostRead_U32(addr);
|
||||
if (max_size && func.size > max_size)
|
||||
{
|
||||
func.address = startAddr;
|
||||
|
@ -275,7 +275,7 @@ static void FindFunctionsFromBranches(u32 startAddr, u32 endAddr, SymbolDB *func
|
|||
{
|
||||
for (u32 addr = startAddr; addr < endAddr; addr+=4)
|
||||
{
|
||||
UGeckoInstruction instr = (UGeckoInstruction)Memory::ReadUnchecked_U32(addr);
|
||||
UGeckoInstruction instr = (UGeckoInstruction)PowerPC::HostRead_U32(addr);
|
||||
|
||||
if (PPCTables::IsValidInstruction(instr))
|
||||
{
|
||||
|
@ -288,7 +288,7 @@ static void FindFunctionsFromBranches(u32 startAddr, u32 endAddr, SymbolDB *func
|
|||
u32 target = SignExt26(instr.LI << 2);
|
||||
if (!instr.AA)
|
||||
target += addr;
|
||||
if (Memory::IsRAMAddress(target))
|
||||
if (PowerPC::HostIsRAMAddress(target))
|
||||
{
|
||||
func_db->AddFunction(target);
|
||||
}
|
||||
|
@ -314,9 +314,9 @@ static void FindFunctionsAfterBLR(PPCSymbolDB *func_db)
|
|||
while (true)
|
||||
{
|
||||
// skip zeroes that sometimes pad function to 16 byte boundary (e.g. Donkey Kong Country Returns)
|
||||
while (Memory::Read_Instruction(location) == 0 && ((location & 0xf) != 0))
|
||||
while (PowerPC::HostRead_Instruction(location) == 0 && ((location & 0xf) != 0))
|
||||
location += 4;
|
||||
if (PPCTables::IsValidInstruction(Memory::Read_Instruction(location)))
|
||||
if (PPCTables::IsValidInstruction(PowerPC::HostRead_Instruction(location)))
|
||||
{
|
||||
//check if this function is already mapped
|
||||
Symbol *f = func_db->AddFunction(location);
|
||||
|
@ -649,34 +649,24 @@ u32 PPCAnalyzer::Analyze(u32 address, CodeBlock *block, CodeBuffer *buffer, u32
|
|||
block->m_num_instructions = 0;
|
||||
block->m_gqr_used = BitSet8(0);
|
||||
|
||||
if (address == 0)
|
||||
{
|
||||
// Memory exception occurred during instruction fetch
|
||||
block->m_memory_exception = true;
|
||||
return address;
|
||||
}
|
||||
|
||||
bool virtualAddr = SConfig::GetInstance().m_LocalCoreStartupParameter.bMMU && (address & JIT_ICACHE_VMEM_BIT);
|
||||
if (virtualAddr)
|
||||
{
|
||||
if (!Memory::TranslateAddress<Memory::FLAG_NO_EXCEPTION>(address))
|
||||
{
|
||||
// Memory exception occurred during instruction fetch
|
||||
block->m_memory_exception = true;
|
||||
return address;
|
||||
}
|
||||
}
|
||||
|
||||
CodeOp *code = buffer->codebuffer;
|
||||
|
||||
bool found_exit = false;
|
||||
u32 return_address = 0;
|
||||
u32 numFollows = 0;
|
||||
u32 num_inst = 0;
|
||||
bool prev_inst_from_bat = true;
|
||||
|
||||
for (u32 i = 0; i < blockSize; ++i)
|
||||
{
|
||||
UGeckoInstruction inst = JitInterface::ReadOpcodeJIT(address);
|
||||
auto result = PowerPC::TryReadInstruction(address);
|
||||
if (!result.valid)
|
||||
{
|
||||
if (i == 0)
|
||||
block->m_memory_exception = true;
|
||||
break;
|
||||
}
|
||||
UGeckoInstruction inst = result.hex;
|
||||
|
||||
if (inst.hex != 0)
|
||||
{
|
||||
|
@ -684,10 +674,11 @@ u32 PPCAnalyzer::Analyze(u32 address, CodeBlock *block, CodeBuffer *buffer, u32
|
|||
// but broken blocks due to page faults break this assumption. Avoid this by just ending
|
||||
// all virtual memory instruction blocks at page boundaries.
|
||||
// FIXME: improve the JIT block cache so we don't need to do this.
|
||||
if (virtualAddr && i > 0 && (address & 0xfff) == 0)
|
||||
if ((!result.from_bat || !prev_inst_from_bat) && i > 0 && (address & 0xfff) == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
prev_inst_from_bat = result.from_bat;
|
||||
|
||||
num_inst++;
|
||||
memset(&code[i], 0, sizeof(CodeOp));
|
||||
|
@ -813,10 +804,7 @@ u32 PPCAnalyzer::Analyze(u32 address, CodeBlock *block, CodeBuffer *buffer, u32
|
|||
}
|
||||
else
|
||||
{
|
||||
// ISI exception or other critical memory exception occured (game over)
|
||||
// We can continue on in MMU mode though, so don't spam this error in that case.
|
||||
if (!virtualAddr)
|
||||
ERROR_LOG(DYNA_REC, "Instruction hex was 0!");
|
||||
ERROR_LOG(DYNA_REC, "Instruction hex was 0!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -100,7 +100,7 @@ namespace PowerPC
|
|||
u32 InstructionCache::ReadInstruction(u32 addr)
|
||||
{
|
||||
if (!HID0.ICE) // instruction cache is disabled
|
||||
return Memory::ReadUnchecked_U32(addr);
|
||||
return Memory::Read_U32(addr);
|
||||
u32 set = (addr >> 5) & 0x7f;
|
||||
u32 tag = addr >> 12;
|
||||
|
||||
|
@ -121,7 +121,7 @@ namespace PowerPC
|
|||
if (t == 0xff) // load to the cache
|
||||
{
|
||||
if (HID0.ILOCK) // instruction cache is locked
|
||||
return Memory::ReadUnchecked_U32(addr);
|
||||
return Memory::Read_U32(addr);
|
||||
// select a way
|
||||
if (valid[set] != 0xff)
|
||||
t = way_from_valid[valid[set]];
|
||||
|
|
|
@ -86,7 +86,7 @@ void PPCSymbolDB::AddKnownSymbol(u32 startAddr, u32 size, const std::string& nam
|
|||
|
||||
Symbol *PPCSymbolDB::GetSymbolFromAddr(u32 addr)
|
||||
{
|
||||
if (!Memory::IsRAMAddress(addr))
|
||||
if (!PowerPC::HostIsRAMAddress(addr))
|
||||
return nullptr;
|
||||
|
||||
XFuncMap::iterator it = functions.find(addr);
|
||||
|
@ -333,11 +333,11 @@ bool PPCSymbolDB::LoadMap(const std::string& filename, bool bad)
|
|||
if (!good)
|
||||
{
|
||||
// check for BLR before function
|
||||
u32 opcode = Memory::Read_Instruction(vaddress - 4);
|
||||
u32 opcode = PowerPC::HostRead_Instruction(vaddress - 4);
|
||||
if (opcode == 0x4e800020)
|
||||
{
|
||||
// check for BLR at end of function
|
||||
opcode = Memory::Read_Instruction(vaddress + size - 4);
|
||||
opcode = PowerPC::HostRead_Instruction(vaddress + size - 4);
|
||||
if (opcode == 0x4e800020)
|
||||
good = true;
|
||||
}
|
||||
|
|
|
@ -192,6 +192,75 @@ void UpdatePerformanceMonitor(u32 cycles, u32 num_load_stores, u32 num_fp_inst);
|
|||
#define riPS0(i) (*(u64*)(&PowerPC::ppcState.ps[i][0]))
|
||||
#define riPS1(i) (*(u64*)(&PowerPC::ppcState.ps[i][1]))
|
||||
|
||||
// Routines for debugger UI, cheats, etc. to access emulated memory from the
|
||||
// perspective of the CPU. Not for use by core emulation routines.
|
||||
// Use "Host_" prefix.
|
||||
u8 HostRead_U8(const u32 address);
|
||||
u16 HostRead_U16(const u32 address);
|
||||
u32 HostRead_U32(const u32 address);
|
||||
u32 HostRead_Instruction(const u32 address);
|
||||
|
||||
void HostWrite_U8(const u8 var, const u32 address);
|
||||
void HostWrite_U16(const u16 var, const u32 address);
|
||||
void HostWrite_U32(const u32 var, const u32 address);
|
||||
void HostWrite_U64(const u64 var, const u32 address);
|
||||
|
||||
// Returns whether a read or write to the given address will resolve to a RAM
|
||||
// access given the current CPU state.
|
||||
bool HostIsRAMAddress(const u32 address);
|
||||
|
||||
std::string HostGetString(u32 em_address, size_t size = 0);
|
||||
|
||||
// Routines for the CPU core to access memory.
|
||||
|
||||
// Used by interpreter to read instructions, uses iCache
|
||||
u32 Read_Opcode(const u32 address);
|
||||
struct TryReadInstResult
|
||||
{
|
||||
bool valid;
|
||||
bool from_bat;
|
||||
u32 hex;
|
||||
};
|
||||
TryReadInstResult TryReadInstruction(const u32 address);
|
||||
|
||||
u8 Read_U8(const u32 address);
|
||||
u16 Read_U16(const u32 address);
|
||||
u32 Read_U32(const u32 address);
|
||||
u64 Read_U64(const u32 address);
|
||||
|
||||
// Useful helper functions, used by ARM JIT
|
||||
float Read_F32(const u32 address);
|
||||
double Read_F64(const u32 address);
|
||||
|
||||
// used by JIT. Return zero-extended 32bit values
|
||||
u32 Read_U8_ZX(const u32 address);
|
||||
u32 Read_U16_ZX(const u32 address);
|
||||
|
||||
void Write_U8(const u8 var, const u32 address);
|
||||
void Write_U16(const u16 var, const u32 address);
|
||||
void Write_U32(const u32 var, const u32 address);
|
||||
void Write_U64(const u64 var, const u32 address);
|
||||
|
||||
void Write_U16_Swap(const u16 var, const u32 address);
|
||||
void Write_U32_Swap(const u32 var, const u32 address);
|
||||
void Write_U64_Swap(const u64 var, const u32 address);
|
||||
|
||||
// Useful helper functions, used by ARM JIT
|
||||
void Write_F64(const double var, const u32 address);
|
||||
|
||||
void DMA_LCToMemory(const u32 memAddr, const u32 cacheAddr, const u32 numBlocks);
|
||||
void DMA_MemoryToLC(const u32 cacheAddr, const u32 memAddr, const u32 numBlocks);
|
||||
void ClearCacheLine(const u32 address); // Zeroes 32 bytes; address should be 32-byte-aligned
|
||||
|
||||
// TLB functions
|
||||
void SDRUpdated();
|
||||
void InvalidateTLBEntry(u32 address);
|
||||
|
||||
// Result changes based on the BAT registers and MSR.DR. Returns whether
|
||||
// it's safe to optimize a read or write to this address to an unguarded
|
||||
// memory access. Does not consider page tables.
|
||||
bool IsOptimizableRAMAddress(const u32 address);
|
||||
|
||||
} // namespace
|
||||
|
||||
enum CRBits
|
||||
|
|
|
@ -150,7 +150,7 @@ void SignatureDB::Initialize(PPCSymbolDB *symbol_db, const std::string& prefix)
|
|||
u32 sum = 0;
|
||||
for (u32 offset = offsetStart; offset <= offsetEnd; offset += 4)
|
||||
{
|
||||
u32 opcode = Memory::Read_Instruction(offset);
|
||||
u32 opcode = PowerPC::HostRead_Instruction(offset);
|
||||
u32 op = opcode & 0xFC000000;
|
||||
u32 op2 = 0;
|
||||
u32 op3 = 0;
|
||||
|
|
|
@ -298,7 +298,7 @@ void CCodeWindow::StepOver()
|
|||
{
|
||||
if (CCPU::IsStepping())
|
||||
{
|
||||
UGeckoInstruction inst = Memory::Read_Instruction(PC);
|
||||
UGeckoInstruction inst = PowerPC::HostRead_Instruction(PC);
|
||||
if (inst.LK)
|
||||
{
|
||||
PowerPC::breakpoints.ClearAllTemporary();
|
||||
|
@ -329,7 +329,7 @@ void CCodeWindow::StepOut()
|
|||
u64 steps = 0;
|
||||
PowerPC::CoreMode oldMode = PowerPC::GetMode();
|
||||
PowerPC::SetMode(PowerPC::MODE_INTERPRETER);
|
||||
UGeckoInstruction inst = Memory::Read_Instruction(PC);
|
||||
UGeckoInstruction inst = PowerPC::HostRead_Instruction(PC);
|
||||
while (inst.hex != 0x4e800020 && steps < timeout) // check for blr
|
||||
{
|
||||
if (inst.LK)
|
||||
|
@ -347,7 +347,7 @@ void CCodeWindow::StepOut()
|
|||
PowerPC::SingleStep();
|
||||
++steps;
|
||||
}
|
||||
inst = Memory::Read_Instruction(PC);
|
||||
inst = PowerPC::HostRead_Instruction(PC);
|
||||
}
|
||||
|
||||
PowerPC::SingleStep();
|
||||
|
@ -604,7 +604,7 @@ void CCodeWindow::OnJitMenu(wxCommandEvent& event)
|
|||
bool found = false;
|
||||
for (u32 addr = 0x80000000; addr < 0x80180000; addr += 4)
|
||||
{
|
||||
const char *name = PPCTables::GetInstructionName(Memory::ReadUnchecked_U32(addr));
|
||||
const char *name = PPCTables::GetInstructionName(PowerPC::HostRead_U32(addr));
|
||||
if (name && (wx_name == name))
|
||||
{
|
||||
NOTICE_LOG(POWERPC, "Found %s at %08x", wx_name.c_str(), addr);
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#include "Common/CommonTypes.h"
|
||||
#include "Common/DebugInterface.h"
|
||||
#include "Common/StringUtil.h"
|
||||
#include "Core/HW/Memmap.h"
|
||||
#include "Core/PowerPC/PowerPC.h"
|
||||
#include "DolphinWX/Frame.h"
|
||||
#include "DolphinWX/Globals.h"
|
||||
#include "DolphinWX/WxUtils.h"
|
||||
|
@ -324,7 +324,7 @@ void CMemoryView::OnPaint(wxPaintEvent& event)
|
|||
dc.SetTextForeground(*wxBLACK);
|
||||
}
|
||||
|
||||
if (!Memory::IsRAMAddress(address))
|
||||
if (!PowerPC::HostIsRAMAddress(address))
|
||||
continue;
|
||||
|
||||
if (debugger->IsAlive())
|
||||
|
|
|
@ -181,7 +181,7 @@ void CMemoryWindow::SetMemoryValue(wxCommandEvent& event)
|
|||
return;
|
||||
}
|
||||
|
||||
Memory::Write_U32(val, addr);
|
||||
PowerPC::HostWrite_U32(val, addr);
|
||||
memview->Refresh();
|
||||
}
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ static u32 GetWatchAddr(int count)
|
|||
|
||||
static u32 GetWatchValue(int count)
|
||||
{
|
||||
return Memory::ReadUnchecked_U32(GetWatchAddr(count));
|
||||
return PowerPC::HostRead_U32(GetWatchAddr(count));
|
||||
}
|
||||
|
||||
static void AddWatchAddr(int count, u32 value)
|
||||
|
@ -71,7 +71,7 @@ static void SetWatchName(int count, const std::string& value)
|
|||
|
||||
static void SetWatchValue(int count, u32 value)
|
||||
{
|
||||
Memory::WriteUnchecked_U32(value, GetWatchAddr(count));
|
||||
PowerPC::HostWrite_U32(value, GetWatchAddr(count));
|
||||
}
|
||||
|
||||
static wxString GetValueByRowCol(int row, int col)
|
||||
|
@ -102,8 +102,8 @@ static wxString GetValueByRowCol(int row, int col)
|
|||
case 4:
|
||||
{
|
||||
u32 addr = GetWatchAddr(row);
|
||||
if (Memory::IsRAMAddress(addr))
|
||||
return Memory::GetString(addr, 32).c_str();
|
||||
if (PowerPC::HostIsRAMAddress(addr))
|
||||
return PowerPC::HostGetString(addr, 32).c_str();
|
||||
else
|
||||
return wxEmptyString;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue