Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SPU Improvements #36

Merged
22 commits merged into from
Dec 27, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 63 additions & 23 deletions rpcs3/Emu/Cell/MFC.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,22 @@

enum
{
MFC_PUT_CMD = 0x20,
MFC_GET_CMD = 0x40,
MFC_MASK_CMD = 0xffff,
MFC_PUT_CMD = 0x20, MFC_PUTB_CMD = 0x21, MFC_PUTF_CMD = 0x22,
MFC_GET_CMD = 0x40, MFC_GETB_CMD = 0x41, MFC_GETF_CMD = 0x42,
MFC_PUTL_CMD = 0x24, MFC_PUTLB_CMD = 0x25, MFC_PUTLF_CMD = 0x26,
MFC_GETL_CMD = 0x44, MFC_GETLB_CMD = 0x45, MFC_GETLF_CMD = 0x46,
MFC_GETLLAR_CMD = 0xD0,
MFC_PUTLLC_CMD = 0xB4,
MFC_PUTLLUC_CMD = 0xB0,
MFC_PUTQLLUC_CMD = 0xB8,
MFC_SNDSIG_CMD = 0xA0, MFC_SNDSIGB_CMD = 0xA1, MFC_SNDSIGF_CMD = 0xA2,
MFC_BARRIER_CMD = 0xC0,
MFC_EIEIO_CMD = 0xC8,
MFC_SYNC_CMD = 0xCC,

MFC_BARRIER_MASK = 0x01,
MFC_FENCE_MASK = 0x02,
MFC_MASK_CMD = 0xffff,
};

enum
Expand Down Expand Up @@ -130,11 +143,34 @@ class SPUReg

struct DMAC
{
DMAC_Queue queue[MFC_SPU_MAX_QUEUE_SPACE];
DMAC_Proxy proxy[MFC_PPU_MAX_QUEUE_SPACE];
//DMAC_Queue queue[MFC_SPU_MAX_QUEUE_SPACE]; //not used yet
DMAC_Proxy proxy[MFC_PPU_MAX_QUEUE_SPACE+MFC_SPU_MAX_QUEUE_SPACE]; //temporarily 24
u64 ls_offset;
std::atomic<u32> queue_pos;
std::atomic<u32> proxy_pos;
u32 queue_pos;
u32 proxy_pos;
long queue_lock;
long proxy_lock;

bool ProcessCmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size)
{
//returns true if the command should be deleted from the queue
if (cmd & (MFC_BARRIER_MASK | MFC_FENCE_MASK)) _mm_mfence();

switch(cmd & ~(MFC_BARRIER_MASK | MFC_FENCE_MASK))
{
case MFC_PUT_CMD:
memcpy(Memory + ea, Memory + ls_offset + lsa, size);
return true;

case MFC_GET_CMD:
memcpy(Memory + ls_offset + lsa, Memory + ea, size);
return true;

default:
ConLog.Error("Unknown DMA cmd.");
return true;
}
}

u32 Cmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size)
{
Expand All @@ -148,36 +184,40 @@ struct DMAC
return MFC_PPU_DMA_QUEUE_FULL;
}

DMAC_Proxy& p = proxy[proxy_pos++];
/* while (_InterlockedExchange(&proxy_lock, 1));
_mm_lfence();
DMAC_Proxy& p = proxy[proxy_pos];
p.cmd = cmd;
p.tag = tag;
p.lsa = lsa;
p.ea = ea;
p.size = size;
_mm_sfence(); //for DoCmd()
proxy_pos++;
_mm_sfence();
proxy_lock = 0; */
ProcessCmd(cmd, tag, lsa, ea, size);

return MFC_PPU_DMA_CMD_ENQUEUE_SUCCESSFUL;
}

void ClearCmd()
{
while (_InterlockedExchange(&proxy_lock, 1));
_mm_lfence();
memcpy(proxy, proxy + 1, --proxy_pos * sizeof(DMAC_Proxy));
_mm_sfence();
proxy_lock = 0; //release lock
}

