diff --git a/rpcs3/Emu/Cell/MFC.h b/rpcs3/Emu/Cell/MFC.h index c928078c46..839987cd68 100644 --- a/rpcs3/Emu/Cell/MFC.h +++ b/rpcs3/Emu/Cell/MFC.h @@ -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 @@ -130,11 +143,34 @@ public: 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 queue_pos; - std::atomic 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) { @@ -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(); } } } diff --git a/rpcs3/Emu/Cell/PPUInstrTable.h b/rpcs3/Emu/Cell/PPUInstrTable.h index c7b90aede8..e82c02abdb 100644 --- a/rpcs3/Emu/Cell/PPUInstrTable.h +++ b/rpcs3/Emu/Cell/PPUInstrTable.h @@ -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); // @@ -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 [0–2] 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 [4–7] 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. */ diff --git a/rpcs3/Emu/Cell/PPUInterpreter.h b/rpcs3/Emu/Cell/PPUInterpreter.h index 485c055cfa..c4fda8f33a 100644 --- a/rpcs3/Emu/Cell/PPUInterpreter.h +++ b/rpcs3/Emu/Cell/PPUInterpreter.h @@ -3427,6 +3427,7 @@ private: 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(); @@ -3440,6 +3441,7 @@ private: 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(); @@ -3450,10 +3452,12 @@ private: 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; } @@ -3472,7 +3476,15 @@ private: 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) diff --git a/rpcs3/Emu/Cell/RawSPUThread.cpp b/rpcs3/Emu/Cell/RawSPUThread.cpp index ee0cf6c4b3..006c7b28d7 100644 --- a/rpcs3/Emu/Cell/RawSPUThread.cpp +++ b/rpcs3/Emu/Cell/RawSPUThread.cpp @@ -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); @@ -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); @@ -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); @@ -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); diff --git a/rpcs3/Emu/Cell/SPUInterpreter.h b/rpcs3/Emu/Cell/SPUInterpreter.h index e71eb5a7f0..1dcb845bd5 100644 --- a/rpcs3/Emu/Cell/SPUInterpreter.h +++ b/rpcs3/Emu/Cell/SPUInterpreter.h @@ -7,12 +7,12 @@ #define UNIMPLEMENTED() UNK(__FUNCTION__) -typedef union _CRT_ALIGN(16) __u32x4 { - unsigned __int32 _u32[4]; +/* typedef union _CRT_ALIGN(16) __u32x4 { + u32 _u32[4]; __m128i m128i; __m128 m128; __m128d m128d; - } __u32x4; + } __u32x4; */ class SPUInterpreter : public SPUOpcodes { @@ -35,24 +35,24 @@ private: if(code & 0x2000) { CPU.SetExitStatus(code & 0xfff); - CPU.Stop(); } else { ConLog.Warning("STOP: 0x%x", code); - Emu.Pause(); + //Emu.Pause(); } + CPU.Stop(); } void LNOP() { } void SYNC(u32 Cbit) { - //UNIMPLEMENTED(); + _mm_mfence(); } void DSYNC() { - //UNIMPLEMENTED(); + _mm_mfence(); } void MFSPR(u32 rt, u32 sa) { @@ -191,18 +191,8 @@ private: { const u32 s = i7 & 0x3f; - for(u32 j = 0; j < 4; ++j) - { - const u32 t = CPU.GPR[ra]._u32[j]; - u32 r = 0; - - for(u32 b = 0; b + s < 32; ++b) - { - r |= t & (1 << (b + s)); - } - - CPU.GPR[rt]._u32[j] = r; - } + for (u32 j = 0; j < 4; ++j) + CPU.GPR[rt]._u32[j] = CPU.GPR[ra]._u32[j] << s; } void ROTHI(u32 rt, u32 ra, s32 i7) { @@ -388,28 +378,21 @@ private: } void FREST(u32 rt, u32 ra) { - //(SSE) RCPPS - Compute Reciprocals of Packed Single-Precision Floating-Point Values - //rt = approximate(1/ra) - CPU.GPR[rt]._m128 = _mm_rcp_ps(CPU.GPR[ra]._m128); + //CPU.GPR[rt]._m128 = _mm_rcp_ps(CPU.GPR[ra]._m128); + for (int i = 0; i < 4; i++) + CPU.GPR[rt]._f[i] = 1 / CPU.GPR[ra]._f[i]; } void FRSQEST(u32 rt, u32 ra) { - //(SSE) RSQRTPS - Compute Reciprocals of Square Roots of Packed Single-Precision Floating-Point Values - //rt = approximate(1/sqrt(abs(ra))) - //abs(ra) === ra & FloatAbsMask - const __u32x4 FloatAbsMask = {0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff}; - CPU.GPR[rt]._m128 = _mm_rsqrt_ps(_mm_and_ps(CPU.GPR[ra]._m128, FloatAbsMask.m128)); + //const __u32x4 FloatAbsMask = {0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff}; + //CPU.GPR[rt]._m128 = _mm_rsqrt_ps(_mm_and_ps(CPU.GPR[ra]._m128, FloatAbsMask.m128)); + for (int i = 0; i < 4; i++) + CPU.GPR[rt]._f[i] = 1 / sqrt(abs(CPU.GPR[ra]._f[i])); } void LQX(u32 rt, u32 ra, u32 rb) { u32 a = CPU.GPR[ra]._u32[3], b = CPU.GPR[rb]._u32[3]; - if(b & 0xf) - { - ConLog.Warning("LQX HACK (a[0x%x] + b[0x%x(0x%x)])", a, b << 3, b); - b <<= 3; - } - u32 lsa = (a + b) & 0x3fff0; if(!CPU.IsGoodLSA(lsa)) @@ -1009,9 +992,10 @@ private: exp = 255; CPU.GPR[rt]._u32[i] = (CPU.GPR[ra]._u32[i] & 0x807fffff) | (exp << 23); + + CPU.GPR[rt]._u32[i] = (u32)CPU.GPR[rt]._f[i]; //trunc } - //(SSE2) CVTTPS2DQ - Convert with Truncation Packed Single FP to Packed Dword Int - CPU.GPR[rt]._m128i = _mm_cvttps_epi32(CPU.GPR[rt]._m128); + //CPU.GPR[rt]._m128i = _mm_cvttps_epi32(CPU.GPR[rt]._m128); } void CFLTU(u32 rt, u32 ra, s32 i8) { @@ -1038,11 +1022,12 @@ private: } void CSFLT(u32 rt, u32 ra, s32 i8) { - //(SSE2) CVTDQ2PS - Convert Packed Dword Integers to Packed Single-Precision FP Values - CPU.GPR[rt]._m128 = _mm_cvtepi32_ps(CPU.GPR[ra]._m128i); + //CPU.GPR[rt]._m128 = _mm_cvtepi32_ps(CPU.GPR[ra]._m128i); const u32 scale = 155 - (i8 & 0xff); //unsigned immediate for (int i = 0; i < 4; i++) { + CPU.GPR[rt]._f[i] = (s32)CPU.GPR[ra]._i32[i]; + u32 exp = ((CPU.GPR[rt]._u32[i] >> 23) & 0xff) - scale; if (exp > 255) //< 0 @@ -1412,7 +1397,7 @@ private: } } } - void MPYA(u32 rc, u32 ra, u32 rb, u32 rt) + void MPYA(u32 rt, u32 ra, u32 rb, u32 rc) { for (int w = 0; w < 4; w++) CPU.GPR[rt]._i32[w] = CPU.GPR[ra]._i16[w*2] * CPU.GPR[rb]._i16[w*2] + CPU.GPR[rc]._i32[w]; @@ -1424,14 +1409,14 @@ private: CPU.GPR[rt]._f[2] = CPU.GPR[rc]._f[2] - CPU.GPR[ra]._f[2] * CPU.GPR[rb]._f[2]; CPU.GPR[rt]._f[3] = CPU.GPR[rc]._f[3] - CPU.GPR[ra]._f[3] * CPU.GPR[rb]._f[3]; } - void FMA(u32 rc, u32 ra, u32 rb, u32 rt) + void FMA(u32 rt, u32 ra, u32 rb, u32 rc) { CPU.GPR[rt]._f[0] = CPU.GPR[ra]._f[0] * CPU.GPR[rb]._f[0] + CPU.GPR[rc]._f[0]; CPU.GPR[rt]._f[1] = CPU.GPR[ra]._f[1] * CPU.GPR[rb]._f[1] + CPU.GPR[rc]._f[1]; CPU.GPR[rt]._f[2] = CPU.GPR[ra]._f[2] * CPU.GPR[rb]._f[2] + CPU.GPR[rc]._f[2]; CPU.GPR[rt]._f[3] = CPU.GPR[ra]._f[3] * CPU.GPR[rb]._f[3] + CPU.GPR[rc]._f[3]; } - void FMS(u32 rc, u32 ra, u32 rb, u32 rt) + void FMS(u32 rt, u32 ra, u32 rb, u32 rc) { CPU.GPR[rt]._f[0] = CPU.GPR[ra]._f[0] * CPU.GPR[rb]._f[0] - CPU.GPR[rc]._f[0]; CPU.GPR[rt]._f[1] = CPU.GPR[ra]._f[1] * CPU.GPR[rb]._f[1] - CPU.GPR[rc]._f[1]; diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index 2faacb49bd..76732b7f58 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -43,14 +43,19 @@ void SPUThread::InitRegs() GPR[5]._u64[1] = m_args[2]; GPR[6]._u64[1] = m_args[3]; + cfg.Reset(); + dmac.ls_offset = m_offset; dmac.proxy_pos = 0; dmac.queue_pos = 0; + dmac.proxy_lock = 0; + dmac.queue_lock = 0; SPU.RunCntl.SetValue(SPU_RUNCNTL_STOP); SPU.Status.SetValue(SPU_STATUS_RUNNING); Prxy.QueryType.SetValue(0); - MFC.CMDStatus.SetValue(0); + MFC1.CMDStatus.SetValue(0); + MFC2.CMDStatus.SetValue(0); //PC = SPU.NPC.GetValue(); } diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index 020882af20..d881fc580c 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -249,22 +249,51 @@ union SPU_SPR_hdr } }; +union SPU_SNRConfig_hdr +{ + u64 value; + + SPU_SNRConfig_hdr() {} + + wxString ToString() const + { + return wxString::Format("%01x", value); + } + + void Reset() + { + memset(this, 0, sizeof(*this)); + } +}; + class SPUThread : public PPCThread { public: SPU_GPR_hdr GPR[128]; //General-Purpose Register SPU_SPR_hdr SPR[128]; //Special-Purpose Registers FPSCR FPSCR; + SPU_SNRConfig_hdr cfg; //Signal Notification Registers Configuration (OR-mode enabled: 0x1 for SNR1, 0x2 for SNR2) template class Channel { public: static const size_t max_count = _max_count; +#ifdef _M_X64 + static const bool x86 = false; +#else + static const bool x86 = true; +#endif private: - u32 m_value[max_count]; - u32 m_index; + union _CRT_ALIGN(8) { + struct { + volatile u32 m_index; + u32 m_value[max_count]; + }; + volatile u64 m_indval; + }; + volatile long m_lock; public: @@ -276,29 +305,154 @@ public: void Init() { m_index = 0; + m_lock = 0; //simple lock } __forceinline bool Pop(u32& res) { - if(!m_index) return false; - res = m_value[--m_index]; - return true; + if (max_count > 1 || x86) + { + while (_InterlockedExchange(&m_lock, 1)); + _mm_lfence(); + if(!m_index) + { + m_lock = 0; //release lock + return false; + } + res = m_value[--m_index]; + m_value[m_index] = 0; + _mm_sfence(); + m_lock = 0; + return true; + } + else + { //lock-free + if(!m_index) + return false; + else + { + res = (m_indval >> 32); + m_indval = 0; + return true; + } + } } __forceinline bool Push(u32 value) { - if(m_index >= max_count) return false; - m_value[m_index++] = value; - return true; + if (max_count > 1 || x86) + { + while (_InterlockedExchange(&m_lock, 1)); + _mm_lfence(); + if(m_index >= max_count) + { + m_lock = 0; //release lock + return false; + } + m_value[m_index++] = value; + _mm_sfence(); + m_lock = 0; + return true; + } + else + { //lock-free + if(m_index) + return false; + else + { + m_indval = ((u64)value << 32) | 1; + return true; + } + } + } + + __forceinline void PushUncond(u32 value) + { + if (max_count > 1 || x86) + { + while (_InterlockedExchange(&m_lock, 1)); + _mm_lfence(); + if(m_index >= max_count) + m_value[max_count-1] = value; //last message is overwritten + else + m_value[m_index++] = value; + _mm_sfence(); + m_lock = 0; + } + else + { //lock-free + m_indval = ((u64)value << 32) | 1; + } + } + + __forceinline void PushUncond_OR(u32 value) + { + if (max_count > 1 || x86) + { + while (_InterlockedExchange(&m_lock, 1)); + _mm_lfence(); + if(m_index >= max_count) + m_value[max_count-1] |= value; //last message is logically ORed + else + m_value[m_index++] = value; + _mm_sfence(); + m_lock = 0; + } + else + { +#ifdef _M_X64 + _InterlockedOr64((volatile __int64*)m_indval, ((u64)value << 32) | 1); +#else + ConLog.Error("PushUncond_OR(): no code compiled"); +#endif + } + } + + __forceinline void PopUncond(u32& res) + { + if (max_count > 1 || x86) + { + while (_InterlockedExchange(&m_lock, 1)); + _mm_lfence(); + if(!m_index) + res = 0; //result is undefined + else + { + res = m_value[--m_index]; + m_value[m_index] = 0; + } + _mm_sfence(); + m_lock = 0; + } + else + { //lock-free + if(!m_index) + res = 0; + else + { + res = (m_indval >> 32); + m_indval = 0; + } + } } u32 GetCount() const { + if (max_count > 1 || x86) + { + while (m_lock); + _mm_lfence(); + } return m_index; } u32 GetFreeCount() const { + if (max_count > 1 || x86) + { + while (m_lock); + _mm_lfence(); + } return max_count - m_index; } @@ -313,7 +467,7 @@ public: } }; - struct + struct MFCReg { Channel<1> LSA; Channel<1> EAH; @@ -321,7 +475,7 @@ public: Channel<1> Size_Tag; Channel<1> CMDStatus; Channel<1> QStatus; - } MFC; + } MFC1, MFC2; struct { @@ -339,8 +493,7 @@ public: Channel<1> RunCntl; Channel<1> Status; Channel<1> NPC; - Channel<1> RdSigNotify1; - Channel<1> RdSigNotify2; + Channel<1> SNR[2]; } SPU; u32 LSA; @@ -353,36 +506,34 @@ public: DMAC dmac; - void DoMfcCmd() + void EnqMfcCmd(MFCReg& MFCArgs) { - u32 cmd = MFC.CMDStatus.GetValue(); + u32 cmd = MFCArgs.CMDStatus.GetValue(); u16 op = cmd & MFC_MASK_CMD; - switch(op & (MFC_PUT_CMD | MFC_GET_CMD)) + u32 lsa = MFCArgs.LSA.GetValue(); + u64 ea = (u64)MFCArgs.EAL.GetValue() | ((u64)MFCArgs.EAH.GetValue() << 32); + u32 size_tag = MFCArgs.Size_Tag.GetValue(); + u16 tag = (u16)size_tag; + u16 size = size_tag >> 16; + + switch(op & ~(MFC_BARRIER_MASK | MFC_FENCE_MASK)) { case MFC_PUT_CMD: case MFC_GET_CMD: { - u32 lsa = MFC.LSA.GetValue(); - u64 ea = (u64)MFC.EAL.GetValue() | ((u64)MFC.EAH.GetValue() << 32); - u32 size_tag = MFC.Size_Tag.GetValue(); - u16 tag = (u16)size_tag; - u16 size = size_tag >> 16; - - ConLog.Warning("DMA %s:", op & MFC_PUT_CMD ? "PUT" : "GET"); - ConLog.Warning("*** lsa = 0x%x", lsa); - ConLog.Warning("*** ea = 0x%llx", ea); - ConLog.Warning("*** tag = 0x%x", tag); - ConLog.Warning("*** size = 0x%x", size); - ConLog.Warning("*** cmd = 0x%x", cmd); - ConLog.SkipLn(); - - MFC.CMDStatus.SetValue(dmac.Cmd(cmd, tag, lsa, ea, size)); + /* ConLog.Warning("DMA %s%s%s: lsa = 0x%x, ea = 0x%llx, tag = 0x%x, size = 0x%x, cmd = 0x%x", + op & MFC_PUT_CMD ? "PUT" : "GET", + op & MFC_BARRIER_MASK ? "B" : "", + op & MFC_FENCE_MASK ? "F" : "", + lsa, ea, tag, size, cmd); */ + MFCArgs.CMDStatus.SetValue(dmac.Cmd(cmd, tag, lsa, ea, size)); } break; default: - ConLog.Error("Unknown MFC cmd. (opcode=0x%x, cmd=0x%x)", op, cmd); + ConLog.Error("Unknown MFC cmd. (opcode=0x%x, cmd=0x%x, lsa = 0x%x, ea = 0x%llx, tag = 0x%x, size = 0x%x)", + op, cmd, lsa, ea, tag, size); break; } } @@ -391,34 +542,6 @@ public: { switch(ch) { - case SPU_RdEventStat: //Read event status with mask applied - case SPU_WrEventMask: //Write event mask - case SPU_WrEventAck: //Write end of event processing - case SPU_RdSigNotify1: //Signal notification 1 - case SPU_RdSigNotify2: //Signal notification 2 - case SPU_WrDec: //Write decrementer count - case SPU_RdDec: //Read decrementer count - case SPU_RdEventMask: //Read event mask - case SPU_RdMachStat: //Read SPU run status - case SPU_WrSRR0: //Write SPU machine state save/restore register 0 (SRR0) - case SPU_RdSRR0: //Read SPU machine state save/restore register 0 (SRR0) - case MFC_WrMSSyncReq: //Write multisource synchronization request - case MFC_RdTagMask: //Read tag mask - case MFC_LSA: //Write local memory address command parameter - case MFC_EAH: //Write high order DMA effective address command parameter - case MFC_EAL: //Write low order DMA effective address command parameter - case MFC_Size: //Write DMA transfer size command parameter - case MFC_TagID: //Write tag identifier command parameter - case MFC_Cmd: //Write and enqueue DMA command with associated class ID - case MFC_WrTagMask: //Write tag mask - case MFC_WrTagUpdate: //Write request for conditional or unconditional tag status update - case MFC_RdTagStat: //Read tag status with mask applied - case MFC_RdListStallStat: //Read DMA list stall-and-notify status - case MFC_WrListStallAck: //Write DMA list stall-and-notify acknowledge - case MFC_RdAtomicStat: //Read completion status of last completed immediate MFC atomic update command - ConLog.Error("%s error: unimplemented channel (%s).", __FUNCTION__, spu_ch_name[ch]); - break; - case SPU_WrOutMbox: return SPU.Out_MBox.GetFreeCount(); @@ -426,8 +549,18 @@ public: return SPU.In_MBox.GetCount(); case SPU_WrOutIntrMbox: + ConLog.Warning("GetChannelCount(%s) = 0", spu_ch_name[ch]); return 0;//return SPU.OutIntr_Mbox.GetFreeCount(); + case MFC_RdTagStat: + return Prxy.TagStatus.GetCount(); + + case SPU_RdSigNotify1: + return SPU.SNR[0].GetCount(); + + case SPU_RdSigNotify2: + return SPU.SNR[1].GetCount(); + default: ConLog.Error("%s error: unknown/illegal channel (%d [%s]).", __FUNCTION__, ch, spu_ch_name[ch]); break; @@ -440,55 +573,51 @@ public: { const u32 v = r._u32[3]; - ConLog.Warning("%s: %s = 0x%x", __FUNCTION__, spu_ch_name[ch], v); - switch(ch) { case SPU_WrOutIntrMbox: - while(!SPU.OutIntr_Mbox.Push(v) && !Emu.IsStopped()) - { - Sleep(1); - } + ConLog.Warning("%s: %s = 0x%x", __FUNCTION__, spu_ch_name[ch], v); + while (!SPU.OutIntr_Mbox.Push(v) && !Emu.IsStopped()) Sleep(1); break; case SPU_WrOutMbox: - while(!SPU.Out_MBox.Push(v) && !Emu.IsStopped()) - { - Sleep(1); - } + ConLog.Warning("%s: %s = 0x%x", __FUNCTION__, spu_ch_name[ch], v); + while (!SPU.Out_MBox.Push(v) && !Emu.IsStopped()) Sleep(1); break; case MFC_WrTagMask: + //ConLog.Warning("%s: %s = 0x%x", __FUNCTION__, spu_ch_name[ch], v); Prxy.QueryMask.SetValue(v); break; case MFC_WrTagUpdate: - Prxy.TagStatus.SetValue(Prxy.QueryMask.GetValue()); + //ConLog.Warning("%s: %s = 0x%x", __FUNCTION__, spu_ch_name[ch], v); + Prxy.TagStatus.PushUncond(Prxy.QueryMask.GetValue()); break; case MFC_LSA: - MFC.LSA.SetValue(v); + MFC1.LSA.SetValue(v); break; case MFC_EAH: - MFC.EAH.SetValue(v); + MFC1.EAH.SetValue(v); break; case MFC_EAL: - MFC.EAL.SetValue(v); + MFC1.EAL.SetValue(v); break; case MFC_Size: - MFC.Size_Tag.SetValue((MFC.Size_Tag.GetValue() & 0xffff) | (v << 16)); + MFC1.Size_Tag.SetValue((MFC1.Size_Tag.GetValue() & 0xffff) | (v << 16)); break; case MFC_TagID: - MFC.Size_Tag.SetValue((MFC.Size_Tag.GetValue() & ~0xffff) | (v & 0xffff)); + MFC1.Size_Tag.SetValue((MFC1.Size_Tag.GetValue() & ~0xffff) | (v & 0xffff)); break; case MFC_Cmd: - MFC.CMDStatus.SetValue(v); - DoMfcCmd(); + MFC1.CMDStatus.SetValue(v); + EnqMfcCmd(MFC1); break; default: @@ -505,19 +634,29 @@ public: switch(ch) { case SPU_RdInMbox: - if(!SPU.In_MBox.Pop(v)) v = 0; + while (!SPU.In_MBox.Pop(v) && !Emu.IsStopped()) Sleep(1); + ConLog.Warning("%s: 0x%x = %s", __FUNCTION__, v, spu_ch_name[ch]); break; case MFC_RdTagStat: - v = Prxy.TagStatus.GetValue(); + while (!Prxy.TagStatus.Pop(v) && !Emu.IsStopped()) Sleep(1); + //ConLog.Warning("%s: 0x%x = %s", __FUNCTION__, v, spu_ch_name[ch]); + break; + + case SPU_RdSigNotify1: + while (!SPU.SNR[0].Pop(v) && !Emu.IsStopped()) Sleep(1); + //ConLog.Warning("%s: 0x%x = %s", __FUNCTION__, v, spu_ch_name[ch]); + break; + + case SPU_RdSigNotify2: + while (!SPU.SNR[1].Pop(v) && !Emu.IsStopped()) Sleep(1); + //ConLog.Warning("%s: 0x%x = %s", __FUNCTION__, v, spu_ch_name[ch]); break; default: ConLog.Error("%s error: unknown/illegal channel (%d [%s]).", __FUNCTION__, ch, spu_ch_name[ch]); break; } - - ConLog.Warning("%s: 0x%x = %s", __FUNCTION__, v, spu_ch_name[ch]); } bool IsGoodLSA(const u32 lsa) const { return Memory.IsGoodAddr(lsa + m_offset) && lsa < 0x40000; } diff --git a/rpcs3/Emu/FS/vfsDevice.cpp b/rpcs3/Emu/FS/vfsDevice.cpp index 570e60dd52..d7fbc464a1 100644 --- a/rpcs3/Emu/FS/vfsDevice.cpp +++ b/rpcs3/Emu/FS/vfsDevice.cpp @@ -30,7 +30,11 @@ u32 vfsDevice::CmpPs3Path(const wxString& ps3_path) for(u32 i=0; i segments, int nseg) +{ + sysPrxForUser.Warning("sys_spu_elf_get_segments(elf_img=0x%x, segments_addr=0x%x, nseg=0x%x)", elf_img, segments.GetAddr(), nseg); + return CELL_OK; +} + +int sys_spu_image_import(mem_ptr_t img, u32 src, u32 type) +{ + sysPrxForUser.Warning("sys_spu_image_import(img=0x%x, src=0x%x, type=0x%x)", img.GetAddr(), src, type); + + if(!img.IsGood() || !Memory.IsGoodAddr(src)) + { + return CELL_EFAULT; + } + + vfsStreamMemory f(src); + u32 entry = LoadSpuImage(f); + + img->type = 1; + img->entry_point = entry; + img->segs_addr = 0x0; + img->nsegs = 0; + + return CELL_OK; +} + +int sys_raw_spu_load(int id, u32 path_addr, mem32_t entry) +{ + const wxString path = Memory.ReadString(path_addr).mb_str(); + sysPrxForUser.Warning("sys_raw_spu_load(id=0x%x, path=0x%x [%s], entry_addr=0x%x)", + id, path_addr, path, entry.GetAddr()); + + vfsFile f(path.c_str()); + if(!f.IsOpened()) + { + sysPrxForUser.Error("sys_raw_spu_load error: '%s' not found!", path); + return CELL_ENOENT; + } + + ELFLoader l(f); + l.LoadInfo(); + l.LoadData(RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * id); + + entry = l.GetEntry(); + + return CELL_OK; +} + +extern u64 g_last_spu_offset; + +int sys_raw_spu_image_load(int id, mem_ptr_t img) +{ + sysPrxForUser.Warning("sys_raw_spu_image_load(id=0x%x, img_addr=0x%x)", id, img.GetAddr()); + + memcpy(Memory + RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * id, Memory + g_last_spu_offset, 256 * 1024); + Memory.Write32(RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * id + RAW_SPU_PROB_OFFSET + SPU_NPC_offs, + img->entry_point - g_last_spu_offset); + + return CELL_OK; +} + void sysPrxForUser_init() { sysPrxForUser.AddFunc(0x744680a2, sys_initialize_tls); @@ -92,4 +162,11 @@ void sysPrxForUser_init() sysPrxForUser.AddFunc(0xb257540b, sys_mmapper_allocate_memory); sysPrxForUser.AddFunc(0xdc578057, sys_mmapper_map_memory); + + sysPrxForUser.AddFunc(0x1ed454ce, sys_spu_elf_get_information); + sysPrxForUser.AddFunc(0xdb6b3250, sys_spu_elf_get_segments); + sysPrxForUser.AddFunc(0xebe5f72f, sys_spu_image_import); + + sysPrxForUser.AddFunc(0x893305fa, sys_raw_spu_load); + sysPrxForUser.AddFunc(0xb995662e, sys_raw_spu_image_load); } diff --git a/rpcs3/Emu/SysCalls/SysCalls.cpp b/rpcs3/Emu/SysCalls/SysCalls.cpp index 686e5e78b7..959fd93dd1 100644 --- a/rpcs3/Emu/SysCalls/SysCalls.cpp +++ b/rpcs3/Emu/SysCalls/SysCalls.cpp @@ -97,8 +97,8 @@ static func_caller* sc_table[1024] = null_func, null_func, null_func, null_func, bind_func(sys_spu_initialize), //169 bind_func(sys_spu_thread_group_create), bind_func(sys_spu_thread_set_argument), bind_func(sys_spu_thread_initialize), bind_func(sys_spu_thread_group_start), null_func, //174 null_func, null_func, null_func, null_func, null_func, //179 - null_func, bind_func(sys_spu_thread_write_ls), bind_func(sys_spu_thread_read_ls), null_func, null_func, //184 - null_func, null_func, null_func, null_func, null_func, //189 + null_func, bind_func(sys_spu_thread_write_ls), bind_func(sys_spu_thread_read_ls), null_func, bind_func(sys_spu_thread_write_snr), //184 + null_func, null_func, bind_func(sys_spu_thread_set_spu_cfg), bind_func(sys_spu_thread_get_spu_cfg), null_func, //189 bind_func(sys_spu_thread_write_spu_mb), bind_func(sys_spu_thread_connect_event), null_func, null_func, null_func, //194 null_func, null_func, null_func, null_func, null_func, //199 null_func, null_func, null_func, null_func, null_func, //204 diff --git a/rpcs3/Emu/SysCalls/SysCalls.h b/rpcs3/Emu/SysCalls/SysCalls.h index e36d8d83b9..f802f7a4b7 100644 --- a/rpcs3/Emu/SysCalls/SysCalls.h +++ b/rpcs3/Emu/SysCalls/SysCalls.h @@ -291,6 +291,9 @@ extern int sys_spu_initialize(u32 max_usable_spu, u32 max_raw_spu); extern int sys_spu_thread_write_ls(u32 id, u32 address, u64 value, u32 type); extern int sys_spu_thread_read_ls(u32 id, u32 address, mem64_t value, u32 type); extern int sys_spu_thread_write_spu_mb(u32 id, u32 value); +extern int sys_spu_thread_set_spu_cfg(u32 id, u64 value); +extern int sys_spu_thread_get_spu_cfg(u32 id, mem64_t value); +extern int sys_spu_thread_write_snr(u32 id, u32 number, u32 value); //sys_time extern int sys_time_get_timezone(mem32_t timezone, mem32_t summertime); diff --git a/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp b/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp index b888915c28..a7fb066862 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp @@ -1,6 +1,7 @@ #include "stdafx.h" #include "SC_SPU_Thread.h" #include "Emu/SysCalls/SysCalls.h" +#include "Emu/SysCalls/SC_FUNC.h" #include "Loader/ELF.h" #include "Emu/Cell/RawSPUThread.h" @@ -20,22 +21,23 @@ struct SpuGroupInfo } }; -u64 g_spu_offset = 0; +u64 g_last_spu_offset = 0; u32 LoadSpuImage(vfsStream& stream) { ELFLoader l(stream); l.LoadInfo(); - g_spu_offset = Memory.MainMem.Alloc(0xFFFFED - stream.GetSize()); - l.LoadData(g_spu_offset); + u32 alloc_size = 0xFFFFED - stream.GetSize(); + g_last_spu_offset = Memory.MainMem.Alloc(alloc_size); + l.LoadData(g_last_spu_offset); - return g_spu_offset + l.GetEntry(); + return g_last_spu_offset + l.GetEntry(); } //156 int sys_spu_image_open(mem_ptr_t img, u32 path_addr) { - const std::string& path = Memory.ReadString(path_addr).mb_str(); + const wxString path = Memory.ReadString(path_addr).mb_str(); sc_spu.Warning("sys_spu_image_open(img_addr=0x%x, path_addr=0x%x [%s])", img.GetAddr(), path_addr, path); if(!img.IsGood() || !Memory.IsGoodAddr(path_addr)) @@ -93,37 +95,41 @@ int sys_spu_thread_initialize(mem32_t thread, u32 group, u32 spu_num, mem_ptr_t< return CELL_EBUSY; } - u32 entry = img->entry_point; + u32 ls_entry = img->entry_point - g_last_spu_offset; std::string name = Memory.ReadString(attr->name_addr, attr->name_len).mb_str(); u64 a1 = arg->arg1; u64 a2 = arg->arg2; u64 a3 = arg->arg3; u64 a4 = arg->arg4; - ConLog.Write("New SPU Thread:"); - ConLog.Write("entry = 0x%x", entry); - ConLog.Write("name = %s", name); - ConLog.Write("a1 = 0x%x", a1); - ConLog.Write("a2 = 0x%x", a2); - ConLog.Write("a3 = 0x%x", a3); - ConLog.Write("a4 = 0x%x", a4); - ConLog.SkipLn(); - CPUThread& new_thread = Emu.GetCPU().AddThread(CPU_THREAD_SPU); - new_thread.SetOffset(g_spu_offset); - new_thread.SetEntry(entry - g_spu_offset); + //copy SPU image: + u32 spu_offset = Memory.MainMem.Alloc(256 * 1024); + memcpy(Memory + spu_offset, Memory + g_last_spu_offset, 256 * 1024); + //initialize from new place: + new_thread.SetOffset(spu_offset); + new_thread.SetEntry(ls_entry); new_thread.SetName(name); - new_thread.Run(); - new_thread.Pause(); new_thread.SetArg(0, a1); new_thread.SetArg(1, a2); new_thread.SetArg(2, a3); new_thread.SetArg(3, a4); + new_thread.Run(); thread = new_thread.GetId(); group_info.threads[spu_num] = &new_thread; + ConLog.Write("New SPU Thread:"); + ConLog.Write("ls_entry = 0x%x", ls_entry); + ConLog.Write("name = %s", wxString(name)); + ConLog.Write("a1 = 0x%x", a1); + ConLog.Write("a2 = 0x%x", a2); + ConLog.Write("a3 = 0x%x", a3); + ConLog.Write("a4 = 0x%x", a4); + ConLog.Write("ls_offset = 0x%x", ((SPUThread&)new_thread).dmac.ls_offset); + ConLog.SkipLn(); + return CELL_OK; } @@ -164,7 +170,7 @@ int sys_spu_thread_group_start(u32 id) ID& id_data = Emu.GetIdManager().GetIDData(id); SpuGroupInfo& group_info = *(SpuGroupInfo*)id_data.m_data; - Emu.Pause(); + //Emu.Pause(); for(int i=0; itype.ToLE()); ConLog.Write("*** attr.option.ct=%d", attr->option.ct.ToLE()); - const std::string& name = Memory.ReadString(attr->name_addr, attr->name_len).mb_str(); + const wxString name = Memory.ReadString(attr->name_addr, attr->name_len).mb_str(); ConLog.Write("*** name='%s'", name); id = Emu.GetIdManager().GetNewID(wxString::Format("sys_spu_thread_group '%s'", name), new SpuGroupInfo(*attr)); @@ -335,6 +341,72 @@ int sys_spu_thread_write_spu_mb(u32 id, u32 value) return CELL_OK; } +//187 +int sys_spu_thread_set_spu_cfg(u32 id, u64 value) +{ + sc_spu.Warning("sys_spu_thread_set_spu_cfg(id=0x%x, value=0x%x)", id, value); + + CPUThread* thr = Emu.GetCPU().GetThread(id); + + if(!thr || (thr->GetType() != CPU_THREAD_SPU && thr->GetType() != CPU_THREAD_RAW_SPU)) + { + return CELL_ESRCH; + } + + if (value > 3) + { + return CELL_EINVAL; + } + + (*(SPUThread*)thr).cfg.value = value; + + return CELL_OK; +} + +//188 +int sys_spu_thread_get_spu_cfg(u32 id, mem64_t value) +{ + sc_spu.Warning("sys_spu_thread_get_spu_cfg(id=0x%x, value_addr=0x%x)", id, value.GetAddr()); + + CPUThread* thr = Emu.GetCPU().GetThread(id); + + if(!thr || (thr->GetType() != CPU_THREAD_SPU && thr->GetType() != CPU_THREAD_RAW_SPU)) + { + return CELL_ESRCH; + } + + value = (*(SPUThread*)thr).cfg.value; + + return CELL_OK; +} + +//184 +int sys_spu_thread_write_snr(u32 id, u32 number, u32 value) +{ + CPUThread* thr = Emu.GetCPU().GetThread(id); + + if(!thr || (thr->GetType() != CPU_THREAD_SPU && thr->GetType() != CPU_THREAD_RAW_SPU)) + { + return CELL_ESRCH; + } + + if (number > 1) + { + return CELL_EINVAL; + } + + if ((*(SPUThread*)thr).cfg.value & ((u64)1< name_len; @@ -30,3 +32,11 @@ struct sys_spu_image be_t segs_addr; be_t nsegs; }; + +struct sys_spu_segment +{ + be_t type; + be_t ls_start; + be_t size; + be_t src; +}; diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index 368ac13a8e..3e79a860be 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -354,7 +354,6 @@ void Emulator::Load() thread.Run(); - wxCriticalSectionLocker lock(m_cs_status); m_status = Ready; #ifndef QT_UI wxGetApp().SendDbgCommand(DID_READY_EMU); @@ -379,7 +378,6 @@ void Emulator::Run() wxGetApp().SendDbgCommand(DID_START_EMU); #endif - wxCriticalSectionLocker lock(m_cs_status); //ConLog.Write("run..."); m_status = Running; @@ -403,7 +401,6 @@ void Emulator::Pause() wxGetApp().SendDbgCommand(DID_PAUSE_EMU); #endif - wxCriticalSectionLocker lock(m_cs_status); m_status = Paused; #ifndef QT_UI wxGetApp().SendDbgCommand(DID_PAUSED_EMU); @@ -418,7 +415,6 @@ void Emulator::Resume() wxGetApp().SendDbgCommand(DID_RESUME_EMU); #endif - wxCriticalSectionLocker lock(m_cs_status); m_status = Running; CheckStatus(); @@ -436,10 +432,7 @@ void Emulator::Stop() #ifndef QT_UI wxGetApp().SendDbgCommand(DID_STOP_EMU); #endif - { - wxCriticalSectionLocker lock(m_cs_status); - m_status = Stopped; - } + m_status = Stopped; m_rsx_callback = 0; diff --git a/rpcs3/Emu/System.h b/rpcs3/Emu/System.h index 04da0a30e8..78b9146937 100644 --- a/rpcs3/Emu/System.h +++ b/rpcs3/Emu/System.h @@ -1,5 +1,6 @@ #pragma once +#include #include "Gui/MemoryViewer.h" #include "Emu/CPU/CPUThreadManager.h" #include "Emu/Io/Pad.h" @@ -64,9 +65,8 @@ class Emulator InterpreterDisAsm, Interpreter, }; - - mutable wxCriticalSection m_cs_status; - Status m_status; + + volatile uint m_status; uint m_mode; u32 m_rsx_callback; @@ -159,10 +159,10 @@ public: void SavePoints(const std::string& path); void LoadPoints(const std::string& path); - __forceinline bool IsRunning() const { wxCriticalSectionLocker lock(m_cs_status); return m_status == Running; } - __forceinline bool IsPaused() const { wxCriticalSectionLocker lock(m_cs_status); return m_status == Paused; } - __forceinline bool IsStopped() const { wxCriticalSectionLocker lock(m_cs_status); return m_status == Stopped; } - __forceinline bool IsReady() const { wxCriticalSectionLocker lock(m_cs_status); return m_status == Ready; } + __forceinline bool IsRunning() const { return m_status == Running; } + __forceinline bool IsPaused() const { return m_status == Paused; } + __forceinline bool IsStopped() const { return m_status == Stopped; } + __forceinline bool IsReady() const { return m_status == Ready; } }; extern Emulator Emu; \ No newline at end of file diff --git a/rpcs3/git-version.h b/rpcs3/git-version.h index 07a3d127dd..f770897486 100644 --- a/rpcs3/git-version.h +++ b/rpcs3/git-version.h @@ -1,6 +1,6 @@ // This is a generated file. -#define RPCS3_GIT_VERSION "d83a9b1" +#define RPCS3_GIT_VERSION "unknown" // If you don't want this file to update/recompile, change to 1. -#define RPCS3_GIT_VERSION_NO_UPDATE 0 +#define RPCS3_GIT_VERSION_NO_UPDATE 1