Merge pull request #1856 from magumagu/correct-translation-disable-2

Make address translation respect the CPU translation mode
This commit is contained in:
magumagu 2015-02-11 17:04:12 -08:00
commit 0e0a196a1c
61 changed files with 1021 additions and 788 deletions

View File

@ -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))

View File

@ -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;

View File

@ -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:

View File

@ -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

View File

@ -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();

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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" />

View File

@ -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>

View File

@ -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)

View File

@ -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] =
{

View File

@ -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()

View File

@ -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)

View File

@ -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();
}

View File

@ -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);
}

View File

@ -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()

View File

@ -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();

View File

@ -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)

View File

@ -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;
@ -102,17 +103,60 @@ bool IsInitialized()
}
// We don't declare the IO region in here since its handled by other means.
// Dolphin allocates memory to represent four regions:
// - 24MB RAM, available on Gamecube and Wii
// - 64MB "EXRAM", RAM only available on Wii
// - 64MB FakeVMem, allocated when MMU support is turned off. This is used
// to approximate the behavior of a common library which pages memory to
// and from the DSP's dedicated RAM, which isn't directly addressable on
// GameCube.
// - 256KB Locked L1, to represent cache lines allocated out of the L1 data cache
// cache in Locked L1 mode. Dolphin does not emulate this hardware feature
// accurately; it just pretends there is extra memory at 0xE0000000.
//
// The 4GB starting at physical_base represents access from the CPU
// with address translation turned off. (This is only used by the CPU;
// other devices, like the GPU, use other rules, approximated by
// Memory::GetPointer.) This memory is laid out as follows:
// [0x00000000, 0x01800000) - 24MB RAM
// [0x08000000, 0x0C000000) - EFB "mapping" (not handled here)
// [0x0C000000, 0x0E000000) - MMIO etc. (not handled here)
// [0x10000000, 0x14000000) - 64MB RAM (Wii-only; slightly slower)
//
// The 4GB starting at logical_base represents access from the CPU
// with address translation turned on. Instead of changing the mapping
// based on the BAT registers, we approximate the common BAT configuration
// used by games:
// [0x00000000, 0x01800000) - 24MB RAM, cached access, normally only mapped
// during startup by Wii WADs
// [0x40000000, 0x50000000) - FakeVMEM
// [0x70000000, 0x80000000) - FakeVMEM
// [0x80000000, 0x81800000) - 24MB RAM, cached access
// [0x90000000, 0x94000000) - 64MB RAM, Wii-only, cached access
// [0xC0000000, 0xC1800000) - 24MB RAM, uncached access
// [0xC8000000, 0xCC000000) - EFB "mapping" (not handled here)
// [0xCC000000, 0xCE000000) - MMIO etc. (not handled here)
// [0xD0000000, 0xD4000000) - 64MB RAM, Wii-only, uncached access
// [0xE0000000, 0xE0040000) - 256KB locked L1
//
// TODO: We shouldn't hardcode this mapping; we can generate it dynamically
// based on the BAT registers.
//
// Each of these 4GB regions is followed by 4GB of empty space so overflows
// in address computation in the JIT don't access the wrong memory.
//
// Dolphin doesn't emulate the difference between cached and uncached access.
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 +173,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 +211,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 +236,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 +270,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 +289,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

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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()

View File

@ -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)

View File

@ -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);

View File

@ -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)

View File

@ -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:

View File

@ -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));
}

View File

@ -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:

View File

@ -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;
}

View File

@ -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);*/
}

View File

@ -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);

View File

@ -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)

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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)

View File

@ -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);

View File

@ -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);

View File