void DoCmd()
{
if(proxy_pos)
{
DMAC_Proxy p = proxy[0];
memcpy(proxy, proxy + 1, --proxy_pos * sizeof(DMAC_Proxy));

switch(p.cmd)
const DMAC_Proxy& p = proxy[0];
if (ProcessCmd(p.cmd, p.tag, p.lsa, p.ea, p.size))
{
case MFC_PUT_CMD:
memcpy(Memory + p.ea, Memory + ls_offset + p.lsa, p.size);
break;

case MFC_GET_CMD:
memcpy(Memory + ls_offset + p.lsa, Memory + p.ea, p.size);
break;

default:
ConLog.Error("Unknown DMA cmd.");
break;
ClearCmd();
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions rpcs3/Emu/Cell/PPUInstrTable.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ namespace PPU_instr
static CodeField<11, 15> BI;

//Immediate field specifying a 14-bit signed two's complement branch displacement that is concatenated on the
//right with �00� and sign-extended to 64 bits.
//right with '00' and sign-extended to 64 bits.
static CodeFieldSigned<16, 31> BD(FIELD_BRANCH);

//
Expand Down Expand Up @@ -179,9 +179,9 @@ namespace PPU_instr
Record bit.
0 Does not update the condition register (CR).
1 Updates the CR to reflect the result of the operation.
For integer instructions, CR bits [02] are set to reflect the result as a signed quantity and CR bit [3]
For integer instructions, CR bits [0-2] are set to reflect the result as a signed quantity and CR bit [3]
receives a copy of the summary overflow bit, XER[SO]. The result as an unsigned quantity or a bit
string can be deduced from the EQ bit. For floating-point instructions, CR bits [47] are set to reflect
string can be deduced from the EQ bit. For floating-point instructions, CR bits [4-7] are set to reflect
floating-point exception, floating-point enabled exception, floating-point invalid operation exception,
and floating-point overflow exception.
*/
Expand Down
12 changes: 12 additions & 0 deletions rpcs3/Emu/Cell/PPUInterpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -3427,6 +3427,7 @@ class PPUInterpreter : public PPUOpcodes
void MTFSB1(u32 crbd, bool rc)
{
u64 mask = (1ULL << crbd);
if ((crbd == 29) && !CPU.FPSCR.NI) ConLog.Warning("Non-IEEE mode enabled");
CPU.FPSCR.FPSCR |= mask;

if(rc) UNIMPLEMENTED();
Expand All @@ -3440,6 +3441,7 @@ class PPUInterpreter : public PPUOpcodes
void MTFSB0(u32 crbd, bool rc)
{
u64 mask = (1ULL << crbd);
if ((crbd == 29) && !CPU.FPSCR.NI) ConLog.Warning("Non-IEEE mode disabled");
CPU.FPSCR.FPSCR &= ~mask;

if(rc) UNIMPLEMENTED();
Expand All @@ -3450,10 +3452,12 @@ class PPUInterpreter : public PPUOpcodes

if(i)
{
if ((crfd == 29) && !CPU.FPSCR.NI) ConLog.Warning("Non-IEEE mode enabled");
CPU.FPSCR.FPSCR |= mask;
}
else
{
if ((crfd == 29) && CPU.FPSCR.NI) ConLog.Warning("Non-IEEE mode disabled");
CPU.FPSCR.FPSCR &= ~mask;
}

Expand All @@ -3472,7 +3476,15 @@ class PPUInterpreter : public PPUOpcodes
if(flm & (1 << i)) mask |= 0xf << (i * 4);
}

const u32 oldNI = CPU.FPSCR.NI;
CPU.FPSCR.FPSCR = (CPU.FPSCR.FPSCR & ~mask) | ((u32&)CPU.FPR[frb] & mask);
if (CPU.FPSCR.NI != oldNI)
{
if (oldNI)
ConLog.Warning("Non-IEEE mode disabled");
else
ConLog.Warning("Non-IEEE mode enabled");
}
if(rc) UNK("mtfsf.");
}
void FCMPU(u32 crfd, u32 fra, u32 frb)
Expand Down
50 changes: 29 additions & 21 deletions rpcs3/Emu/Cell/RawSPUThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,16 +57,22 @@ bool RawSPUThread::Read32(const u64 addr, u32* value)
u32 offset = addr - GetStartAddr() - RAW_SPU_PROB_OFFSET;
switch(offset)
{
case MFC_LSA_offs: ConLog.Warning("RawSPUThread[%d]: Read32(MFC_LSA)", m_index); *value = MFC.LSA.GetValue(); break;
case MFC_EAH_offs: ConLog.Warning("RawSPUThread[%d]: Read32(MFC_EAH)", m_index); *value = MFC.EAH.GetValue(); break;
case MFC_EAL_offs: ConLog.Warning("RawSPUThread[%d]: Read32(MFC_EAL)", m_index); *value = MFC.EAL.GetValue(); break;
case MFC_Size_Tag_offs: ConLog.Warning("RawSPUThread[%d]: Read32(MFC_Size_Tag)", m_index); *value = MFC.Size_Tag.GetValue(); break;
case MFC_CMDStatus_offs: ConLog.Warning("RawSPUThread[%d]: Read32(MFC_CMDStatus)", m_index); *value = MFC.CMDStatus.GetValue(); break;
case MFC_QStatus_offs: ConLog.Warning("RawSPUThread[%d]: Read32(MFC_QStatus)", m_index); *value = MFC.QStatus.GetValue(); break;
case MFC_LSA_offs: ConLog.Warning("RawSPUThread[%d]: Read32(MFC_LSA)", m_index); *value = MFC2.LSA.GetValue(); break;
case MFC_EAH_offs: ConLog.Warning("RawSPUThread[%d]: Read32(MFC_EAH)", m_index); *value = MFC2.EAH.GetValue(); break;
case MFC_EAL_offs: ConLog.Warning("RawSPUThread[%d]: Read32(MFC_EAL)", m_index); *value = MFC2.EAL.GetValue(); break;
case MFC_Size_Tag_offs: ConLog.Warning("RawSPUThread[%d]: Read32(MFC_Size_Tag)", m_index); *value = MFC2.Size_Tag.GetValue(); break;
case MFC_CMDStatus_offs: ConLog.Warning("RawSPUThread[%d]: Read32(MFC_CMDStatus)", m_index); *value = MFC2.CMDStatus.GetValue(); break;
case MFC_QStatus_offs:
ConLog.Warning("RawSPUThread[%d]: Read32(MFC_QStatus)", m_index);
*value = MFC2.QStatus.GetValue();
break;
case Prxy_QueryType_offs: ConLog.Warning("RawSPUThread[%d]: Read32(Prxy_QueryType)", m_index); *value = Prxy.QueryType.GetValue(); break;
case Prxy_QueryMask_offs: ConLog.Warning("RawSPUThread[%d]: Read32(Prxy_QueryMask)", m_index); *value = Prxy.QueryMask.GetValue(); break;
case Prxy_TagStatus_offs: ConLog.Warning("RawSPUThread[%d]: Read32(Prxy_TagStatus)", m_index); *value = Prxy.TagStatus.GetValue(); break;
case SPU_Out_MBox_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_Out_MBox)", m_index); while(!SPU.Out_MBox.Pop(*value) && !Emu.IsStopped()) Sleep(1); break;
case SPU_Out_MBox_offs:
ConLog.Warning("RawSPUThread[%d]: Read32(SPU_Out_MBox)", m_index);
SPU.Out_MBox.PopUncond(*value); //if Out_MBox is empty yet, the result will be undefined
break;
case SPU_In_MBox_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_In_MBox)", m_index); while(!SPU.In_MBox.Pop(*value) && !Emu.IsStopped()) Sleep(1); break;
case SPU_MBox_Status_offs: //ConLog.Warning("RawSPUThread[%d]: Read32(SPU_MBox_Status)", m_index);
//SPU.MBox_Status.SetValue(SPU.Out_MBox.GetCount() ? SPU.MBox_Status.GetValue() | 1 : SPU.MBox_Status.GetValue() & ~1);
Expand All @@ -76,8 +82,8 @@ bool RawSPUThread::Read32(const u64 addr, u32* value)
case SPU_RunCntl_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_RunCntl)", m_index); *value = SPU.RunCntl.GetValue(); break;
case SPU_Status_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_Status)", m_index); *value = SPU.Status.GetValue(); break;
case SPU_NPC_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_NPC)", m_index); *value = SPU.NPC.GetValue(); break;
case SPU_RdSigNotify1_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_RdSigNotify1)", m_index); *value = SPU.RdSigNotify1.GetValue(); break;
case SPU_RdSigNotify2_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_RdSigNotify2)", m_index); *value = SPU.RdSigNotify2.GetValue(); break;
case SPU_RdSigNotify1_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_RdSigNotify1)", m_index); *value = SPU.SNR[0].GetValue(); break;
case SPU_RdSigNotify2_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_RdSigNotify2)", m_index); *value = SPU.SNR[1].GetValue(); break;

