Skip to content

Commit

Permalink
Fix the addresses of MMIO registers.
Browse files Browse the repository at this point in the history
MMIO registers are located at 0x0C000000 and 0x0D000000, not 0xCC000000.
The 0xCC000000 addresses are just an artifact of address translation.
  • Loading branch information
magumagu committed Feb 16, 2015
1 parent 5b6a947 commit f316265
Show file tree
Hide file tree
Showing 8 changed files with 199 additions and 160 deletions.
20 changes: 10 additions & 10 deletions Source/Core/Core/HW/MMIO.h
Expand Up @@ -16,9 +16,9 @@ namespace MMIO
{

// There are three main MMIO blocks on the Wii (only one on the GameCube):
// - 0xCC00xxxx: GameCube MMIOs (CP, PE, VI, PI, MI, DSP, DVD, SI, EI, AI, GP)
// - 0xCD00xxxx: Wii MMIOs and GC mirrors (IPC, DVD, SI, EI, AI)
// - 0xCD80xxxx: Mirror of 0xCD00xxxx.
// - 0x0C00xxxx: GameCube MMIOs (CP, PE, VI, PI, MI, DSP, DVD, SI, EI, AI, GP)
// - 0x0D00xxxx: Wii MMIOs and GC mirrors (IPC, DVD, SI, EI, AI)
// - 0x0D80xxxx: Mirror of 0x0D00xxxx.
//
// In practice, since the third block is a mirror of the second one, we can
// assume internally that there are only two blocks: one for GC, one for Wii.
Expand All @@ -41,15 +41,15 @@ const u32 NUM_MMIOS = NUM_BLOCKS * BLOCK_SIZE;
// interface.
inline bool IsMMIOAddress(u32 address)
{
if (address == 0xCC008000)
if (address == 0x0C008000)
return false; // WG Pipe
if ((address & 0xFFFF0000) == 0xCC000000)
if ((address & 0xFFFF0000) == 0x0C000000)
return true; // GameCube MMIOs

if(SConfig::GetInstance().m_LocalCoreStartupParameter.bWii)
{
return ((address & 0xFFFF0000) == 0xCD000000) || // Wii MMIOs
((address & 0xFFFF0000) == 0xCD800000); // Mirror of Wii MMIOs
return ((address & 0xFFFF0000) == 0x0D000000) || // Wii MMIOs
((address & 0xFFFF0000) == 0x0D800000); // Mirror of Wii MMIOs
}

return false;
Expand All @@ -61,9 +61,9 @@ inline bool IsMMIOAddress(u32 address)
// The block ID can easily be computed by simply checking bit 24 (CC vs. CD).
inline u32 UniqueID(u32 address)
{
_dbg_assert_msg_(MEMMAP, ((address & 0xFFFF0000) == 0xCC000000) ||
((address & 0xFFFF0000) == 0xCD000000) ||
((address & 0xFFFF0000) == 0xCD800000),
_dbg_assert_msg_(MEMMAP, ((address & 0xFFFF0000) == 0x0C000000) ||
((address & 0xFFFF0000) == 0x0D000000) ||
((address & 0xFFFF0000) == 0x0D800000),
"Trying to get the ID of a non-existing MMIO address.");

return (((address >> 24) & 1) << 16) | (address & 0xFFFF);
Expand Down
30 changes: 15 additions & 15 deletions Source/Core/Core/HW/Memmap.cpp
Expand Up @@ -74,27 +74,27 @@ MMIO::Mapping* mmio_mapping;

static void InitMMIO(MMIO::Mapping* mmio)
{
g_video_backend->RegisterCPMMIO(mmio, 0xCC000000);
PixelEngine::RegisterMMIO(mmio, 0xCC001000);
VideoInterface::RegisterMMIO(mmio, 0xCC002000);
ProcessorInterface::RegisterMMIO(mmio, 0xCC003000);
MemoryInterface::RegisterMMIO(mmio, 0xCC004000);
DSP::RegisterMMIO(mmio, 0xCC005000);
DVDInterface::RegisterMMIO(mmio, 0xCC006000);
SerialInterface::RegisterMMIO(mmio, 0xCC006400);
ExpansionInterface::RegisterMMIO(mmio, 0xCC006800);
AudioInterface::RegisterMMIO(mmio, 0xCC006C00);
g_video_backend->RegisterCPMMIO(mmio, 0x0C000000);
PixelEngine::RegisterMMIO(mmio, 0x0C001000);
VideoInterface::RegisterMMIO(mmio, 0x0C002000);
ProcessorInterface::RegisterMMIO(mmio, 0x0C003000);
MemoryInterface::RegisterMMIO(mmio, 0x0C004000);
DSP::RegisterMMIO(mmio, 0x0C005000);
DVDInterface::RegisterMMIO(mmio, 0x0C006000);
SerialInterface::RegisterMMIO(mmio, 0x0C006400);
ExpansionInterface::RegisterMMIO(mmio, 0x0C006800);
AudioInterface::RegisterMMIO(mmio, 0x0C006C00);
}

static void InitMMIOWii(MMIO::Mapping* mmio)
{
InitMMIO(mmio);

WII_IPCInterface::RegisterMMIO(mmio, 0xCD000000);
DVDInterface::RegisterMMIO(mmio, 0xCD006000);
SerialInterface::RegisterMMIO(mmio, 0xCD006400);
ExpansionInterface::RegisterMMIO(mmio, 0xCD006800);
AudioInterface::RegisterMMIO(mmio, 0xCD006C00);
WII_IPCInterface::RegisterMMIO(mmio, 0x0D000000);
DVDInterface::RegisterMMIO(mmio, 0x0D006000);
SerialInterface::RegisterMMIO(mmio, 0x0D006400);
ExpansionInterface::RegisterMMIO(mmio, 0x0D006800);
AudioInterface::RegisterMMIO(mmio, 0x0D006C00);
}

bool IsInitialized()
Expand Down
19 changes: 14 additions & 5 deletions Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStore.cpp
Expand Up @@ -147,15 +147,20 @@ void JitArm64::SafeLoadToReg(u32 dest, s32 addr, s32 offsetReg, u32 flags, s32 o
if (update)
MOV(gpr.R(addr), addr_reg);

u32 access_size = BackPatchInfo::GetFlagSize(flags);
u32 mmio_address = 0;
if (is_immediate)
mmio_address = PowerPC::IsOptimizableMMIOAccess(imm_addr, access_size);

if (is_immediate && PowerPC::IsOptimizableRAMAddress(imm_addr))
{
EmitBackpatchRoutine(this, flags, true, false, dest_reg, XA);
}
else if (is_immediate && MMIO::IsMMIOAddress(imm_addr))
else if (mmio_address)
{
MMIOLoadToReg(Memory::mmio_mapping, this,
regs_in_use, fprs_in_use, dest_reg,
imm_addr, flags);
mmio_address, flags);
}
else
{
Expand Down Expand Up @@ -288,18 +293,22 @@ void JitArm64::SafeStoreFromReg(s32 dest, u32 value, s32 regOffset, u32 flags, s

ARM64Reg XA = EncodeRegTo64(addr_reg);

u32 access_size = BackPatchInfo::GetFlagSize(flags);
u32 mmio_address = 0;
if (is_immediate)
mmio_address = PowerPC::IsOptimizableMMIOAccess(imm_addr, access_size);

if (is_immediate && PowerPC::IsOptimizableRAMAddress(imm_addr))
{
MOVI2R(XA, imm_addr);

EmitBackpatchRoutine(this, flags, true, false, RS, XA);
}
else if (is_immediate && MMIO::IsMMIOAddress(imm_addr) &&
!(flags & BackPatchInfo::FLAG_REVERSE))
else if (mmio_address && !(flags & BackPatchInfo::FLAG_REVERSE))
{
MMIOWriteRegToAddr(Memory::mmio_mapping, this,
regs_in_use, fprs_in_use, RS,
imm_addr, flags);
mmio_address, flags);
}
else
{
Expand Down
15 changes: 15 additions & 0 deletions Source/Core/Core/PowerPC/JitArmCommon/BackPatch.h
Expand Up @@ -20,6 +20,21 @@ struct BackPatchInfo
FLAG_EXTEND = (1 << 8),
};

static u32 GetFlagSize(u32 flags)
{
if (flags & FLAG_SIZE_8)
return 8;
if (flags & FLAG_SIZE_16)
return 16;
if (flags & FLAG_SIZE_32)
return 32;
if (flags & FLAG_SIZE_F32)
return 32;
if (flags & FLAG_SIZE_F64)
return 64;
return 0;
}

u32 m_fastmem_size;
u32 m_fastmem_trouble_inst_offset;
u32 m_slowmem_size;
Expand Down
193 changes: 94 additions & 99 deletions Source/Core/Core/PowerPC/JitCommon/Jit_Util.cpp
Expand Up @@ -289,116 +289,111 @@ void EmuCodeBlock::SafeLoadToReg(X64Reg reg_value, const Gen::OpArg & opAddress,

registersInUseAtLoc[mov] = registersInUse;
jit->js.fastmemLoadStore = mov;
return;
}
else

u32 mem_mask = Memory::ADDR_MASK_HW_ACCESS;

// The following masks the region used by the GC/Wii virtual memory lib
mem_mask |= Memory::ADDR_MASK_MEM1;

if (opAddress.IsImm())
{
u32 mem_mask = Memory::ADDR_MASK_HW_ACCESS;
u32 address = (u32)opAddress.offset + offset;

// The following masks the region used by the GC/Wii virtual memory lib
mem_mask |= Memory::ADDR_MASK_MEM1;
// If the address is known to be RAM, just load it directly.
if (PowerPC::IsOptimizableRAMAddress(address))
{
UnsafeLoadToReg(reg_value, opAddress, accessSize, offset, signExtend);
return;
}

if (opAddress.IsImm())
// If the address maps to an MMIO register, inline MMIO read code.
u32 mmioAddress = PowerPC::IsOptimizableMMIOAccess(address, accessSize);
if (accessSize != 64 && mmioAddress)
{
u32 address = (u32)opAddress.offset + offset;

// If we know the address, try the following loading methods in
// order:
//
// 1. If the address is in RAM, generate an unsafe load (directly
// 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 PowerPC::Read_* with the
// address hardcoded.
if (PowerPC::IsOptimizableRAMAddress(address))
{
UnsafeLoadToReg(reg_value, opAddress, accessSize, offset, signExtend);
}
else if (MMIO::IsMMIOAddress(address) && accessSize != 64)
{
MMIOLoadToReg(Memory::mmio_mapping, reg_value, registersInUse,
address, accessSize, signExtend);
}
else
{
ABI_PushRegistersAndAdjustStack(registersInUse, 0);
switch (accessSize)
{
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);

MemoryExceptionCheck();
if (signExtend && accessSize < 32)
{
// Need to sign extend values coming from the Read_U* functions.
MOVSX(32, accessSize, reg_value, R(ABI_RETURN));
}
else if (reg_value != ABI_RETURN)
{
MOVZX(64, accessSize, reg_value, R(ABI_RETURN));
}
}
MMIOLoadToReg(Memory::mmio_mapping, reg_value, registersInUse,
address, accessSize, signExtend);
return;
}
else

// Fall back to general-case code.
ABI_PushRegistersAndAdjustStack(registersInUse, 0);
switch (accessSize)
{
_assert_msg_(DYNA_REC, opAddress.IsSimpleReg(), "Incorrect use of SafeLoadToReg (address isn't register or immediate)");
X64Reg reg_addr = opAddress.GetSimpleReg();
if (offset)
{
reg_addr = RSCRATCH;
LEA(32, RSCRATCH, MDisp(opAddress.GetSimpleReg(), offset));
}
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);

FixupBranch slow, exit;
slow = CheckIfSafeAddress(R(reg_value), reg_addr, registersInUse, mem_mask);
UnsafeLoadToReg(reg_value, R(reg_addr), accessSize, 0, signExtend);
if (farcode.Enabled())
SwitchToFarCode();
else
exit = J(true);
SetJumpTarget(slow);
size_t rsp_alignment = (flags & SAFE_LOADSTORE_NO_PROLOG) ? 8 : 0;
ABI_PushRegistersAndAdjustStack(registersInUse, rsp_alignment);
switch (accessSize)
{
case 64:
ABI_CallFunctionR((void *)&PowerPC::Read_U64, reg_addr);
break;
case 32:
ABI_CallFunctionR((void *)&PowerPC::Read_U32, reg_addr);
break;
case 16:
ABI_CallFunctionR((void *)&PowerPC::Read_U16_ZX, reg_addr);
break;
case 8:
ABI_CallFunctionR((void *)&PowerPC::Read_U8_ZX, reg_addr);
break;
}
ABI_PopRegistersAndAdjustStack(registersInUse, rsp_alignment);
MemoryExceptionCheck();
if (signExtend && accessSize < 32)
{
// Need to sign extend values coming from the Read_U* functions.
MOVSX(32, accessSize, reg_value, R(ABI_RETURN));
}
else if (reg_value != ABI_RETURN)
{
MOVZX(64, accessSize, reg_value, R(ABI_RETURN));
}

MemoryExceptionCheck();
if (signExtend && accessSize < 32)
{
// Need to sign extend values coming from the Read_U* functions.
MOVSX(32, accessSize, reg_value, R(ABI_RETURN));
}
else if (reg_value != ABI_RETURN)
{
MOVZX(64, accessSize, reg_value, R(ABI_RETURN));
}
return;
}

if (farcode.Enabled())
{
exit = J(true);
SwitchToNearCode();
}
SetJumpTarget(exit);
}
_assert_msg_(DYNA_REC, opAddress.IsSimpleReg(), "Incorrect use of SafeLoadToReg (address isn't register or immediate)");
X64Reg reg_addr = opAddress.GetSimpleReg();
if (offset)
{
reg_addr = RSCRATCH;
LEA(32, RSCRATCH, MDisp(opAddress.GetSimpleReg(), offset));
}

FixupBranch slow, exit;
slow = CheckIfSafeAddress(R(reg_value), reg_addr, registersInUse, mem_mask);
UnsafeLoadToReg(reg_value, R(reg_addr), accessSize, 0, signExtend);
if (farcode.Enabled())
SwitchToFarCode();
else
exit = J(true);
SetJumpTarget(slow);
size_t rsp_alignment = (flags & SAFE_LOADSTORE_NO_PROLOG) ? 8 : 0;
ABI_PushRegistersAndAdjustStack(registersInUse, rsp_alignment);
switch (accessSize)
{
case 64:
ABI_CallFunctionR((void *)&PowerPC::Read_U64, reg_addr);
break;
case 32:
ABI_CallFunctionR((void *)&PowerPC::Read_U32, reg_addr);
break;
case 16:
ABI_CallFunctionR((void *)&PowerPC::Read_U16_ZX, reg_addr);
break;
case 8:
ABI_CallFunctionR((void *)&PowerPC::Read_U8_ZX, reg_addr);
break;
}
ABI_PopRegistersAndAdjustStack(registersInUse, rsp_alignment);

MemoryExceptionCheck();
if (signExtend && accessSize < 32)
{
// Need to sign extend values coming from the Read_U* functions.
MOVSX(32, accessSize, reg_value, R(ABI_RETURN));
}
else if (reg_value != ABI_RETURN)
{
MOVZX(64, accessSize, reg_value, R(ABI_RETURN));
}

if (farcode.Enabled())
{
exit = J(true);
SwitchToNearCode();
}
SetJumpTarget(exit);
}

static OpArg SwapImmediate(int accessSize, OpArg reg_value)
Expand Down

0 comments on commit f316265

Please sign in to comment.