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:
parent
9eb280c367
commit
126b636edf
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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]);
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user