RSXIO memory mapping with strict ordering (draft)

This commit is contained in:
Nekotekina 2014-10-10 01:26:04 +04:00
parent 266c3d4753
commit 1dac13be16
5 changed files with 66 additions and 29 deletions

View File

@ -3,6 +3,7 @@
#include "Utilities/Log.h"
#include "Emu/Memory/Memory.h"
#include "Emu/System.h"
#include "Emu/RSX/GSManager.h"
#include "RSXThread.h"
#include "Emu/SysCalls/Callback.h"
@ -45,15 +46,40 @@ void RSXThread::nativeRescale(float width, float height)
u32 GetAddress(u32 offset, u32 location)
{
u32 res = 0;
switch(location)
{
case CELL_GCM_LOCATION_LOCAL: return (u32)Memory.RSXFBMem.GetStartAddr() + offset;
case CELL_GCM_LOCATION_MAIN: return (u32)Memory.RSXIOMem.RealAddr(offset); // TODO: Error Check?
case CELL_GCM_LOCATION_LOCAL:
{
res = (u32)Memory.RSXFBMem.GetStartAddr() + offset;
break;
}
case CELL_GCM_LOCATION_MAIN:
{
res = (u32)Memory.RSXIOMem.RealAddr(offset); // TODO: Error Check?
if (res == 0)
{
LOG_ERROR(RSX, "GetAddress(offset=0x%x): RSXIO memory not mapped", offset);
Emu.Pause();
break;
}
LOG_ERROR(RSX, "GetAddress(offset=0x%x, location=0x%x)", location);
assert(0);
return 0;
if (Emu.GetGSManager().GetRender().m_strict_ordering[offset >> 20])
{
_mm_mfence(); // probably doesn't have any effect on current implementation
}
break;
}
default:
{
LOG_ERROR(RSX, "GetAddress(offset=0x%x, location=0x%x): invalid location", offset, location);
Emu.Pause();
break;
}
}
return res;
}
RSXVertexData::RSXVertexData()

View File

@ -134,6 +134,7 @@ public:
u32 m_report_main_addr;
u32 m_local_mem_addr, m_main_mem_addr;
bool m_strict_ordering[0x1000];
public:
uint m_draw_mode;

View File

