1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-22 18:53:28 +01:00

Light hack for FSCRRD and FSCRWR

SPU_*Event* channels implemented for LR event
MFC_RdTagMask implemented
This commit is contained in:
Nekotekina 2014-08-21 02:12:56 +04:00
parent 9eb280c367
commit 126b636edf
4 changed files with 138 additions and 5 deletions

View File

@ -936,7 +936,8 @@ private:
void FSCRRD(u32 rt)
{
UNIMPLEMENTED(); // TODO (rarely used)
// TODO (rarely used)
CPU.GPR[rt].Reset();
}
void FESD(u32 rt, u32 ra)
{
@ -952,7 +953,12 @@ private:
}
void FSCRWR(u32 rt, u32 ra)
{
UNIMPLEMENTED(); // TODO (rarely used)
// TODO (rarely used)
if (CPU.GPR[ra]._u128)
{
LOG_ERROR(SPU, "FSCRWR(%d,%d): value = %s", rt, ra, CPU.GPR[ra].ToString().c_str());
UNIMPLEMENTED();
}
}
void DFTSV(u32 rt, u32 ra, s32 i7)
{

View File

@ -81,6 +81,9 @@ void SPUThread::InitRegs()
MFC1.TagStatus.SetValue(0);
MFC2.TagStatus.SetValue(0);
//PC = SPU.NPC.GetValue();
m_event_mask = 0;
m_events = 0;
}
u64 SPUThread::GetFreeStackSize() const

View File

@ -106,6 +106,24 @@ enum MFCchannels
MFC_RdAtomicStat = 27, //Read completion status of last completed immediate MFC atomic update command
};
enum SPUEvents
{
SPU_EVENT_MS = 0x1000, // multisource synchronization event
SPU_EVENT_A = 0x800, // privileged attention event
SPU_EVENT_LR = 0x400, // lock line reservation lost event
SPU_EVENT_S1 = 0x200, // signal notification register 1 available
SPU_EVENT_S2 = 0x100, // signal notification register 2 available
SPU_EVENT_LE = 0x80, // SPU outbound mailbox available
SPU_EVENT_ME = 0x40, // SPU outbound interrupt mailbox available
SPU_EVENT_TM = 0x20, // SPU decrementer became negative (?)
SPU_EVENT_MB = 0x10, // SPU inbound mailbox available
SPU_EVENT_QV = 0x4, // MFC SPU command queue available
SPU_EVENT_SN = 0x2, // MFC list command stall-and-notify event
SPU_EVENT_TG = 0x1, // MFC tag-group status update event
SPU_EVENT_IMPLEMENTED = SPU_EVENT_LR,
};
enum
{
SPU_RUNCNTL_STOP = 0,
@ -302,6 +320,9 @@ public:
u64 m_dec_start; // timestamp of writing decrementer value
u32 m_dec_value; // written decrementer value
u32 m_event_mask;
u32 m_events;
struct IntrTag
{
u32 enabled; // 1 == true
@ -855,6 +876,32 @@ public:
}
}
bool CheckEvents() // checks events
{
// SPU_EVENT_LR:
{
SMutexLockerR lock(reservation.mutex);
if (reservation.owner == lock.tid)
{
for (u32 i = 0; i < 16; i++)
{
if (*(u64*)&Memory[reservation.addr + i * 8] != reservation.data[i])
{
m_events |= SPU_EVENT_LR;
reservation.clear();
}
}
}
else
{
m_events |= SPU_EVENT_LR; // ???
}
}
return (m_events & m_event_mask) != 0;
}
u32 GetChannelCount(u32 ch)
{
switch(ch)
@ -868,6 +915,7 @@ public:
case SPU_RdSigNotify1: return SPU.SNR[0].GetCount();
case SPU_RdSigNotify2: return SPU.SNR[1].GetCount();
case MFC_RdAtomicStat: return MFC1.AtomicStat.GetCount();
case SPU_RdEventStat: return CheckEvents() ? 1 : 0;
default:
{
@ -1112,6 +1160,19 @@ public:
break;
}
case SPU_WrEventMask:
{
m_event_mask = v;
if (v & ~(SPU_EVENT_IMPLEMENTED)) LOG_ERROR(Log::SPU, "SPU_WrEventMask: unsupported event masked (0x%x)");
break;
}
case SPU_WrEventAck:
{
m_events &= ~v;
break;
}
default:
{
LOG_ERROR(Log::SPU, "%s error (v=0x%x): unknown/illegal channel (%d [%s]).", __FUNCTION__, v, ch, spu_ch_name[ch]);
@ -1141,6 +1202,12 @@ public:
break;
}
case MFC_RdTagMask:
{
v = MFC1.QueryMask.GetValue();
break;
}
case SPU_RdSigNotify1:
{
while (!SPU.SNR[0].Pop(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1));
@ -1171,6 +1238,19 @@ public:
break;
}
case SPU_RdEventMask:
{
v = m_event_mask;
break;
}
case SPU_RdEventStat:
{
while (!CheckEvents() && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1));
v = m_events & m_event_mask;
break;
}
default:
{
LOG_ERROR(Log::SPU, "%s error: unknown/illegal channel (%d [%s]).", __FUNCTION__, ch, spu_ch_name[ch]);

View File

@ -2261,10 +2261,54 @@ void cellSync_init()
FIX_IMPORT(sysPrxForUser, _sys_vprintf , libsre + 0x1D97C);
FIX_IMPORT(sysPrxForUser, _sys_memcmp , libsre + 0x1D99C);
// fix xrefs
for (u32 i = libsre + 0x30EAC; i < libsre + 0x31EE0; i += 4)
const u32 seg2 = 0x2DF00;
// start of table:
// addr = (u64) addr - seg2, (u32) 1, (u32) 1, (u64) ptr
// addr = (u64) addr - seg2, (u32) 0x101, (u32) 1, (u64) ptr - seg2 (???)
// addr = (u64) addr, (u32) 0x100, (u32) 1, (u64) ptr - seg2 (???)
// addr = (u64) addr, (u32) 0, (u32) 1, (u64) ptr (???)
for (u32 i = libsre + 0x31EE0; i < libsre + 0x3A4F0; i += 24)
{
Memory.Write32(i, Memory.Read32(i) + libsre);
u64 addr = Memory.Read64(i);
const u64 flag = Memory.Read64(i + 8);
if (flag == 0x10100000001ull)
{
addr = addr + seg2 + libsre;
u32 value = Memory.Read32(addr);
assert(value == Memory.Read64(i + 16) + seg2);
Memory.Write32(addr, value + libsre);
}
else if (flag == 0x100000001ull)
{
addr = addr + seg2 + libsre;
u32 value = Memory.Read32(addr);
assert(value == Memory.Read64(i + 16));
Memory.Write32(addr, value + libsre);
}
else if (flag == 0x10000000001ull)
{
addr = addr + libsre;
u32 value = Memory.Read32(addr);
assert(value == Memory.Read64(i + 16) + seg2);
Memory.Write32(addr, value + libsre);
}
else if (flag == 1)
{
addr = addr + libsre;
u32 value = Memory.Read32(addr);
assert(value == Memory.Read64(i + 16));
Memory.Write32(addr, value + libsre);
}
else if (flag == 0x10000000004ull || flag == 0x10000000006ull)
{
// seems to be instruction modifiers for imports (done in other way in FIX_IMPORT)
}
else
{
LOG_NOTICE(HLE, "libsre: 0x%x : 0x%llx", i - libsre, flag);
}
}
});
#endif