default:
ConLog.Error("RawSPUThread[%d]: Read32(0x%x)", m_index, offset);
Expand Down Expand Up @@ -151,16 +157,15 @@ bool RawSPUThread::Write32(const u64 addr, const u32 value)

switch(offset)
{
case MFC_LSA_offs: ConLog.Warning("RawSPUThread[%d]: Write32(MFC_LSA, 0x%x)", m_index, value); MFC.LSA.SetValue(value); break;
case MFC_EAH_offs: ConLog.Warning("RawSPUThread[%d]: Write32(MFC_EAH, 0x%x)", m_index, value); MFC.EAH.SetValue(value); break;
case MFC_EAL_offs: ConLog.Warning("RawSPUThread[%d]: Write32(MFC_EAL, 0x%x)", m_index, value); MFC.EAL.SetValue(value); break;
case MFC_Size_Tag_offs: ConLog.Warning("RawSPUThread[%d]: Write32(MFC_Size_Tag, 0x%x)", m_index, value); MFC.Size_Tag.SetValue(value); break;
case MFC_LSA_offs: MFC2.LSA.SetValue(value); break;
case MFC_EAH_offs: MFC2.EAH.SetValue(value); break;
case MFC_EAL_offs: MFC2.EAL.SetValue(value); break;
case MFC_Size_Tag_offs: MFC2.Size_Tag.SetValue(value); break;
case MFC_CMDStatus_offs:
ConLog.Warning("RawSPUThread[%d]: Write32(MFC_CMDStatus, 0x%x)", m_index, value);
MFC.CMDStatus.SetValue(value);
DoMfcCmd();
MFC2.CMDStatus.SetValue(value);
EnqMfcCmd(MFC2);
break;
case MFC_QStatus_offs: ConLog.Warning("RawSPUThread[%d]: Write32(MFC_QStatus, 0x%x)", m_index, value); MFC.QStatus.SetValue(value); break;
case MFC_QStatus_offs: ConLog.Warning("RawSPUThread[%d]: Write32(MFC_QStatus, 0x%x)", m_index, value); MFC2.QStatus.SetValue(value); break;
case Prxy_QueryType_offs:
{
ConLog.Warning("RawSPUThread[%d]: Write32(Prxy_QueryType, 0x%x)", m_index, value);
Expand All @@ -178,19 +183,22 @@ bool RawSPUThread::Write32(const u64 addr, const u32 value)
}

Prxy.QueryType.SetValue(0);
MFC.QStatus.SetValue(Prxy.QueryMask.GetValue());
MFC2.QStatus.SetValue(Prxy.QueryMask.GetValue());
}
break;
case Prxy_QueryMask_offs: ConLog.Warning("RawSPUThread[%d]: Write32(Prxy_QueryMask, 0x%x)", m_index, value); Prxy.QueryMask.SetValue(value); break;
case Prxy_TagStatus_offs: ConLog.Warning("RawSPUThread[%d]: Write32(Prxy_TagStatus, 0x%x)", m_index, value); Prxy.TagStatus.SetValue(value); break;
case SPU_Out_MBox_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_Out_MBox, 0x%x)", m_index, value); while(!SPU.Out_MBox.Push(value) && !Emu.IsStopped()) Sleep(1); break;
case SPU_In_MBox_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_In_MBox, 0x%x)", m_index, value); while(!SPU.In_MBox.Push(value) && !Emu.IsStopped()) Sleep(1); break;
case SPU_In_MBox_offs:
ConLog.Warning("RawSPUThread[%d]: Write32(SPU_In_MBox, 0x%x)", m_index, value);
SPU.In_MBox.PushUncond(value); //if In_MBox is already full, the last message will be overwritten
break;
case SPU_MBox_Status_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_MBox_Status, 0x%x)", m_index, value); SPU.MBox_Status.SetValue(value); break;
case SPU_RunCntl_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_RunCntl, 0x%x)", m_index, value); SPU.RunCntl.SetValue(value); break;
case SPU_Status_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_Status, 0x%x)", m_index, value); SPU.Status.SetValue(value); break;
case SPU_NPC_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_NPC, 0x%x)", m_index, value); SPU.NPC.SetValue(value); break;
case SPU_RdSigNotify1_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_RdSigNotify1, 0x%x)", m_index, value); SPU.RdSigNotify1.SetValue(value); break;
case SPU_RdSigNotify2_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_RdSigNotify2, 0x%x)", m_index, value); SPU.RdSigNotify2.SetValue(value); break;
case SPU_RdSigNotify1_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_RdSigNotify1, 0x%x)", m_index, value); SPU.SNR[0].SetValue(value); break;
case SPU_RdSigNotify2_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_RdSigNotify2, 0x%x)", m_index, value); SPU.SNR[1].SetValue(value); break;

default:
ConLog.Error("RawSPUThread[%d]: Write32(0x%x, 0x%x)", m_index, offset, value);
Expand Down
Loading