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 "Utilities/Log.h"
#include "Emu/Memory/Memory.h" #include "Emu/Memory/Memory.h"
#include "Emu/System.h" #include "Emu/System.h"
#include "Emu/RSX/GSManager.h"
#include "RSXThread.h" #include "RSXThread.h"
#include "Emu/SysCalls/Callback.h" #include "Emu/SysCalls/Callback.h"
@ -45,15 +46,40 @@ void RSXThread::nativeRescale(float width, float height)
u32 GetAddress(u32 offset, u32 location) u32 GetAddress(u32 offset, u32 location)
{ {
u32 res = 0;
switch(location) switch(location)
{ {
case CELL_GCM_LOCATION_LOCAL: return (u32)Memory.RSXFBMem.GetStartAddr() + offset; case CELL_GCM_LOCATION_LOCAL:
case CELL_GCM_LOCATION_MAIN: return (u32)Memory.RSXIOMem.RealAddr(offset); // TODO: Error Check? {
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;
}
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;
}
} }
LOG_ERROR(RSX, "GetAddress(offset=0x%x, location=0x%x)", location); return res;
assert(0);
return 0;
} }
RSXVertexData::RSXVertexData() RSXVertexData::RSXVertexData()

View File

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

View File

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

View File

@ -12,8 +12,8 @@ enum
struct CellGcmOffsetTable struct CellGcmOffsetTable
{ {
be_t<u32> ioAddress; // u16* vm::bptr<u16> ioAddress;
be_t<u32> eaAddress; // u16* vm::bptr<u16> eaAddress;
}; };
// Auxiliary functions // 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) 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); ppu_thread_exit(CPU, errorcode);
} }