@ -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))
@ -215,12 +217,12 @@ u32 JitArm64::EmitBackpatchRoutine(ARM64XEmitter* emit, u32 flags, bool fastmem,
{
float_emit.FCVT(32, 64, Q0, RS);
float_emit.UMOV(32, W0, Q0, 0);
emit->MOVI2R(X30, (u64)&Memory::Write_U32);
emit->MOVI2R(X30, (u64)&PowerPC::Write_U32);
emit->BLR(X30);
}
else
{
emit->MOVI2R(X30, (u64)&Memory::Write_U64);
emit->MOVI2R(X30, (u64)&PowerPC::Write_U64);
float_emit.UMOV(64, X0, RS, 0);
emit->BLR(X30);
}
@ -232,14 +234,14 @@ u32 JitArm64::EmitBackpatchRoutine(ARM64XEmitter* emit, u32 flags, bool fastmem,
ARM64FloatEmitter float_emit(emit);
if (flags & BackPatchInfo::FLAG_SIZE_F32)
{
emit->MOVI2R(X30, (u64)&Memory::Read_U32);
emit->MOVI2R(X30, (u64)&PowerPC::Read_U32);
emit->BLR(X30);
float_emit.DUP(32, RS, X0);
float_emit.FCVTL(64, RS, RS);
}
else
{
emit->MOVI2R(X30, (u64)&Memory::Read_F64);
emit->MOVI2R(X30, (u64)&PowerPC::Read_F64);
emit->BLR(X30);
float_emit.INS(64, RS, 0, X0);
}
@ -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;

View File

@ -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));

View File

@ -181,7 +181,7 @@ void JitArm64::lfXX(UGeckoInstruction inst)
fprs_in_use[0] = 0; // Q0
fprs_in_use[VD - Q0] = 0;
if (is_immediate && Memory::IsRAMAddress(imm_addr))
if (is_immediate && PowerPC::IsOptimizableRAMAddress(imm_addr))
{
EmitBackpatchRoutine(this, flags, true, false, VD, XA);
}
@ -399,7 +399,7 @@ void JitArm64::stfXX(UGeckoInstruction inst)
jit->js.fifoBytesThisBlock += accessSize >> 3;
}
else if (Memory::IsRAMAddress(imm_addr))
else if (PowerPC::IsOptimizableRAMAddress(imm_addr))
{
EmitBackpatchRoutine(this, flags, true, false, V0, XA);
}

View File

