Skip to content

Commit

Permalink
Merge pull request #2033 from magumagu/mmio-fix-addresses
Browse files Browse the repository at this point in the history
Fix the addresses of MMIO registers.
  • Loading branch information
magumagu committed Feb 22, 2015
2 parents c54a8c5 + f316265 commit 18ada7a
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 18ada7a

Please sign in to comment.