@ -61,11 +61,11 @@ CellGcmOffsetTable offsetTable;
void InitOffsetTable()
{
offsetTable.ioAddress = (u32)Memory.Alloc(3072 * sizeof(u16), 1);
offsetTable.eaAddress = (u32)Memory.Alloc(512 * sizeof(u16), 1);
offsetTable.ioAddress.set(be_t<u32>::make((u32)Memory.Alloc(3072 * sizeof(u16), 1)));
offsetTable.eaAddress.set(be_t<u32>::make((u32)Memory.Alloc(512 * sizeof(u16), 1)));
memset(vm::get_ptr<void>(offsetTable.ioAddress), 0xFF, 3072 * sizeof(u16));
memset(vm::get_ptr<void>(offsetTable.eaAddress), 0xFF, 512 * sizeof(u16));
memset(offsetTable.ioAddress.get_ptr(), 0xFF, 3072 * sizeof(u16));
memset(offsetTable.eaAddress.get_ptr(), 0xFF, 512 * sizeof(u16));
}
//----------------------------------------------------------------------------
@ -129,7 +129,7 @@ u32 cellGcmGetNotifyDataAddress(u32 index)
cellGcmGetOffsetTable(table);
// If entry not in use, return NULL
u16 entry = vm::read16(table->eaAddress + 241 * sizeof(u16));
u16 entry = table->eaAddress[241];
if (entry == 0xFFFF) {
return 0;
}
@ -814,7 +814,7 @@ s32 cellGcmAddressToOffset(u64 address, vm::ptr<be_t<u32>> offset)
// Address in main memory else check
else
{
u16 upper12Bits = vm::read16(offsetTable.ioAddress + sizeof(u16)*(address >> 20));
u16 upper12Bits = offsetTable.ioAddress[address >> 20];
// If the address is mapped in IO
if (upper12Bits != 0xFFFF) {
@ -858,10 +858,8 @@ s32 cellGcmIoOffsetToAddress(u32 ioOffset, u64 address)
return CELL_OK;
}
s32 cellGcmMapEaIoAddress(u32 ea, u32 io, u32 size)
s32 gcmMapEaIoAddress(u32 ea, u32 io, u32 size, bool is_strict)
{
cellGcmSys->Warning("cellGcmMapEaIoAddress(ea=0x%x, io=0x%x, size=0x%x)", ea, io, size);
if ((ea & 0xFFFFF) || (io & 0xFFFFF) || (size & 0xFFFFF)) return CELL_GCM_ERROR_FAILURE;
// Check if the mapping was successfull
@ -870,8 +868,9 @@ s32 cellGcmMapEaIoAddress(u32 ea, u32 io, u32 size)
// Fill the offset table
for (u32 i = 0; i<(size >> 20); i++)
{
vm::write16(offsetTable.ioAddress + ((ea >> 20) + i)*sizeof(u16), (io >> 20) + i);
vm::write16(offsetTable.eaAddress + ((io >> 20) + i)*sizeof(u16), (ea >> 20) + i);
offsetTable.ioAddress[(ea >> 20) + i] = (io >> 20) + i;
offsetTable.eaAddress[(io >> 20) + i] = (ea >> 20) + i;
Emu.GetGSManager().GetRender().m_strict_ordering[(io >> 20) + i] = is_strict;
}
}
else
@ -883,10 +882,20 @@ s32 cellGcmMapEaIoAddress(u32 ea, u32 io, u32 size)
return CELL_OK;
}
s32 cellGcmMapEaIoAddress(u32 ea, u32 io, u32 size)
{
cellGcmSys->Warning("cellGcmMapEaIoAddress(ea=0x%x, io=0x%x, size=0x%x)", ea, io, size);
return gcmMapEaIoAddress(ea, io, size, false);
}
s32 cellGcmMapEaIoAddressWithFlags(u32 ea, u32 io, u32 size, u32 flags)
{
cellGcmSys->Warning("cellGcmMapEaIoAddressWithFlags(ea=0x%x, io=0x%x, size=0x%x, flags=0x%x)", ea, io, size, flags);
return cellGcmMapEaIoAddress(ea, io, size); // TODO: strict ordering
assert(flags == 2 /*CELL_GCM_IOMAP_FLAG_STRICT_ORDERING*/);
return gcmMapEaIoAddress(ea, io, size, true);
}
s32 cellGcmMapLocalMemory(u64 address, u64 size)
@ -919,13 +928,14 @@ s32 cellGcmMapMainMemory(u32 ea, u32 size, vm::ptr<be_t<u32>> offset)
u32 io = Memory.RSXIOMem.Map(ea, size);
//check if the mapping was successfull
if (Memory.RSXIOMem.Write32(io, 0))
if (Memory.RSXIOMem.RealAddr(io) == ea)
{
//fill the offset table
for (u32 i = 0; i<(size >> 20); i++)
{
vm::write16(offsetTable.ioAddress + ((ea >> 20) + i) * sizeof(u16), (u16)(io >> 20) + i);
vm::write16(offsetTable.eaAddress + ((io >> 20) + i) * sizeof(u16), (u16)(ea >> 20) + i);
offsetTable.ioAddress[(ea >> 20) + i] = (u16)(io >> 20) + i;
offsetTable.eaAddress[(io >> 20) + i] = (u16)(ea >> 20) + i;
Emu.GetGSManager().GetRender().m_strict_ordering[(io >> 20) + i] = false;
}
*offset = io;
@ -970,12 +980,12 @@ s32 cellGcmUnmapEaIoAddress(u64 ea)
{
u64 io;
ea = ea >> 20;
io = vm::read16(offsetTable.ioAddress + (ea*sizeof(u16)));
io = offsetTable.ioAddress[ea];
for (u32 i = 0; i<size; i++)
{
vm::write16(offsetTable.ioAddress + ((ea + i)*sizeof(u16)), 0xFFFF);
vm::write16(offsetTable.eaAddress + ((io + i)*sizeof(u16)), 0xFFFF);
offsetTable.ioAddress[ea + i] = 0xFFFF;
offsetTable.eaAddress[io + i] = 0xFFFF;
}
}
else
@ -996,12 +1006,12 @@ s32 cellGcmUnmapIoAddress(u64 io)
{
u64 ea;
io = io >> 20;
ea = vm::read16(offsetTable.eaAddress + (io*sizeof(u16)));
ea = offsetTable.eaAddress[io];
for (u32 i = 0; i<size; i++)
{
vm::write16(offsetTable.ioAddress + ((ea + i)*sizeof(u16)), 0xFFFF);
vm::write16(offsetTable.eaAddress + ((io + i)*sizeof(u16)), 0xFFFF);
offsetTable.ioAddress[ea + i] = 0xFFFF;
offsetTable.eaAddress[io + i] = 0xFFFF;
}
}
else

View File

@ -12,8 +12,8 @@ enum
struct CellGcmOffsetTable
{
be_t<u32> ioAddress; // u16*
be_t<u32> eaAddress; // u16*
vm::bptr<u16> ioAddress;
vm::bptr<u16> eaAddress;
};
// Auxiliary functions

View File

@ -34,7 +34,7 @@ void sys_ppu_thread_exit(PPUThread& CPU, u64 errorcode)
void sys_internal_ppu_thread_exit(PPUThread& CPU, u64 errorcode)
{
sys_ppu_thread.Log("sys_internal_ppu_thread_exit(0x%llx)", errorcode);
sys_ppu_thread.Warning("sys_internal_ppu_thread_exit(0x%llx)", errorcode);
ppu_thread_exit(CPU, errorcode);
}