@ -113,14 +113,14 @@ void JitArm64AsmRoutineManager::GenerateCommon()
BRK(100);
const u8* loadPairedFloatTwo = GetCodePtr();
{
MOVK(addr_reg, ((u64)Memory::base >> 32) & 0xFFFF, SHIFT_32);
MOVK(addr_reg, ((u64)Memory::logical_base >> 32) & 0xFFFF, SHIFT_32);
float_emit.LD1(32, 1, D0, addr_reg);
float_emit.REV32(8, D0, D0);
RET(X30);
}
const u8* loadPairedU8Two = GetCodePtr();
{
MOVK(addr_reg, ((u64)Memory::base >> 32) & 0xFFFF, SHIFT_32);
MOVK(addr_reg, ((u64)Memory::logical_base >> 32) & 0xFFFF, SHIFT_32);
float_emit.LDR(16, INDEX_UNSIGNED, D0, addr_reg, 0);
float_emit.UXTL(8, D0, D0);
float_emit.UXTL(16, D0, D0);
@ -134,7 +134,7 @@ void JitArm64AsmRoutineManager::GenerateCommon()
}
const u8* loadPairedS8Two = GetCodePtr();
{
MOVK(addr_reg, ((u64)Memory::base >> 32) & 0xFFFF, SHIFT_32);
MOVK(addr_reg, ((u64)Memory::logical_base >> 32) & 0xFFFF, SHIFT_32);
float_emit.LDR(16, INDEX_UNSIGNED, D0, addr_reg, 0);
float_emit.SXTL(8, D0, D0);
float_emit.SXTL(16, D0, D0);
@ -148,7 +148,7 @@ void JitArm64AsmRoutineManager::GenerateCommon()
}
const u8* loadPairedU16Two = GetCodePtr();
{
MOVK(addr_reg, ((u64)Memory::base >> 32) & 0xFFFF, SHIFT_32);
MOVK(addr_reg, ((u64)Memory::logical_base >> 32) & 0xFFFF, SHIFT_32);
float_emit.LD1(16, 1, D0, addr_reg);
float_emit.REV16(8, D0, D0);
float_emit.UXTL(16, D0, D0);
@ -162,7 +162,7 @@ void JitArm64AsmRoutineManager::GenerateCommon()
}
const u8* loadPairedS16Two = GetCodePtr();
{
MOVK(addr_reg, ((u64)Memory::base >> 32) & 0xFFFF, SHIFT_32);
MOVK(addr_reg, ((u64)Memory::logical_base >> 32) & 0xFFFF, SHIFT_32);
float_emit.LD1(16, 1, D0, addr_reg);
float_emit.REV16(8, D0, D0);
float_emit.SXTL(16, D0, D0);
@ -177,14 +177,14 @@ void JitArm64AsmRoutineManager::GenerateCommon()
const u8* loadPairedFloatOne = GetCodePtr();
{
MOVK(addr_reg, ((u64)Memory::base >> 32) & 0xFFFF, SHIFT_32);
MOVK(addr_reg, ((u64)Memory::logical_base >> 32) & 0xFFFF, SHIFT_32);
float_emit.LDR(32, INDEX_UNSIGNED, D0, addr_reg, 0);
float_emit.REV32(8, D0, D0);
RET(X30);
}
const u8* loadPairedU8One = GetCodePtr();
{
MOVK(addr_reg, ((u64)Memory::base >> 32) & 0xFFFF, SHIFT_32);
MOVK(addr_reg, ((u64)Memory::logical_base >> 32) & 0xFFFF, SHIFT_32);
float_emit.LDR(8, INDEX_UNSIGNED, D0, addr_reg, 0);
float_emit.UXTL(8, D0, D0);
float_emit.UXTL(16, D0, D0);
@ -198,7 +198,7 @@ void JitArm64AsmRoutineManager::GenerateCommon()
}
const u8* loadPairedS8One = GetCodePtr();
{
MOVK(addr_reg, ((u64)Memory::base >> 32) & 0xFFFF, SHIFT_32);
MOVK(addr_reg, ((u64)Memory::logical_base >> 32) & 0xFFFF, SHIFT_32);
float_emit.LDR(8, INDEX_UNSIGNED, D0, addr_reg, 0);
float_emit.SXTL(8, D0, D0);
float_emit.SXTL(16, D0, D0);
@ -212,7 +212,7 @@ void JitArm64AsmRoutineManager::GenerateCommon()
}
const u8* loadPairedU16One = GetCodePtr();
{
MOVK(addr_reg, ((u64)Memory::base >> 32) & 0xFFFF, SHIFT_32);
MOVK(addr_reg, ((u64)Memory::logical_base >> 32) & 0xFFFF, SHIFT_32);
float_emit.LDR(16, INDEX_UNSIGNED, D0, addr_reg, 0);
float_emit.REV16(8, D0, D0);
float_emit.UXTL(16, D0, D0);
@ -226,7 +226,7 @@ void JitArm64AsmRoutineManager::GenerateCommon()
}
const u8* loadPairedS16One = GetCodePtr();
{
MOVK(addr_reg, ((u64)Memory::base >> 32) & 0xFFFF, SHIFT_32);
MOVK(addr_reg, ((u64)Memory::logical_base >> 32) & 0xFFFF, SHIFT_32);
float_emit.LDR(16, INDEX_UNSIGNED, D0, addr_reg, 0);
float_emit.REV16(8, D0, D0);
float_emit.SXTL(16, D0, D0);
@ -272,7 +272,7 @@ void JitArm64AsmRoutineManager::GenerateCommon()
FixupBranch argh = B(CC_NEQ);
float_emit.REV32(8, D0, D0);
MOVK(addr_reg, ((u64)Memory::base >> 32) & 0xFFFF, SHIFT_32);
MOVK(addr_reg, ((u64)Memory::logical_base >> 32) & 0xFFFF, SHIFT_32);
float_emit.ST1(64, Q0, 0, addr_reg, SP);
RET(X30);
@ -282,7 +282,7 @@ void JitArm64AsmRoutineManager::GenerateCommon()
float_emit.ABI_PushRegisters(fprs);
float_emit.UMOV(64, X0, Q0, 0);
ORR(X0, SP, X0, ArithOption(X0, ST_ROR, 32));
MOVI2R(X30, (u64)Memory::Write_U64);
MOVI2R(X30, (u64)PowerPC::Write_U64);
BLR(X30);
float_emit.ABI_PopRegisters(fprs);
ABI_PopRegisters(gprs);
@ -304,7 +304,7 @@ void JitArm64AsmRoutineManager::GenerateCommon()
TST(DecodeReg(addr_reg), 6, 1);
FixupBranch argh = B(CC_NEQ);
MOVK(addr_reg, ((u64)Memory::base >> 32) & 0xFFFF, SHIFT_32);
MOVK(addr_reg, ((u64)Memory::logical_base >> 32) & 0xFFFF, SHIFT_32);
float_emit.ST1(16, Q0, 0, addr_reg, SP);
RET(X30);
@ -313,7 +313,7 @@ void JitArm64AsmRoutineManager::GenerateCommon()
float_emit.ABI_PushRegisters(fprs);
float_emit.UMOV(16, W0, Q0, 0);
REV16(W0, W0);
MOVI2R(X30, (u64)Memory::Write_U16);
MOVI2R(X30, (u64)PowerPC::Write_U16);
BLR(X30);
float_emit.ABI_PopRegisters(fprs);
ABI_PopRegisters(gprs);
@ -335,7 +335,7 @@ void JitArm64AsmRoutineManager::GenerateCommon()
TST(DecodeReg(addr_reg), 6, 1);
FixupBranch argh = B(CC_NEQ);
MOVK(addr_reg, ((u64)Memory::base >> 32) & 0xFFFF, SHIFT_32);
MOVK(addr_reg, ((u64)Memory::logical_base >> 32) & 0xFFFF, SHIFT_32);
float_emit.ST1(16, Q0, 0, addr_reg, SP);
RET(X30);
@ -344,7 +344,7 @@ void JitArm64AsmRoutineManager::GenerateCommon()
float_emit.ABI_PushRegisters(fprs);
float_emit.UMOV(16, W0, Q0, 0);
REV16(W0, W0);
MOVI2R(X30, (u64)Memory::Write_U16);
MOVI2R(X30, (u64)PowerPC::Write_U16);
BLR(X30);
float_emit.ABI_PopRegisters(fprs);
ABI_PopRegisters(gprs);
@ -366,7 +366,7 @@ void JitArm64AsmRoutineManager::GenerateCommon()
TST(DecodeReg(addr_reg), 6, 1);
FixupBranch argh = B(CC_NEQ);
MOVK(addr_reg, ((u64)Memory::base >> 32) & 0xFFFF, SHIFT_32);
MOVK(addr_reg, ((u64)Memory::logical_base >> 32) & 0xFFFF, SHIFT_32);
float_emit.ST1(32, Q0, 0, addr_reg, SP);
RET(X30);
@ -375,7 +375,7 @@ void JitArm64AsmRoutineManager::GenerateCommon()
float_emit.ABI_PushRegisters(fprs);
float_emit.REV32(8, D0, D0);
float_emit.UMOV(32, W0, Q0, 0);
MOVI2R(X30, (u64)Memory::Write_U32);
MOVI2R(X30, (u64)PowerPC::Write_U32);
BLR(X30);
float_emit.ABI_PopRegisters(fprs);
ABI_PopRegisters(gprs);
@ -396,7 +396,7 @@ void JitArm64AsmRoutineManager::GenerateCommon()
TST(DecodeReg(addr_reg), 6, 1);
FixupBranch argh = B(CC_NEQ);
MOVK(addr_reg, ((u64)Memory::base >> 32) & 0xFFFF, SHIFT_32);
MOVK(addr_reg, ((u64)Memory::logical_base >> 32) & 0xFFFF, SHIFT_32);
float_emit.ST1(32, Q0, 0, addr_reg, SP);
RET(X30);
@ -405,7 +405,7 @@ void JitArm64AsmRoutineManager::GenerateCommon()
float_emit.ABI_PushRegisters(fprs);
float_emit.REV32(8, D0, D0);
float_emit.UMOV(32, W0, Q0, 0);
MOVI2R(X30, (u64)Memory::Write_U32);
MOVI2R(X30, (u64)PowerPC::Write_U32);
BLR(X30);
float_emit.ABI_PopRegisters(fprs);
ABI_PopRegisters(gprs);
@ -421,7 +421,7 @@ void JitArm64AsmRoutineManager::GenerateCommon()
FixupBranch argh = B(CC_NEQ);
float_emit.REV32(8, D0, D0);
MOVK(addr_reg, ((u64)Memory::base >> 32) & 0xFFFF, SHIFT_32);
MOVK(addr_reg, ((u64)Memory::logical_base >> 32) & 0xFFFF, SHIFT_32);
float_emit.STR(32, INDEX_UNSIGNED, D0, addr_reg, 0);
RET(X30);
@ -430,7 +430,7 @@ void JitArm64AsmRoutineManager::GenerateCommon()
ABI_PushRegisters(gprs);
float_emit.ABI_PushRegisters(fprs);
float_emit.UMOV(32, W0, Q0, 0);
MOVI2R(X30, (u64)&Memory::Write_U32);
MOVI2R(X30, (u64)&PowerPC::Write_U32);
BLR(X30);
float_emit.ABI_PopRegisters(fprs);
ABI_PopRegisters(gprs);
@ -451,7 +451,7 @@ void JitArm64AsmRoutineManager::GenerateCommon()
TST(DecodeReg(addr_reg), 6, 1);
FixupBranch argh = B(CC_NEQ);
MOVK(addr_reg, ((u64)Memory::base >> 32) & 0xFFFF, SHIFT_32);
MOVK(addr_reg, ((u64)Memory::logical_base >> 32) & 0xFFFF, SHIFT_32);
float_emit.ST1(8, Q0, 0, addr_reg);
RET(X30);
@ -459,7 +459,7 @@ void JitArm64AsmRoutineManager::GenerateCommon()
ABI_PushRegisters(gprs);
float_emit.ABI_PushRegisters(fprs);
float_emit.UMOV(32, W0, Q0, 0);
MOVI2R(X30, (u64)&Memory::Write_U8);
MOVI2R(X30, (u64)&PowerPC::Write_U8);
BLR(X30);
float_emit.ABI_PopRegisters(fprs);
ABI_PopRegisters(gprs);
@ -480,7 +480,7 @@ void JitArm64AsmRoutineManager::GenerateCommon()
TST(DecodeReg(addr_reg), 6, 1);
FixupBranch argh = B(CC_NEQ);
MOVK(addr_reg, ((u64)Memory::base >> 32) & 0xFFFF, SHIFT_32);
MOVK(addr_reg, ((u64)Memory::logical_base >> 32) & 0xFFFF, SHIFT_32);
float_emit.ST1(8, Q0, 0, addr_reg);
RET(X30);
@ -488,7 +488,7 @@ void JitArm64AsmRoutineManager::GenerateCommon()
ABI_PushRegisters(gprs);
float_emit.ABI_PushRegisters(fprs);
float_emit.SMOV(32, W0, Q0, 0);
MOVI2R(X30, (u64)&Memory::Write_U8);
MOVI2R(X30, (u64)&PowerPC::Write_U8);
BLR(X30);
float_emit.ABI_PopRegisters(fprs);
ABI_PopRegisters(gprs);
@ -508,7 +508,7 @@ void JitArm64AsmRoutineManager::GenerateCommon()
TST(DecodeReg(addr_reg), 6, 1);
FixupBranch argh = B(CC_NEQ);
MOVK(addr_reg, ((u64)Memory::base >> 32) & 0xFFFF, SHIFT_32);
MOVK(addr_reg, ((u64)Memory::logical_base >> 32) & 0xFFFF, SHIFT_32);
float_emit.REV16(8, D0, D0);
float_emit.ST1(16, Q0, 0, addr_reg);
RET(X30);
@ -517,7 +517,7 @@ void JitArm64AsmRoutineManager::GenerateCommon()
ABI_PushRegisters(gprs);
float_emit.ABI_PushRegisters(fprs);
float_emit.UMOV(32, W0, Q0, 0);
MOVI2R(X30, (u64)&Memory::Write_U16);
MOVI2R(X30, (u64)&PowerPC::Write_U16);
BLR(X30);
float_emit.ABI_PopRegisters(fprs);
ABI_PopRegisters(gprs);
@ -537,7 +537,7 @@ void JitArm64AsmRoutineManager::GenerateCommon()
TST(DecodeReg(addr_reg), 6, 1);
FixupBranch argh = B(CC_NEQ);
MOVK(addr_reg, ((u64)Memory::base >> 32) & 0xFFFF, SHIFT_32);
MOVK(addr_reg, ((u64)Memory::logical_base >> 32) & 0xFFFF, SHIFT_32);
float_emit.REV16(8, D0, D0);
float_emit.ST1(16, Q0, 0, addr_reg);
RET(X30);
@ -546,7 +546,7 @@ void JitArm64AsmRoutineManager::GenerateCommon()
ABI_PushRegisters(gprs);
float_emit.ABI_PushRegisters(fprs);
float_emit.SMOV(32, W0, Q0, 0);
MOVI2R(X30, (u64)&Memory::Write_U16);
MOVI2R(X30, (u64)&PowerPC::Write_U16);
BLR(X30);
float_emit.ABI_PopRegisters(fprs);
ABI_PopRegisters(gprs);

View File

@ -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;
}

View File

@ -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)

View File

@ -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;
}

View File

@ -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.

View File

@ -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.

View File

@ -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;
}

View File

@ -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();

View File

@ -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

View File

@ -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,176 +649,156 @@ 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);
if (inst.hex != 0)
auto result = PowerPC::TryReadInstruction(address);
if (!result.valid)
{
// Slight hack: the JIT block cache currently assumes all blocks end at the same place,
// 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)
{
break;
}
num_inst++;
memset(&code[i], 0, sizeof(CodeOp));
GekkoOPInfo *opinfo = GetOpInfo(inst);
if (!opinfo)
{
PanicAlert("Invalid PowerPC opcode: %x.", inst.hex);
Crash();
}
code[i].opinfo = opinfo;
code[i].address = address;
code[i].inst = inst;
code[i].branchTo = -1;
code[i].branchToIndex = -1;
code[i].skip = false;
block->m_stats->numCycles += opinfo->numCycles;
SetInstructionStats(block, &code[i], opinfo, i);
bool follow = false;
u32 destination = 0;
bool conditional_continue = false;
// Do we inline leaf functions?
if (HasOption(OPTION_LEAF_INLINE))
{
if (inst.OPCD == 18 && blockSize > 1)
{
//Is bx - should we inline? yes!
if (inst.AA)
destination = SignExt26(inst.LI << 2);
else
destination = address + SignExt26(inst.LI << 2);
if (destination != block->m_address)
follow = true;
}
else if (inst.OPCD == 19 && inst.SUBOP10 == 16 &&
(inst.BO & (1 << 4)) && (inst.BO & (1 << 2)) &&
return_address != 0)
{
// bclrx with unconditional branch = return
follow = true;
destination = return_address;
return_address = 0;
if (inst.LK)
return_address = address + 4;
}
else if (inst.OPCD == 31 && inst.SUBOP10 == 467)
{
// mtspr
const u32 index = (inst.SPRU << 5) | (inst.SPRL & 0x1F);
if (index == SPR_LR)
{
// We give up to follow the return address
// because we have to check the register usage.
return_address = 0;
}
}
// TODO: Find the optimal value for FUNCTION_FOLLOWING_THRESHOLD.
// If it is small, the performance will be down.
// If it is big, the size of generated code will be big and
// cache clearning will happen many times.
// TODO: Investivate the reason why
// "0" is fastest in some games, MP2 for example.
if (numFollows > FUNCTION_FOLLOWING_THRESHOLD)
follow = false;
}
if (HasOption(OPTION_CONDITIONAL_CONTINUE))
{
if (inst.OPCD == 16 &&
((inst.BO & BO_DONT_DECREMENT_FLAG) == 0 || (inst.BO & BO_DONT_CHECK_CONDITION) == 0))
{
// bcx with conditional branch
conditional_continue = true;
}
else if (inst.OPCD == 19 && inst.SUBOP10 == 16 &&
((inst.BO & BO_DONT_DECREMENT_FLAG) == 0 || (inst.BO & BO_DONT_CHECK_CONDITION) == 0))
{
// bclrx with conditional branch
conditional_continue = true;
}
else if (inst.OPCD == 3 ||
(inst.OPCD == 31 && inst.SUBOP10 == 4))
{
// tw/twi tests and raises an exception
conditional_continue = true;
}
else if (inst.OPCD == 19 && inst.SUBOP10 == 528 &&
(inst.BO_2 & BO_DONT_CHECK_CONDITION) == 0)
{
// Rare bcctrx with conditional branch
// Seen in NES games
conditional_continue = true;
}
}
if (!follow)
{
address += 4;
if (!conditional_continue && opinfo->flags & FL_ENDBLOCK) //right now we stop early
{
found_exit = true;
break;
}
}
// XXX: We don't support inlining yet.
#if 0
else
{
numFollows++;
// We don't "code[i].skip = true" here
// because bx may store a certain value to the link register.
// Instead, we skip a part of bx in Jit**::bx().
address = destination;
merged_addresses[size_of_merged_addresses++] = address;
}
#endif
}
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!");
if (i == 0)
block->m_memory_exception = true;
break;
}
UGeckoInstruction inst = result.hex;
// Slight hack: the JIT block cache currently assumes all blocks end at the same place,
// 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 ((!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));
GekkoOPInfo *opinfo = GetOpInfo(inst);
if (!opinfo)
{
PanicAlert("Invalid PowerPC opcode: %x.", inst.hex);
Crash();
}
code[i].opinfo = opinfo;
code[i].address = address;
code[i].inst = inst;
code[i].branchTo = -1;
code[i].branchToIndex = -1;
code[i].skip = false;
block->m_stats->numCycles += opinfo->numCycles;
SetInstructionStats(block, &code[i], opinfo, i);
bool follow = false;
u32 destination = 0;
bool conditional_continue = false;
// Do we inline leaf functions?
if (HasOption(OPTION_LEAF_INLINE))
{
if (inst.OPCD == 18 && blockSize > 1)
{
//Is bx - should we inline? yes!
if (inst.AA)
destination = SignExt26(inst.LI << 2);
else
destination = address + SignExt26(inst.LI << 2);
if (destination != block->m_address)
follow = true;
}
else if (inst.OPCD == 19 && inst.SUBOP10 == 16 &&
(inst.BO & (1 << 4)) && (inst.BO & (1 << 2)) &&
return_address != 0)
{
// bclrx with unconditional branch = return
follow = true;
destination = return_address;
return_address = 0;
if (inst.LK)
return_address = address + 4;
}
else if (inst.OPCD == 31 && inst.SUBOP10 == 467)
{
// mtspr
const u32 index = (inst.SPRU << 5) | (inst.SPRL & 0x1F);
if (index == SPR_LR)
{
// We give up to follow the return address
// because we have to check the register usage.
return_address = 0;
}
}
// TODO: Find the optimal value for FUNCTION_FOLLOWING_THRESHOLD.
// If it is small, the performance will be down.
// If it is big, the size of generated code will be big and
// cache clearning will happen many times.
// TODO: Investivate the reason why
// "0" is fastest in some games, MP2 for example.
if (numFollows > FUNCTION_FOLLOWING_THRESHOLD)
follow = false;
}
if (HasOption(OPTION_CONDITIONAL_CONTINUE))
{
if (inst.OPCD == 16 &&
((inst.BO & BO_DONT_DECREMENT_FLAG) == 0 || (inst.BO & BO_DONT_CHECK_CONDITION) == 0))
{
// bcx with conditional branch
conditional_continue = true;
}
else if (inst.OPCD == 19 && inst.SUBOP10 == 16 &&
((inst.BO & BO_DONT_DECREMENT_FLAG) == 0 || (inst.BO & BO_DONT_CHECK_CONDITION) == 0))
{
// bclrx with conditional branch
conditional_continue = true;
}
else if (inst.OPCD == 3 ||
(inst.OPCD == 31 && inst.SUBOP10 == 4))
{
// tw/twi tests and raises an exception
conditional_continue = true;
}
else if (inst.OPCD == 19 && inst.SUBOP10 == 528 &&
(inst.BO_2 & BO_DONT_CHECK_CONDITION) == 0)
{
// Rare bcctrx with conditional branch
// Seen in NES games
conditional_continue = true;
}
}
if (!follow)
{
address += 4;
if (!conditional_continue && opinfo->flags & FL_ENDBLOCK) //right now we stop early
{
found_exit = true;
break;
}
}
// XXX: We don't support inlining yet.
#if 0
else
{
numFollows++;
// We don't "code[i].skip = true" here
// because bx may store a certain value to the link register.
// Instead, we skip a part of bx in Jit**::bx().
address = destination;
merged_addresses[size_of_merged_addresses++] = address;
}
#endif
}
block->m_num_instructions = num_inst;

View File

@ -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]];

View File

@ -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;
}

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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())

View File

@ -181,7 +181,7 @@ void CMemoryWindow::SetMemoryValue(wxCommandEvent& event)
return;
}
Memory::Write_U32(val, addr);
PowerPC::HostWrite_U32(val, addr);
memview->Refresh();
}

View File

@ -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;
}