From 0b35be32a43b575e16a43e50a385841dc0a58e1a Mon Sep 17 00:00:00 2001 From: DH Date: Sun, 3 Nov 2013 21:23:16 +0200 Subject: [PATCH] - Implemented ARM9Thread. - Improved OpenGL Renderer. - Improved RAW SPU mfc. --- rpcs3/Emu/ARM9/ARM9Thread.cpp | 69 ++ rpcs3/Emu/ARM9/ARM9Thread.h | 30 + rpcs3/Emu/CPU/CPUDecoder.h | 873 +++++++++++++++++++++++ rpcs3/Emu/CPU/CPUDisAsm.h | 63 ++ rpcs3/Emu/CPU/CPUInstrTable.h | 34 + rpcs3/Emu/CPU/CPUThread.cpp | 311 ++++++++ rpcs3/Emu/CPU/CPUThread.h | 183 +++++ rpcs3/Emu/CPU/CPUThreadManager.cpp | 111 +++ rpcs3/Emu/CPU/CPUThreadManager.h | 27 + rpcs3/Emu/Cell/PPCDecoder.h | 873 +---------------------- rpcs3/Emu/Cell/PPCDisAsm.h | 74 +- rpcs3/Emu/Cell/PPCInstrTable.h | 34 +- rpcs3/Emu/Cell/PPCThread.cpp | 351 +-------- rpcs3/Emu/Cell/PPCThread.h | 164 +---- rpcs3/Emu/Cell/PPUDecoder.h | 9 +- rpcs3/Emu/Cell/PPUDisAsm.h | 260 ++++++- rpcs3/Emu/Cell/PPUInstrTable.h | 20 +- rpcs3/Emu/Cell/PPUInterpreter.h | 6 +- rpcs3/Emu/Cell/PPUOpcodes.h | 4 +- rpcs3/Emu/Cell/PPUProgramCompiler.cpp | 12 +- rpcs3/Emu/Cell/PPUThread.cpp | 38 +- rpcs3/Emu/Cell/PPUThread.h | 10 +- rpcs3/Emu/Cell/RawSPUThread.cpp | 298 ++++++-- rpcs3/Emu/Cell/RawSPUThread.h | 32 +- rpcs3/Emu/Cell/SPUDecoder.h | 9 +- rpcs3/Emu/Cell/SPUDisAsm.h | 32 +- rpcs3/Emu/Cell/SPUInstrTable.h | 6 +- rpcs3/Emu/Cell/SPUInterpreter.h | 6 +- rpcs3/Emu/Cell/SPUOpcodes.h | 4 +- rpcs3/Emu/Cell/SPUThread.cpp | 31 +- rpcs3/Emu/Cell/SPUThread.h | 138 +++- rpcs3/Emu/GS/GL/FragmentProgram.cpp | 39 +- rpcs3/Emu/GS/GL/FragmentProgram.h | 2 + rpcs3/Emu/GS/GL/GLBuffers.cpp | 24 +- rpcs3/Emu/GS/GL/GLBuffers.h | 5 +- rpcs3/Emu/GS/GL/GLGSRender.cpp | 469 ++++++++---- rpcs3/Emu/GS/GL/GLGSRender.h | 127 +++- rpcs3/Emu/GS/GL/GLProcTable.tbl | 8 +- rpcs3/Emu/GS/GL/VertexProgram.cpp | 12 +- rpcs3/Emu/GS/RSXThread.h | 48 +- rpcs3/Emu/Memory/Memory.cpp | 106 +-- rpcs3/Emu/Memory/Memory.h | 41 +- rpcs3/Emu/SysCalls/Callback.cpp | 4 +- rpcs3/Emu/SysCalls/FuncList.cpp | 89 +-- rpcs3/Emu/SysCalls/SysCalls.cpp | 9 +- rpcs3/Emu/SysCalls/SysCalls.h | 24 +- rpcs3/Emu/SysCalls/lv2/SC_Event.cpp | 8 +- rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp | 2 +- rpcs3/Emu/SysCalls/lv2/SC_PPU_Thread.cpp | 16 +- rpcs3/Emu/SysCalls/lv2/SC_Process.cpp | 14 +- rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp | 38 +- rpcs3/Emu/System.cpp | 50 +- rpcs3/Emu/System.h | 6 +- rpcs3/Emu/event.h | 2 +- rpcs3/Gui/DisAsmFrame.cpp | 39 +- rpcs3/Gui/InstructionEditor.cpp | 8 +- rpcs3/Gui/InterpreterDisAsm.cpp | 19 +- rpcs3/Gui/InterpreterDisAsm.h | 4 +- rpcs3/Gui/RegisterEditor.cpp | 33 +- rpcs3/Loader/Loader.cpp | 42 +- rpcs3/Loader/Loader.h | 13 +- rpcs3/rpcs3.cpp | 2 +- rpcs3/rpcs3.h | 2 +- rpcs3/rpcs3.vcxproj | 9 +- rpcs3/rpcs3.vcxproj.filters | 36 +- 65 files changed, 3255 insertions(+), 2207 deletions(-) create mode 100644 rpcs3/Emu/ARM9/ARM9Thread.cpp create mode 100644 rpcs3/Emu/ARM9/ARM9Thread.h create mode 100644 rpcs3/Emu/CPU/CPUDecoder.h create mode 100644 rpcs3/Emu/CPU/CPUDisAsm.h create mode 100644 rpcs3/Emu/CPU/CPUInstrTable.h create mode 100644 rpcs3/Emu/CPU/CPUThread.cpp create mode 100644 rpcs3/Emu/CPU/CPUThread.h create mode 100644 rpcs3/Emu/CPU/CPUThreadManager.cpp create mode 100644 rpcs3/Emu/CPU/CPUThreadManager.h diff --git a/rpcs3/Emu/ARM9/ARM9Thread.cpp b/rpcs3/Emu/ARM9/ARM9Thread.cpp new file mode 100644 index 0000000000..9d2ea4c069 --- /dev/null +++ b/rpcs3/Emu/ARM9/ARM9Thread.cpp @@ -0,0 +1,69 @@ +#include "stdafx.h" +#include "ARM9Thread.h" + +ARM9Thread::ARM9Thread() : CPUThread(CPU_THREAD_ARM9) +{ +} + +void ARM9Thread::InitRegs() +{ +} + +void ARM9Thread::InitStack() +{ +} + +u64 ARM9Thread::GetFreeStackSize() const +{ + return GetStackSize() - m_stack_point; +} + +void ARM9Thread::SetArg(const uint pos, const u64 arg) +{ + assert(0); +} + +void ARM9Thread::SetPc(const u64 pc) +{ + PC = pc; + nPC = pc + 2; +} + +wxString ARM9Thread::RegsToString() +{ + return wxEmptyString; +} + +wxString ARM9Thread::ReadRegString(wxString reg) +{ + return wxEmptyString; +} + +bool ARM9Thread::WriteRegString(wxString reg, wxString value) +{ + return true; +} + +void ARM9Thread::DoReset() +{ +} + +void ARM9Thread::DoRun() +{ +} + +void ARM9Thread::DoPause() +{ +} + +void ARM9Thread::DoResume() +{ +} + +void ARM9Thread::DoStop() +{ +} + +void ARM9Thread::DoCode() +{ +} \ No newline at end of file diff --git a/rpcs3/Emu/ARM9/ARM9Thread.h b/rpcs3/Emu/ARM9/ARM9Thread.h new file mode 100644 index 0000000000..466f7149f7 --- /dev/null +++ b/rpcs3/Emu/ARM9/ARM9Thread.h @@ -0,0 +1,30 @@ +#pragma once +#include "Emu\CPU\CPUThread.h" + +class ARM9Thread : public CPUThread +{ +public: + ARM9Thread(); + +public: + virtual void InitRegs(); + virtual void InitStack(); + virtual u64 GetFreeStackSize() const; + virtual void SetArg(const uint pos, const u64 arg); + +public: + virtual void SetPc(const u64 pc); + + virtual wxString RegsToString(); + virtual wxString ReadRegString(wxString reg); + virtual bool WriteRegString(wxString reg, wxString value); + +protected: + virtual void DoReset(); + virtual void DoRun(); + virtual void DoPause(); + virtual void DoResume(); + virtual void DoStop(); + + virtual void DoCode(); +}; \ No newline at end of file diff --git a/rpcs3/Emu/CPU/CPUDecoder.h b/rpcs3/Emu/CPU/CPUDecoder.h new file mode 100644 index 0000000000..2bb1b640cb --- /dev/null +++ b/rpcs3/Emu/CPU/CPUDecoder.h @@ -0,0 +1,873 @@ +#pragma once +#include "CPUInstrTable.h" +#pragma warning( disable : 4800 ) + +template +class InstrCaller +{ +public: + virtual ~InstrCaller() + { + } + + virtual void operator ()(TO* op, u32 code) const = 0; + + virtual u32 operator [](u32) const + { + return 0; + } +}; + +template +class InstrBinder_0 : public InstrCaller +{ + typedef void (TO::*func_t)(); + func_t m_func; + +public: + InstrBinder_0(func_t func) + : InstrCaller() + , m_func(func) + { + } + + virtual void operator ()(TO* op, u32 code) const + { + (op->*m_func)(); + } +}; + +template +class InstrBinder_1 : public InstrCaller +{ + typedef void (TO::*func_t)(T1); + func_t m_func; + const CodeFieldBase& m_arg_func_1; + +public: + InstrBinder_1(func_t func, const CodeFieldBase& arg_func_1) + : InstrCaller() + , m_func(func) + , m_arg_func_1(arg_func_1) + { + } + + virtual void operator ()(TO* op, u32 code) const + { + (op->*m_func)((T1)m_arg_func_1(code)); + } +}; + +template +class InstrBinder_2 : public InstrCaller +{ + typedef void (TO::*func_t)(T1, T2); + func_t m_func; + const CodeFieldBase& m_arg_func_1; + const CodeFieldBase& m_arg_func_2; + +public: + InstrBinder_2(func_t func, const CodeFieldBase& arg_func_1, const CodeFieldBase& arg_func_2) + : InstrCaller() + , m_func(func) + , m_arg_func_1(arg_func_1) + , m_arg_func_2(arg_func_2) + { + } + + virtual void operator ()(TO* op, u32 code) const + { + (op->*m_func)( + (T1)m_arg_func_1(code), + (T2)m_arg_func_2(code) + ); + } +}; + +template +class InstrBinder_3 : public InstrCaller +{ + typedef void (TO::*func_t)(T1, T2, T3); + func_t m_func; + const CodeFieldBase& m_arg_func_1; + const CodeFieldBase& m_arg_func_2; + const CodeFieldBase& m_arg_func_3; + +public: + InstrBinder_3(func_t func, + const CodeFieldBase& arg_func_1, + const CodeFieldBase& arg_func_2, + const CodeFieldBase& arg_func_3) + : InstrCaller() + , m_func(func) + , m_arg_func_1(arg_func_1) + , m_arg_func_2(arg_func_2) + , m_arg_func_3(arg_func_3) + { + } + + virtual void operator ()(TO* op, u32 code) const + { + (op->*m_func)( + (T1)m_arg_func_1(code), + (T2)m_arg_func_2(code), + (T3)m_arg_func_3(code) + ); + } +}; + +template +class InstrBinder_4 : public InstrCaller +{ + typedef void (TO::*func_t)(T1, T2, T3, T4); + func_t m_func; + const CodeFieldBase& m_arg_func_1; + const CodeFieldBase& m_arg_func_2; + const CodeFieldBase& m_arg_func_3; + const CodeFieldBase& m_arg_func_4; + +public: + InstrBinder_4(func_t func, + const CodeFieldBase& arg_func_1, + const CodeFieldBase& arg_func_2, + const CodeFieldBase& arg_func_3, + const CodeFieldBase& arg_func_4) + : InstrCaller() + , m_func(func) + , m_arg_func_1(arg_func_1) + , m_arg_func_2(arg_func_2) + , m_arg_func_3(arg_func_3) + , m_arg_func_4(arg_func_4) + { + } + + virtual void operator ()(TO* op, u32 code) const + { + (op->*m_func)( + (T1)m_arg_func_1(code), + (T2)m_arg_func_2(code), + (T3)m_arg_func_3(code), + (T4)m_arg_func_4(code) + ); + } +}; + +template +class InstrBinder_5 : public InstrCaller +{ + typedef void (TO::*func_t)(T1, T2, T3, T4, T5); + func_t m_func; + const CodeFieldBase& m_arg_func_1; + const CodeFieldBase& m_arg_func_2; + const CodeFieldBase& m_arg_func_3; + const CodeFieldBase& m_arg_func_4; + const CodeFieldBase& m_arg_func_5; + +public: + InstrBinder_5(func_t func, + const CodeFieldBase& arg_func_1, + const CodeFieldBase& arg_func_2, + const CodeFieldBase& arg_func_3, + const CodeFieldBase& arg_func_4, + const CodeFieldBase& arg_func_5) + : InstrCaller() + , m_func(func) + , m_arg_func_1(arg_func_1) + , m_arg_func_2(arg_func_2) + , m_arg_func_3(arg_func_3) + , m_arg_func_4(arg_func_4) + , m_arg_func_5(arg_func_5) + { + } + + virtual void operator ()(TO* op, u32 code) const + { + (op->*m_func)( + (T1)m_arg_func_1(code), + (T2)m_arg_func_2(code), + (T3)m_arg_func_3(code), + (T4)m_arg_func_4(code), + (T5)m_arg_func_5(code) + ); + } +}; + +template +class InstrBinder_6 : public InstrCaller +{ + typedef void (TO::*func_t)(T1, T2, T3, T4, T5, T6); + func_t m_func; + const CodeFieldBase& m_arg_func_1; + const CodeFieldBase& m_arg_func_2; + const CodeFieldBase& m_arg_func_3; + const CodeFieldBase& m_arg_func_4; + const CodeFieldBase& m_arg_func_5; + const CodeFieldBase& m_arg_func_6; + +public: + InstrBinder_6(func_t func, + const CodeFieldBase& arg_func_1, + const CodeFieldBase& arg_func_2, + const CodeFieldBase& arg_func_3, + const CodeFieldBase& arg_func_4, + const CodeFieldBase& arg_func_5, + const CodeFieldBase& arg_func_6) + : InstrCaller() + , m_func(func) + , m_arg_func_1(arg_func_1) + , m_arg_func_2(arg_func_2) + , m_arg_func_3(arg_func_3) + , m_arg_func_4(arg_func_4) + , m_arg_func_5(arg_func_5) + , m_arg_func_6(arg_func_6) + { + } + + virtual void operator ()(TO* op, u32 code) const + { + (op->*m_func)( + (T1)m_arg_func_1(code), + (T2)m_arg_func_2(code), + (T3)m_arg_func_3(code), + (T4)m_arg_func_4(code), + (T5)m_arg_func_5(code), + (T6)m_arg_func_6(code) + ); + } +}; + +template +InstrCaller* instr_bind(void (TO::*func)()) +{ + return new InstrBinder_0(func); +} + +template +InstrCaller* instr_bind(void (TO::*func)(T1), const CodeFieldBase& arg_func_1) +{ + return new InstrBinder_1(func, arg_func_1); +} + +template +InstrCaller* instr_bind(void (TO::*func)(T1, T2), + const CodeFieldBase& arg_func_1, + const CodeFieldBase& arg_func_2) +{ + return new InstrBinder_2(func, arg_func_1, arg_func_2); +} + +template +InstrCaller* instr_bind(void (TO::*func)(T1, T2, T3), + const CodeFieldBase& arg_func_1, + const CodeFieldBase& arg_func_2, + const CodeFieldBase& arg_func_3) +{ + return new InstrBinder_3(func, arg_func_1, arg_func_2, arg_func_3); +} + +template +InstrCaller* instr_bind(void (TO::*func)(T1, T2, T3, T4), + const CodeFieldBase& arg_func_1, + const CodeFieldBase& arg_func_2, + const CodeFieldBase& arg_func_3, + const CodeFieldBase& arg_func_4) +{ + return new InstrBinder_4(func, arg_func_1, arg_func_2, arg_func_3, arg_func_4); +} + +template +InstrCaller* instr_bind(void (TO::*func)(T1, T2, T3, T4, T5), + const CodeFieldBase& arg_func_1, + const CodeFieldBase& arg_func_2, + const CodeFieldBase& arg_func_3, + const CodeFieldBase& arg_func_4, + const CodeFieldBase& arg_func_5) +{ + return new InstrBinder_5(func, arg_func_1, arg_func_2, arg_func_3, arg_func_4, arg_func_5); +} + +template +InstrCaller* instr_bind(void (TO::*func)(T1, T2, T3, T4, T5, T6), + const CodeFieldBase& arg_func_1, + const CodeFieldBase& arg_func_2, + const CodeFieldBase& arg_func_3, + const CodeFieldBase& arg_func_4, + const CodeFieldBase& arg_func_5, + const CodeFieldBase& arg_func_6) +{ + return new InstrBinder_6(func, arg_func_1, arg_func_2, arg_func_3, arg_func_4, arg_func_5, arg_func_6); +} + +template +class InstrBase : public InstrCaller +{ +protected: + wxString m_name; + const u32 m_opcode; + CodeFieldBase** m_args; + const uint m_args_count; + +public: + InstrBase(const wxString& name, int opcode, uint args_count) + : InstrCaller() + , m_name(name) + , m_opcode(opcode) + , m_args_count(args_count) + , m_args(args_count ? new CodeFieldBase*[args_count] : nullptr) + { + m_name.MakeLower().Replace("_", "."); + } + + __forceinline const wxString& GetName() const + { + return m_name; + } + + __forceinline const uint GetArgCount() const + { + return m_args_count; + } + + __forceinline const CodeFieldBase& GetArg(uint index) const + { + assert(index < m_args_count); + return *m_args[index]; + } + + void operator ()(TO* op, u32 code) const + { + decode(op, code); + } + + u32 operator()(const Array& args) const + { + return encode(args); + } + + virtual void decode(TO* op, u32 code) const=0; + virtual u32 encode(const Array& args) const=0; +}; + +template +class InstrList : public InstrCaller +{ +public: + static const int count = _count; + +protected: + const CodeFieldBase& m_func; + InstrCaller* m_instrs[count]; + InstrBase* m_instrs_info[count]; + InstrCaller* m_error_func; + InstrCaller* m_parent; + int m_opcode; + +public: + InstrList(const CodeFieldBase& func, InstrCaller* error_func) + : InstrCaller() + , m_func(func) + , m_error_func(error_func) + , m_parent(nullptr) + , m_opcode(-1) + { + for(int i=0; i*) * count); + } + + virtual ~InstrList() + { + for(int i=0; i* parent, int opcode) + { + m_opcode = opcode; + m_parent = parent; + } + + InstrCaller* get_parent() const + { + return m_parent; + } + + u32 get_opcode() const + { + return m_opcode; + } + + void set_error_func(InstrCaller* error_func) + { + for(int i=0; i* func, InstrBase* info = nullptr) + { + assert(pos < count); + m_instrs[pos] = func; + m_instrs_info[pos] = info; + } + + InstrCaller* get_instr(int pos) const + { + assert(pos < count); + return m_instrs[pos]; + } + + InstrBase* get_instr_info(int pos) const + { + assert(pos < count); + return m_instrs_info[pos]; + } + + u32 encode(u32 entry) const + { + return m_func[entry] | (m_parent ? (*m_parent)[m_opcode] : 0); + } + + void decode(TO* op, u32 entry, u32 code) const + { + (*m_instrs[entry])(op, code); + } + + virtual void operator ()(TO* op, u32 code) const + { + decode(op, m_func(code) & (count - 1), code); + } + + virtual u32 operator [](u32 entry) const + { + return encode(entry); + } +}; + +template +static InstrList* connect_list(InstrList* parent, InstrList* child, int opcode) +{ + parent->set_instr(opcode, child); + child->set_parent(parent, opcode); + return child; +} + +template +static InstrList* connect_list(InstrList* parent, InstrList* child) +{ + parent->set_error_func(child); + child->set_parent(parent->get_parent(), parent->get_opcode()); + return child; +} + +template +class Instr0 : public InstrBase +{ + InstrList& m_list; + +public: + Instr0(InstrList* list, const wxString& name, + void (TO::*func)()) + : InstrBase(name, opcode, 0) + , m_list(*list) + { + m_list.set_instr(opcode, instr_bind(func), this); + } + + virtual void decode(TO* op, u32 code) const + { + m_list.decode(op, opcode, code); + } + + virtual u32 encode(const Array& args) const + { + assert(args.GetCount() == m_args_count); + return m_list.encode(opcode); + } + + u32 encode() const + { + return m_list.encode(opcode); + } + + u32 operator()() const + { + return encode(); + } +}; + +template +class Instr1 : public InstrBase +{ + InstrList& m_list; + +public: + Instr1(InstrList* list, const wxString& name, + void (TO::*func)(T1), + CodeFieldBase& arg_1) + : InstrBase(name, opcode, 1) + , m_list(*list) + { + m_args[0] = &arg_1; + + m_list.set_instr(opcode, instr_bind(func, arg_1), this); + } + + virtual void decode(TO* op, u32 code) const + { + m_list.decode(op, opcode, code); + } + + virtual u32 encode(const Array& args) const + { + assert(args.GetCount() == m_args_count); + return m_list.encode(opcode) | (*m_args[0])[args[0]]; + } + + u32 encode(T1 a1) const + { + return m_list.encode(opcode) | (*m_args[0])[a1]; + } + + u32 operator()(T1 a1) const + { + return encode(a1); + } +}; + +template +class Instr2 : public InstrBase +{ + InstrList& m_list; + +public: + Instr2(InstrList* list, const wxString& name, + void (TO::*func)(T1, T2), + CodeFieldBase& arg_1, + CodeFieldBase& arg_2) + : InstrBase(name, opcode, 2) + , m_list(*list) + { + m_args[0] = &arg_1; + m_args[1] = &arg_2; + + m_list.set_instr(opcode, instr_bind(func, arg_1, arg_2), this); + } + + virtual void decode(TO* op, u32 code) const + { + m_list.decode(op, opcode, code); + } + + virtual u32 encode(const Array& args) const + { + assert(args.GetCount() == m_args_count); + return m_list.encode(opcode) | (*m_args[0])[args[0]] | (*m_args[1])[args[1]]; + } + + u32 encode(T1 a1, T2 a2) const + { + return m_list.encode(opcode) | (*m_args[0])[a1] | (*m_args[1])[a2]; + } + + u32 operator()(T1 a1, T2 a2) const + { + return encode(a1, a2); + } +}; + +template +class Instr3 : public InstrBase +{ + InstrList& m_list; + +public: + Instr3(InstrList* list, const wxString& name, + void (TO::*func)(T1, T2, T3), + CodeFieldBase& arg_1, + CodeFieldBase& arg_2, + CodeFieldBase& arg_3) + : InstrBase(name, opcode, 3) + , m_list(*list) + { + m_args[0] = &arg_1; + m_args[1] = &arg_2; + m_args[2] = &arg_3; + + m_list.set_instr(opcode, instr_bind(func, arg_1, arg_2, arg_3), this); + } + + virtual void decode(TO* op, u32 code) const + { + m_list.decode(op, opcode, code); + } + + virtual u32 encode(const Array& args) const + { + assert(args.GetCount() == m_args_count); + return m_list.encode(opcode) | (*m_args[0])[args[0]] | (*m_args[1])[args[1]] | (*m_args[2])[args[2]]; + } + + u32 encode(T1 a1, T2 a2, T3 a3) const + { + return m_list.encode(opcode) | (*m_args[0])[a1] | (*m_args[1])[a2] | (*m_args[2])[a3]; + } + + u32 operator()(T1 a1, T2 a2, T3 a3) const + { + return encode(a1, a2, a3); + } +}; + +template +class Instr4 : public InstrBase +{ + InstrList& m_list; + +public: + Instr4(InstrList* list, const wxString& name, + void (TO::*func)(T1, T2, T3, T4), + CodeFieldBase& arg_1, + CodeFieldBase& arg_2, + CodeFieldBase& arg_3, + CodeFieldBase& arg_4) + : InstrBase(name, opcode, 4) + , m_list(*list) + { + m_args[0] = &arg_1; + m_args[1] = &arg_2; + m_args[2] = &arg_3; + m_args[3] = &arg_4; + + m_list.set_instr(opcode, instr_bind(func, arg_1, arg_2, arg_3, arg_4), this); + } + + virtual void decode(TO* op, u32 code) const + { + m_list.decode(op, opcode, code); + } + + virtual u32 encode(const Array& args) const + { + assert(args.GetCount() == m_args_count); + return m_list.encode(opcode) | + (*m_args[0])[args[0]] | + (*m_args[1])[args[1]] | + (*m_args[2])[args[2]] | + (*m_args[3])[args[3]]; + } + + u32 encode(T1 a1, T2 a2, T3 a3, T4 a4) const + { + return m_list.encode(opcode) | + (*m_args[0])[a1] | + (*m_args[1])[a2] | + (*m_args[2])[a3] | + (*m_args[3])[a4]; + } + + u32 operator()(T1 a1, T2 a2, T3 a3, T4 a4) const + { + return encode(a1, a2, a3, a4); + } +}; + +template +class Instr5 : public InstrBase +{ + InstrList& m_list; + +public: + Instr5(InstrList* list, const wxString& name, + void (TO::*func)(T1, T2, T3, T4, T5), + CodeFieldBase& arg_1, + CodeFieldBase& arg_2, + CodeFieldBase& arg_3, + CodeFieldBase& arg_4, + CodeFieldBase& arg_5) + : InstrBase(name, opcode, 5) + , m_list(*list) + { + m_args[0] = &arg_1; + m_args[1] = &arg_2; + m_args[2] = &arg_3; + m_args[3] = &arg_4; + m_args[4] = &arg_5; + + m_list.set_instr(opcode, instr_bind(func, arg_1, arg_2, arg_3, arg_4, arg_5), this); + } + + virtual void decode(TO* op, u32 code) const + { + m_list.decode(op, opcode, code); + } + + virtual u32 encode(const Array& args) const + { + assert(args.GetCount() == m_args_count); + return m_list.encode(opcode) | + (*m_args[0])[args[0]] | + (*m_args[1])[args[1]] | + (*m_args[2])[args[2]] | + (*m_args[3])[args[3]] | + (*m_args[4])[args[4]]; + } + + u32 encode(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) const + { + return m_list.encode(opcode) | + (*m_args[0])[a1] | + (*m_args[1])[a2] | + (*m_args[2])[a3] | + (*m_args[3])[a4] | + (*m_args[4])[a5]; + } + + u32 operator()(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) const + { + return encode(a1, a2, a3, a4, a5); + } +}; + +template +class Instr6 : public InstrBase +{ + InstrList& m_list; + +public: + Instr6(InstrList* list, const wxString& name, + void (TO::*func)(T1, T2, T3, T4, T5, T6), + CodeFieldBase& arg_1, + CodeFieldBase& arg_2, + CodeFieldBase& arg_3, + CodeFieldBase& arg_4, + CodeFieldBase& arg_5, + CodeFieldBase& arg_6) + : InstrBase(name, opcode, 6) + , m_list(*list) + { + m_args[0] = &arg_1; + m_args[1] = &arg_2; + m_args[2] = &arg_3; + m_args[3] = &arg_4; + m_args[4] = &arg_5; + m_args[5] = &arg_6; + + m_list.set_instr(opcode, instr_bind(func, arg_1, arg_2, arg_3, arg_4, arg_5, arg_6), this); + } + + virtual void decode(TO* op, u32 code) const + { + m_list.decode(op, opcode, code); + } + + virtual u32 encode(const Array& args) const + { + assert(args.GetCount() == m_args_count); + return m_list.encode(opcode) | + (*m_args[0])[args[0]] | + (*m_args[1])[args[1]] | + (*m_args[2])[args[2]] | + (*m_args[3])[args[3]] | + (*m_args[4])[args[4]] | + (*m_args[5])[args[5]]; + } + + u32 encode(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T5 a6) const + { + return m_list.encode(opcode) | + (*m_args[0])[a1] | + (*m_args[1])[a2] | + (*m_args[2])[a3] | + (*m_args[3])[a4] | + (*m_args[4])[a5] | + (*m_args[5])[a6]; + } + + u32 operator()(T1 a1, T2 a2, T3 a3, T4 a4, T4 a5, T4 a6) const + { + return encode(a1, a2, a3, a4, a5, a6); + } +}; + +template +static Instr0& make_instr(InstrList* list, const wxString& name, void (TO::*func)()) +{ + return *new Instr0(list, name, func); +} + +template +static Instr1& make_instr(InstrList* list, const wxString& name, + void (TO::*func)(T1), + CodeFieldBase& arg_1) +{ + return *new Instr1(list, name, func, arg_1); +} + +template +static Instr2& make_instr(InstrList* list, const wxString& name, + void (TO::*func)(T1, T2), + CodeFieldBase& arg_1, + CodeFieldBase& arg_2) +{ + return *new Instr2(list, name, func, arg_1, arg_2); +} + +template +static Instr3& make_instr(InstrList* list, const wxString& name, + void (TO::*func)(T1, T2, T3), + CodeFieldBase& arg_1, + CodeFieldBase& arg_2, + CodeFieldBase& arg_3) +{ + return *new Instr3(list, name, func, arg_1, arg_2, arg_3); +} + +template +static Instr4& make_instr(InstrList* list, const wxString& name, + void (TO::*func)(T1, T2, T3, T4), + CodeFieldBase& arg_1, + CodeFieldBase& arg_2, + CodeFieldBase& arg_3, + CodeFieldBase& arg_4) +{ + return *new Instr4(list, name, func, arg_1, arg_2, arg_3, arg_4); +} + +template +static Instr5& make_instr(InstrList* list, const wxString& name, + void (TO::*func)(T1, T2, T3, T4, T5), + CodeFieldBase& arg_1, + CodeFieldBase& arg_2, + CodeFieldBase& arg_3, + CodeFieldBase& arg_4, + CodeFieldBase& arg_5) +{ + return *new Instr5(list, name, func, arg_1, arg_2, arg_3, arg_4, arg_5); +} + +template +static Instr6& make_instr(InstrList* list, const wxString& name, + void (TO::*func)(T1, T2, T3, T4, T5, T6), + CodeFieldBase& arg_1, + CodeFieldBase& arg_2, + CodeFieldBase& arg_3, + CodeFieldBase& arg_4, + CodeFieldBase& arg_5, + CodeFieldBase& arg_6) +{ + return *new Instr6(list, name, func, arg_1, arg_2, arg_3, arg_4, arg_5, arg_6); +} \ No newline at end of file diff --git a/rpcs3/Emu/CPU/CPUDisAsm.h b/rpcs3/Emu/CPU/CPUDisAsm.h new file mode 100644 index 0000000000..139dd3f1d0 --- /dev/null +++ b/rpcs3/Emu/CPU/CPUDisAsm.h @@ -0,0 +1,63 @@ +#pragma once + +#include "Emu/Memory/Memory.h" + +enum CPUDisAsmMode +{ + CPUDisAsm_DumpMode, + CPUDisAsm_InterpreterMode, + //CPUDisAsm_NormalMode, + CPUDisAsm_CompilerElfMode, +}; + +class CPUDisAsm +{ +protected: + const CPUDisAsmMode m_mode; + + virtual void Write(const wxString& value) + { + switch(m_mode) + { + case CPUDisAsm_DumpMode: + last_opcode = wxString::Format("\t%08llx:\t%02x %02x %02x %02x\t%s\n", dump_pc, + Memory.Read8(offset + dump_pc), + Memory.Read8(offset + dump_pc + 1), + Memory.Read8(offset + dump_pc + 2), + Memory.Read8(offset + dump_pc + 3), value); + break; + + case CPUDisAsm_InterpreterMode: + last_opcode = wxString::Format("[%08llx] %02x %02x %02x %02x: %s", dump_pc, + Memory.Read8(offset + dump_pc), + Memory.Read8(offset + dump_pc + 1), + Memory.Read8(offset + dump_pc + 2), + Memory.Read8(offset + dump_pc + 3), value); + break; + + case CPUDisAsm_CompilerElfMode: + last_opcode = value + "\n"; + break; + } + } + +public: + wxString last_opcode; + u64 dump_pc; + u64 offset; + +protected: + CPUDisAsm(CPUDisAsmMode mode) + : m_mode(mode) + , offset(0) + { + } + + virtual u32 DisAsmBranchTarget(const s32 imm)=0; + + wxString FixOp(wxString op) + { + op.Append(' ', max(8 - op.Len(), 0)); + return op; + } +}; \ No newline at end of file diff --git a/rpcs3/Emu/CPU/CPUInstrTable.h b/rpcs3/Emu/CPU/CPUInstrTable.h new file mode 100644 index 0000000000..1ec101a875 --- /dev/null +++ b/rpcs3/Emu/CPU/CPUInstrTable.h @@ -0,0 +1,34 @@ +#pragma once + +template __forceinline static T sign(const T value) +{ + static_assert(size > 0 && size < sizeof(T) * 8, "Bad sign size"); + + if(value & (T(1) << (size - 1))) + { + return value - (T(1) << size); + } + + return value; +} + +class CodeFieldBase +{ +public: + u32 m_type; + +public: + CodeFieldBase(u32 type) : m_type(type) + { + } + + virtual u32 operator ()(u32 data) const=0; + virtual void operator()(u32& data, u32 value) const=0; + + virtual u32 operator[](u32 value) const + { + u32 result = 0; + (*this)(result, value); + return result; + } +}; diff --git a/rpcs3/Emu/CPU/CPUThread.cpp b/rpcs3/Emu/CPU/CPUThread.cpp new file mode 100644 index 0000000000..a890c3a281 --- /dev/null +++ b/rpcs3/Emu/CPU/CPUThread.cpp @@ -0,0 +1,311 @@ +#include "stdafx.h" +#include "CPUThread.h" + +CPUThread* GetCurrentCPUThread() +{ + return (CPUThread*)GetCurrentNamedThread(); +} + +CPUThread::CPUThread(CPUThreadType type) + : ThreadBase(true, "CPUThread") + , m_type(type) + , m_stack_size(0) + , m_stack_addr(0) + , m_offset(0) + , m_prio(0) + , m_sync_wait(false) + , m_wait_thread_id(-1) + , m_free_data(false) +{ +} + +CPUThread::~CPUThread() +{ + Close(); +} + +void CPUThread::Close() +{ + if(IsAlive()) + { + m_free_data = true; + } + + Stop(); +} + +void CPUThread::Reset() +{ + CloseStack(); + + m_sync_wait = 0; + m_wait_thread_id = -1; + + SetPc(0); + cycle = 0; + + m_status = Stopped; + m_error = 0; + + DoReset(); +} + +void CPUThread::CloseStack() +{ + if(m_stack_addr) + { + Memory.Free(m_stack_addr); + m_stack_addr = 0; + } + + m_stack_size = 0; + m_stack_point = 0; +} + +void CPUThread::SetId(const u32 id) +{ + m_id = id; +} + +void CPUThread::SetName(const wxString& name) +{ + m_name = name; +} + +void CPUThread::Wait(bool wait) +{ + wxCriticalSectionLocker lock(m_cs_sync); + m_sync_wait = wait; +} + +void CPUThread::Wait(const CPUThread& thr) +{ + wxCriticalSectionLocker lock(m_cs_sync); + m_wait_thread_id = thr.GetId(); + m_sync_wait = true; +} + +bool CPUThread::Sync() +{ + wxCriticalSectionLocker lock(m_cs_sync); + + return m_sync_wait; +} + +int CPUThread::ThreadStatus() +{ + if(m_is_step) + { + return CPUThread_Step; + } + + if(Emu.IsStopped()) + { + return CPUThread_Stopped; + } + + if(TestDestroy()) + { + return CPUThread_Break; + } + + if(Emu.IsPaused() || Sync()) + { + return CPUThread_Sleeping; + } + + return CPUThread_Running; +} + +void CPUThread::SetEntry(const u64 pc) +{ + entry = pc; +} + +void CPUThread::NextPc() +{ + SetPc(nPC); +} + +void CPUThread::SetBranch(const u64 pc) +{ + if(!Memory.IsGoodAddr(m_offset + pc)) + { + ConLog.Error("%s branch error: bad address 0x%llx #pc: 0x%llx", GetFName(), m_offset + pc, m_offset + PC); + Emu.Pause(); + } + + nPC = pc; +} + +void CPUThread::SetError(const u32 error) +{ + if(error == 0) + { + m_error = 0; + } + else + { + m_error |= error; + } +} + +wxArrayString CPUThread::ErrorToString(const u32 error) +{ + wxArrayString earr; + + if(error == 0) return earr; + + earr.Add("Unknown error"); + + return earr; +} + +void CPUThread::Run() +{ + if(IsRunning()) Stop(); + if(IsPaused()) + { + Resume(); + return; + } + + wxGetApp().SendDbgCommand(DID_START_THREAD, this); + + m_status = Running; + + SetPc(entry); + InitStack(); + InitRegs(); + DoRun(); + Emu.CheckStatus(); + + wxGetApp().SendDbgCommand(DID_STARTED_THREAD, this); +} + +void CPUThread::Resume() +{ + if(!IsPaused()) return; + + wxGetApp().SendDbgCommand(DID_RESUME_THREAD, this); + + m_status = Running; + DoResume(); + Emu.CheckStatus(); + + ThreadBase::Start(); + + wxGetApp().SendDbgCommand(DID_RESUMED_THREAD, this); +} + +void CPUThread::Pause() +{ + if(!IsRunning()) return; + + wxGetApp().SendDbgCommand(DID_PAUSE_THREAD, this); + + m_status = Paused; + DoPause(); + Emu.CheckStatus(); + + ThreadBase::Stop(false); + wxGetApp().SendDbgCommand(DID_PAUSED_THREAD, this); +} + +void CPUThread::Stop() +{ + if(IsStopped()) return; + + wxGetApp().SendDbgCommand(DID_STOP_THREAD, this); + + m_status = Stopped; + ThreadBase::Stop(false); + Reset(); + DoStop(); + Emu.CheckStatus(); + + wxGetApp().SendDbgCommand(DID_STOPED_THREAD, this); +} + +void CPUThread::Exec() +{ + m_is_step = false; + wxGetApp().SendDbgCommand(DID_EXEC_THREAD, this); + ThreadBase::Start(); +} + +void CPUThread::ExecOnce() +{ + m_is_step = true; + wxGetApp().SendDbgCommand(DID_EXEC_THREAD, this); + ThreadBase::Start(); + if(!ThreadBase::Wait()) while(m_is_step) Sleep(1); + wxGetApp().SendDbgCommand(DID_PAUSE_THREAD, this); + wxGetApp().SendDbgCommand(DID_PAUSED_THREAD, this); +} + +void CPUThread::Task() +{ + //ConLog.Write("%s enter", CPUThread::GetFName()); + + const Array& bp = Emu.GetBreakPoints(); + + try + { + for(uint i=0; i + void WaitFor(T func) + { + while(func(ThreadStatus())) + { + Sleep(1); + } + } + + int ThreadStatus(); + + virtual void NextPc(); + virtual void SetBranch(const u64 pc); + virtual void SetPc(const u64 pc) = 0; + virtual void SetEntry(const u64 entry); + + void SetError(const u32 error); + + static wxArrayString ErrorToString(const u32 error); + wxArrayString ErrorToString() { return ErrorToString(m_error); } + + bool IsOk() const { return m_error == 0; } + bool IsRunning() const { return m_status == Running; } + bool IsPaused() const { return m_status == Paused; } + bool IsStopped() const { return m_status == Stopped; } + + bool IsJoinable() const { return m_joinable; } + bool IsJoining() const { return m_joining; } + void SetJoinable(bool joinable) { m_joinable = joinable; } + void SetJoining(bool joining) { m_joining = joining; } + + u32 GetError() const { return m_error; } + u32 GetId() const { return m_id; } + CPUThreadType GetType() const { return m_type; } + + void Reset(); + void Close(); + void Run(); + void Pause(); + void Resume(); + void Stop(); + + virtual void AddArgv(const wxString& arg) {} + + virtual wxString RegsToString() = 0; + virtual wxString ReadRegString(wxString reg) = 0; + virtual bool WriteRegString(wxString reg, wxString value) = 0; + + virtual void Exec(); + void ExecOnce(); + +protected: + virtual void DoReset()=0; + virtual void DoRun()=0; + virtual void DoPause()=0; + virtual void DoResume()=0; + virtual void DoStop()=0; + +protected: + virtual void Task(); + virtual void DoCode() = 0; +}; + +CPUThread* GetCurrentCPUThread(); \ No newline at end of file diff --git a/rpcs3/Emu/CPU/CPUThreadManager.cpp b/rpcs3/Emu/CPU/CPUThreadManager.cpp new file mode 100644 index 0000000000..90ac8e9fc7 --- /dev/null +++ b/rpcs3/Emu/CPU/CPUThreadManager.cpp @@ -0,0 +1,111 @@ +#include "stdafx.h" +#include "CPUThreadManager.h" +#include "Emu\Cell\PPUThread.h" +#include "Emu\Cell\SPUThread.h" +#include "Emu\Cell\RawSPUThread.h" +#include "Emu\ARM9\ARM9Thread.h" + +CPUThreadManager::CPUThreadManager() + : m_raw_spu_num(0) +{ +} + +CPUThreadManager::~CPUThreadManager() +{ + Close(); +} + +void CPUThreadManager::Close() +{ + m_raw_spu_num = 0; + while(m_threads.GetCount()) RemoveThread(m_threads[0].GetId()); +} + +CPUThread& CPUThreadManager::AddThread(CPUThreadType type) +{ + std::lock_guard lock(m_mtx_thread); + + CPUThread* new_thread; + + switch(type) + { + case CPU_THREAD_PPU: new_thread = new PPUThread(); break; + case CPU_THREAD_SPU: new_thread = new SPUThread(); break; + case CPU_THREAD_RAW_SPU: new_thread = new RawSPUThread(m_raw_spu_num++); break; + case CPU_THREAD_ARM9: new_thread = new ARM9Thread(); break; + default: assert(0); + } + + new_thread->SetId(Emu.GetIdManager().GetNewID(wxString::Format("%s Thread", new_thread->GetTypeString()), new_thread)); + + m_threads.Add(new_thread); + wxGetApp().SendDbgCommand(DID_CREATE_THREAD, new_thread); + + return *new_thread; +} + +void CPUThreadManager::RemoveThread(const u32 id) +{ + std::lock_guard lock(m_mtx_thread); + + for(u32 i=0; iIsAlive()) + { + thr->Close(); + } + else + { + thr->Close(); + delete thr; + } + + + m_threads.RemoveFAt(i); + i--; + } + + Emu.GetIdManager().RemoveID(id, false); + Emu.CheckStatus(); +} + +s32 CPUThreadManager::GetThreadNumById(CPUThreadType type, u32 id) +{ + s32 num = 0; + + for(u32 i=0; i m_threads; + std::mutex m_mtx_thread; + wxSemaphore m_sem_task; + Stack m_delete_threads; + u32 m_raw_spu_num; + +public: + CPUThreadManager(); + ~CPUThreadManager(); + + void Close(); + + CPUThread& AddThread(CPUThreadType type); + void RemoveThread(const u32 id); + + ArrayF& GetThreads() { return m_threads; } + s32 GetThreadNumById(CPUThreadType type, u32 id); + CPUThread* GetThread(u32 id); + + void Exec(); + void Task(); +}; \ No newline at end of file diff --git a/rpcs3/Emu/Cell/PPCDecoder.h b/rpcs3/Emu/Cell/PPCDecoder.h index 68e7d6da72..9d1ad519fe 100644 --- a/rpcs3/Emu/Cell/PPCDecoder.h +++ b/rpcs3/Emu/Cell/PPCDecoder.h @@ -1,24 +1,8 @@ #pragma once +#include "Emu/CPU/CPUDecoder.h" #include "PPCInstrTable.h" -#pragma warning( disable : 4800 ) -template -class InstrCaller -{ -public: - virtual ~InstrCaller() - { - } - - virtual void operator ()(TO* op, u32 code) const = 0; - - virtual u32 operator [](u32) const - { - return 0; - } -}; - -class PPC_Decoder +class PPCDecoder { protected: u32 m_code; @@ -29,460 +13,6 @@ public: virtual void Decode(const u32 code)=0; }; -template -class InstrBinder_0 : public InstrCaller -{ - typedef void (TO::*func_t)(); - func_t m_func; - -public: - InstrBinder_0(func_t func) - : InstrCaller() - , m_func(func) - { - } - - virtual void operator ()(TO* op, u32 code) const - { - (op->*m_func)(); - } -}; - -template -class InstrBinder_1 : public InstrCaller -{ - typedef void (TO::*func_t)(T1); - func_t m_func; - const CodeFieldBase& m_arg_func_1; - -public: - InstrBinder_1(func_t func, const CodeFieldBase& arg_func_1) - : InstrCaller() - , m_func(func) - , m_arg_func_1(arg_func_1) - { - } - - virtual void operator ()(TO* op, u32 code) const - { - (op->*m_func)((T1)m_arg_func_1(code)); - } -}; - -template -class InstrBinder_2 : public InstrCaller -{ - typedef void (TO::*func_t)(T1, T2); - func_t m_func; - const CodeFieldBase& m_arg_func_1; - const CodeFieldBase& m_arg_func_2; - -public: - InstrBinder_2(func_t func, const CodeFieldBase& arg_func_1, const CodeFieldBase& arg_func_2) - : InstrCaller() - , m_func(func) - , m_arg_func_1(arg_func_1) - , m_arg_func_2(arg_func_2) - { - } - - virtual void operator ()(TO* op, u32 code) const - { - (op->*m_func)( - (T1)m_arg_func_1(code), - (T2)m_arg_func_2(code) - ); - } -}; - -template -class InstrBinder_3 : public InstrCaller -{ - typedef void (TO::*func_t)(T1, T2, T3); - func_t m_func; - const CodeFieldBase& m_arg_func_1; - const CodeFieldBase& m_arg_func_2; - const CodeFieldBase& m_arg_func_3; - -public: - InstrBinder_3(func_t func, - const CodeFieldBase& arg_func_1, - const CodeFieldBase& arg_func_2, - const CodeFieldBase& arg_func_3) - : InstrCaller() - , m_func(func) - , m_arg_func_1(arg_func_1) - , m_arg_func_2(arg_func_2) - , m_arg_func_3(arg_func_3) - { - } - - virtual void operator ()(TO* op, u32 code) const - { - (op->*m_func)( - (T1)m_arg_func_1(code), - (T2)m_arg_func_2(code), - (T3)m_arg_func_3(code) - ); - } -}; - -template -class InstrBinder_4 : public InstrCaller -{ - typedef void (TO::*func_t)(T1, T2, T3, T4); - func_t m_func; - const CodeFieldBase& m_arg_func_1; - const CodeFieldBase& m_arg_func_2; - const CodeFieldBase& m_arg_func_3; - const CodeFieldBase& m_arg_func_4; - -public: - InstrBinder_4(func_t func, - const CodeFieldBase& arg_func_1, - const CodeFieldBase& arg_func_2, - const CodeFieldBase& arg_func_3, - const CodeFieldBase& arg_func_4) - : InstrCaller() - , m_func(func) - , m_arg_func_1(arg_func_1) - , m_arg_func_2(arg_func_2) - , m_arg_func_3(arg_func_3) - , m_arg_func_4(arg_func_4) - { - } - - virtual void operator ()(TO* op, u32 code) const - { - (op->*m_func)( - (T1)m_arg_func_1(code), - (T2)m_arg_func_2(code), - (T3)m_arg_func_3(code), - (T4)m_arg_func_4(code) - ); - } -}; - -template -class InstrBinder_5 : public InstrCaller -{ - typedef void (TO::*func_t)(T1, T2, T3, T4, T5); - func_t m_func; - const CodeFieldBase& m_arg_func_1; - const CodeFieldBase& m_arg_func_2; - const CodeFieldBase& m_arg_func_3; - const CodeFieldBase& m_arg_func_4; - const CodeFieldBase& m_arg_func_5; - -public: - InstrBinder_5(func_t func, - const CodeFieldBase& arg_func_1, - const CodeFieldBase& arg_func_2, - const CodeFieldBase& arg_func_3, - const CodeFieldBase& arg_func_4, - const CodeFieldBase& arg_func_5) - : InstrCaller() - , m_func(func) - , m_arg_func_1(arg_func_1) - , m_arg_func_2(arg_func_2) - , m_arg_func_3(arg_func_3) - , m_arg_func_4(arg_func_4) - , m_arg_func_5(arg_func_5) - { - } - - virtual void operator ()(TO* op, u32 code) const - { - (op->*m_func)( - (T1)m_arg_func_1(code), - (T2)m_arg_func_2(code), - (T3)m_arg_func_3(code), - (T4)m_arg_func_4(code), - (T5)m_arg_func_5(code) - ); - } -}; - -template -class InstrBinder_6 : public InstrCaller -{ - typedef void (TO::*func_t)(T1, T2, T3, T4, T5, T6); - func_t m_func; - const CodeFieldBase& m_arg_func_1; - const CodeFieldBase& m_arg_func_2; - const CodeFieldBase& m_arg_func_3; - const CodeFieldBase& m_arg_func_4; - const CodeFieldBase& m_arg_func_5; - const CodeFieldBase& m_arg_func_6; - -public: - InstrBinder_6(func_t func, - const CodeFieldBase& arg_func_1, - const CodeFieldBase& arg_func_2, - const CodeFieldBase& arg_func_3, - const CodeFieldBase& arg_func_4, - const CodeFieldBase& arg_func_5, - const CodeFieldBase& arg_func_6) - : InstrCaller() - , m_func(func) - , m_arg_func_1(arg_func_1) - , m_arg_func_2(arg_func_2) - , m_arg_func_3(arg_func_3) - , m_arg_func_4(arg_func_4) - , m_arg_func_5(arg_func_5) - , m_arg_func_6(arg_func_6) - { - } - - virtual void operator ()(TO* op, u32 code) const - { - (op->*m_func)( - (T1)m_arg_func_1(code), - (T2)m_arg_func_2(code), - (T3)m_arg_func_3(code), - (T4)m_arg_func_4(code), - (T5)m_arg_func_5(code), - (T6)m_arg_func_6(code) - ); - } -}; - -template -InstrCaller* instr_bind(void (TO::*func)()) -{ - return new InstrBinder_0(func); -} - -template -InstrCaller* instr_bind(void (TO::*func)(T1), const CodeFieldBase& arg_func_1) -{ - return new InstrBinder_1(func, arg_func_1); -} - -template -InstrCaller* instr_bind(void (TO::*func)(T1, T2), - const CodeFieldBase& arg_func_1, - const CodeFieldBase& arg_func_2) -{ - return new InstrBinder_2(func, arg_func_1, arg_func_2); -} - -template -InstrCaller* instr_bind(void (TO::*func)(T1, T2, T3), - const CodeFieldBase& arg_func_1, - const CodeFieldBase& arg_func_2, - const CodeFieldBase& arg_func_3) -{ - return new InstrBinder_3(func, arg_func_1, arg_func_2, arg_func_3); -} - -template -InstrCaller* instr_bind(void (TO::*func)(T1, T2, T3, T4), - const CodeFieldBase& arg_func_1, - const CodeFieldBase& arg_func_2, - const CodeFieldBase& arg_func_3, - const CodeFieldBase& arg_func_4) -{ - return new InstrBinder_4(func, arg_func_1, arg_func_2, arg_func_3, arg_func_4); -} - -template -InstrCaller* instr_bind(void (TO::*func)(T1, T2, T3, T4, T5), - const CodeFieldBase& arg_func_1, - const CodeFieldBase& arg_func_2, - const CodeFieldBase& arg_func_3, - const CodeFieldBase& arg_func_4, - const CodeFieldBase& arg_func_5) -{ - return new InstrBinder_5(func, arg_func_1, arg_func_2, arg_func_3, arg_func_4, arg_func_5); -} - -template -InstrCaller* instr_bind(void (TO::*func)(T1, T2, T3, T4, T5, T6), - const CodeFieldBase& arg_func_1, - const CodeFieldBase& arg_func_2, - const CodeFieldBase& arg_func_3, - const CodeFieldBase& arg_func_4, - const CodeFieldBase& arg_func_5, - const CodeFieldBase& arg_func_6) -{ - return new InstrBinder_6(func, arg_func_1, arg_func_2, arg_func_3, arg_func_4, arg_func_5, arg_func_6); -} - -template -class InstrBase : public InstrCaller -{ -protected: - wxString m_name; - const u32 m_opcode; - CodeFieldBase** m_args; - const uint m_args_count; - -public: - InstrBase(const wxString& name, int opcode, uint args_count) - : InstrCaller() - , m_name(name) - , m_opcode(opcode) - , m_args_count(args_count) - , m_args(args_count ? new CodeFieldBase*[args_count] : nullptr) - { - m_name.MakeLower().Replace("_", "."); - } - - __forceinline const wxString& GetName() const - { - return m_name; - } - - __forceinline const uint GetArgCount() const - { - return m_args_count; - } - - __forceinline const CodeFieldBase& GetArg(uint index) const - { - assert(index < m_args_count); - return *m_args[index]; - } - - void operator ()(TO* op, u32 code) const - { - decode(op, code); - } - - u32 operator()(const Array& args) const - { - return encode(args); - } - - virtual void decode(TO* op, u32 code) const=0; - virtual u32 encode(const Array& args) const=0; -}; - -template -class InstrList : public InstrCaller -{ -public: - static const int count = _count; - -protected: - const CodeFieldBase& m_func; - InstrCaller* m_instrs[count]; - InstrBase* m_instrs_info[count]; - InstrCaller* m_error_func; - InstrCaller* m_parent; - int m_opcode; - -public: - InstrList(const CodeFieldBase& func, InstrCaller* error_func) - : InstrCaller() - , m_func(func) - , m_error_func(error_func) - , m_parent(nullptr) - , m_opcode(-1) - { - for(int i=0; i*) * count); - } - - virtual ~InstrList() - { - for(int i=0; i* parent, int opcode) - { - m_opcode = opcode; - m_parent = parent; - } - - InstrCaller* get_parent() const - { - return m_parent; - } - - u32 get_opcode() const - { - return m_opcode; - } - - void set_error_func(InstrCaller* error_func) - { - for(int i=0; i* func, InstrBase* info = nullptr) - { - assert(pos < count); - m_instrs[pos] = func; - m_instrs_info[pos] = info; - } - - InstrCaller* get_instr(int pos) const - { - assert(pos < count); - return m_instrs[pos]; - } - - InstrBase* get_instr_info(int pos) const - { - assert(pos < count); - return m_instrs_info[pos]; - } - - u32 encode(u32 entry) const - { - return m_func[entry] | (m_parent ? (*m_parent)[m_opcode] : 0); - } - - void decode(TO* op, u32 entry, u32 code) const - { - (*m_instrs[entry])(op, code); - } - - virtual void operator ()(TO* op, u32 code) const - { - decode(op, m_func(code) & (count - 1), code); - } - - virtual u32 operator [](u32 entry) const - { - return encode(entry); - } -}; - -template -static InstrList* connect_list(InstrList* parent, InstrList* child, int opcode) -{ - parent->set_instr(opcode, child); - child->set_parent(parent, opcode); - return child; -} - -template -static InstrList* connect_list(InstrList* parent, InstrList* child) -{ - parent->set_error_func(child); - child->set_parent(parent->get_parent(), parent->get_opcode()); - return child; -} template static InstrList<1 << CodeField::size, TO>* new_list(const CodeField& func, InstrCaller* error_func = nullptr) @@ -500,403 +30,4 @@ template static InstrList<1 << CodeField::size, TO>* new_list(InstrList* parent, const CodeField& func, InstrCaller* error_func = nullptr) { return connect_list(parent, new InstrList<1 << CodeField::size, TO>(func, error_func)); -} - -template -class Instr0 : public InstrBase -{ - InstrList& m_list; - -public: - Instr0(InstrList* list, const wxString& name, - void (TO::*func)()) - : InstrBase(name, opcode, 0) - , m_list(*list) - { - m_list.set_instr(opcode, instr_bind(func), this); - } - - virtual void decode(TO* op, u32 code) const - { - m_list.decode(op, opcode, code); - } - - virtual u32 encode(const Array& args) const - { - assert(args.GetCount() == m_args_count); - return m_list.encode(opcode); - } - - u32 encode() const - { - return m_list.encode(opcode); - } - - u32 operator()() const - { - return encode(); - } -}; - -template -class Instr1 : public InstrBase -{ - InstrList& m_list; - -public: - Instr1(InstrList* list, const wxString& name, - void (TO::*func)(T1), - CodeFieldBase& arg_1) - : InstrBase(name, opcode, 1) - , m_list(*list) - { - m_args[0] = &arg_1; - - m_list.set_instr(opcode, instr_bind(func, arg_1), this); - } - - virtual void decode(TO* op, u32 code) const - { - m_list.decode(op, opcode, code); - } - - virtual u32 encode(const Array& args) const - { - assert(args.GetCount() == m_args_count); - return m_list.encode(opcode) | (*m_args[0])[args[0]]; - } - - u32 encode(T1 a1) const - { - return m_list.encode(opcode) | (*m_args[0])[a1]; - } - - u32 operator()(T1 a1) const - { - return encode(a1); - } -}; - -template -class Instr2 : public InstrBase -{ - InstrList& m_list; - -public: - Instr2(InstrList* list, const wxString& name, - void (TO::*func)(T1, T2), - CodeFieldBase& arg_1, - CodeFieldBase& arg_2) - : InstrBase(name, opcode, 2) - , m_list(*list) - { - m_args[0] = &arg_1; - m_args[1] = &arg_2; - - m_list.set_instr(opcode, instr_bind(func, arg_1, arg_2), this); - } - - virtual void decode(TO* op, u32 code) const - { - m_list.decode(op, opcode, code); - } - - virtual u32 encode(const Array& args) const - { - assert(args.GetCount() == m_args_count); - return m_list.encode(opcode) | (*m_args[0])[args[0]] | (*m_args[1])[args[1]]; - } - - u32 encode(T1 a1, T2 a2) const - { - return m_list.encode(opcode) | (*m_args[0])[a1] | (*m_args[1])[a2]; - } - - u32 operator()(T1 a1, T2 a2) const - { - return encode(a1, a2); - } -}; - -template -class Instr3 : public InstrBase -{ - InstrList& m_list; - -public: - Instr3(InstrList* list, const wxString& name, - void (TO::*func)(T1, T2, T3), - CodeFieldBase& arg_1, - CodeFieldBase& arg_2, - CodeFieldBase& arg_3) - : InstrBase(name, opcode, 3) - , m_list(*list) - { - m_args[0] = &arg_1; - m_args[1] = &arg_2; - m_args[2] = &arg_3; - - m_list.set_instr(opcode, instr_bind(func, arg_1, arg_2, arg_3), this); - } - - virtual void decode(TO* op, u32 code) const - { - m_list.decode(op, opcode, code); - } - - virtual u32 encode(const Array& args) const - { - assert(args.GetCount() == m_args_count); - return m_list.encode(opcode) | (*m_args[0])[args[0]] | (*m_args[1])[args[1]] | (*m_args[2])[args[2]]; - } - - u32 encode(T1 a1, T2 a2, T3 a3) const - { - return m_list.encode(opcode) | (*m_args[0])[a1] | (*m_args[1])[a2] | (*m_args[2])[a3]; - } - - u32 operator()(T1 a1, T2 a2, T3 a3) const - { - return encode(a1, a2, a3); - } -}; - -template -class Instr4 : public InstrBase -{ - InstrList& m_list; - -public: - Instr4(InstrList* list, const wxString& name, - void (TO::*func)(T1, T2, T3, T4), - CodeFieldBase& arg_1, - CodeFieldBase& arg_2, - CodeFieldBase& arg_3, - CodeFieldBase& arg_4) - : InstrBase(name, opcode, 4) - , m_list(*list) - { - m_args[0] = &arg_1; - m_args[1] = &arg_2; - m_args[2] = &arg_3; - m_args[3] = &arg_4; - - m_list.set_instr(opcode, instr_bind(func, arg_1, arg_2, arg_3, arg_4), this); - } - - virtual void decode(TO* op, u32 code) const - { - m_list.decode(op, opcode, code); - } - - virtual u32 encode(const Array& args) const - { - assert(args.GetCount() == m_args_count); - return m_list.encode(opcode) | - (*m_args[0])[args[0]] | - (*m_args[1])[args[1]] | - (*m_args[2])[args[2]] | - (*m_args[3])[args[3]]; - } - - u32 encode(T1 a1, T2 a2, T3 a3, T4 a4) const - { - return m_list.encode(opcode) | - (*m_args[0])[a1] | - (*m_args[1])[a2] | - (*m_args[2])[a3] | - (*m_args[3])[a4]; - } - - u32 operator()(T1 a1, T2 a2, T3 a3, T4 a4) const - { - return encode(a1, a2, a3, a4); - } -}; - -template -class Instr5 : public InstrBase -{ - InstrList& m_list; - -public: - Instr5(InstrList* list, const wxString& name, - void (TO::*func)(T1, T2, T3, T4, T5), - CodeFieldBase& arg_1, - CodeFieldBase& arg_2, - CodeFieldBase& arg_3, - CodeFieldBase& arg_4, - CodeFieldBase& arg_5) - : InstrBase(name, opcode, 5) - , m_list(*list) - { - m_args[0] = &arg_1; - m_args[1] = &arg_2; - m_args[2] = &arg_3; - m_args[3] = &arg_4; - m_args[4] = &arg_5; - - m_list.set_instr(opcode, instr_bind(func, arg_1, arg_2, arg_3, arg_4, arg_5), this); - } - - virtual void decode(TO* op, u32 code) const - { - m_list.decode(op, opcode, code); - } - - virtual u32 encode(const Array& args) const - { - assert(args.GetCount() == m_args_count); - return m_list.encode(opcode) | - (*m_args[0])[args[0]] | - (*m_args[1])[args[1]] | - (*m_args[2])[args[2]] | - (*m_args[3])[args[3]] | - (*m_args[4])[args[4]]; - } - - u32 encode(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) const - { - return m_list.encode(opcode) | - (*m_args[0])[a1] | - (*m_args[1])[a2] | - (*m_args[2])[a3] | - (*m_args[3])[a4] | - (*m_args[4])[a5]; - } - - u32 operator()(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) const - { - return encode(a1, a2, a3, a4, a5); - } -}; - -template -class Instr6 : public InstrBase -{ - InstrList& m_list; - -public: - Instr6(InstrList* list, const wxString& name, - void (TO::*func)(T1, T2, T3, T4, T5, T6), - CodeFieldBase& arg_1, - CodeFieldBase& arg_2, - CodeFieldBase& arg_3, - CodeFieldBase& arg_4, - CodeFieldBase& arg_5, - CodeFieldBase& arg_6) - : InstrBase(name, opcode, 6) - , m_list(*list) - { - m_args[0] = &arg_1; - m_args[1] = &arg_2; - m_args[2] = &arg_3; - m_args[3] = &arg_4; - m_args[4] = &arg_5; - m_args[5] = &arg_6; - - m_list.set_instr(opcode, instr_bind(func, arg_1, arg_2, arg_3, arg_4, arg_5, arg_6), this); - } - - virtual void decode(TO* op, u32 code) const - { - m_list.decode(op, opcode, code); - } - - virtual u32 encode(const Array& args) const - { - assert(args.GetCount() == m_args_count); - return m_list.encode(opcode) | - (*m_args[0])[args[0]] | - (*m_args[1])[args[1]] | - (*m_args[2])[args[2]] | - (*m_args[3])[args[3]] | - (*m_args[4])[args[4]] | - (*m_args[5])[args[5]]; - } - - u32 encode(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T5 a6) const - { - return m_list.encode(opcode) | - (*m_args[0])[a1] | - (*m_args[1])[a2] | - (*m_args[2])[a3] | - (*m_args[3])[a4] | - (*m_args[4])[a5] | - (*m_args[5])[a6]; - } - - u32 operator()(T1 a1, T2 a2, T3 a3, T4 a4, T4 a5, T4 a6) const - { - return encode(a1, a2, a3, a4, a5, a6); - } -}; - -template -static Instr0& make_instr(InstrList* list, const wxString& name, void (TO::*func)()) -{ - return *new Instr0(list, name, func); -} - -template -static Instr1& make_instr(InstrList* list, const wxString& name, - void (TO::*func)(T1), - CodeFieldBase& arg_1) -{ - return *new Instr1(list, name, func, arg_1); -} - -template -static Instr2& make_instr(InstrList* list, const wxString& name, - void (TO::*func)(T1, T2), - CodeFieldBase& arg_1, - CodeFieldBase& arg_2) -{ - return *new Instr2(list, name, func, arg_1, arg_2); -} - -template -static Instr3& make_instr(InstrList* list, const wxString& name, - void (TO::*func)(T1, T2, T3), - CodeFieldBase& arg_1, - CodeFieldBase& arg_2, - CodeFieldBase& arg_3) -{ - return *new Instr3(list, name, func, arg_1, arg_2, arg_3); -} - -template -static Instr4& make_instr(InstrList* list, const wxString& name, - void (TO::*func)(T1, T2, T3, T4), - CodeFieldBase& arg_1, - CodeFieldBase& arg_2, - CodeFieldBase& arg_3, - CodeFieldBase& arg_4) -{ - return *new Instr4(list, name, func, arg_1, arg_2, arg_3, arg_4); -} - -template -static Instr5& make_instr(InstrList* list, const wxString& name, - void (TO::*func)(T1, T2, T3, T4, T5), - CodeFieldBase& arg_1, - CodeFieldBase& arg_2, - CodeFieldBase& arg_3, - CodeFieldBase& arg_4, - CodeFieldBase& arg_5) -{ - return *new Instr5(list, name, func, arg_1, arg_2, arg_3, arg_4, arg_5); -} - -template -static Instr6& make_instr(InstrList* list, const wxString& name, - void (TO::*func)(T1, T2, T3, T4, T5, T6), - CodeFieldBase& arg_1, - CodeFieldBase& arg_2, - CodeFieldBase& arg_3, - CodeFieldBase& arg_4, - CodeFieldBase& arg_5, - CodeFieldBase& arg_6) -{ - return *new Instr6(list, name, func, arg_1, arg_2, arg_3, arg_4, arg_5, arg_6); } \ No newline at end of file diff --git a/rpcs3/Emu/Cell/PPCDisAsm.h b/rpcs3/Emu/Cell/PPCDisAsm.h index c3ca64fa25..40c56dda39 100644 --- a/rpcs3/Emu/Cell/PPCDisAsm.h +++ b/rpcs3/Emu/Cell/PPCDisAsm.h @@ -1,80 +1,18 @@ #pragma once +#include "Emu/CPU/CPUDisAsm.h" #include "Gui/DisAsmFrame.h" #include "Emu/Memory/Memory.h" -enum DisAsmModes -{ - DumpMode, - InterpreterMode, - NormalMode, - CompilerElfMode, -}; - -class PPC_DisAsm +class PPCDisAsm : public CPUDisAsm { protected: - DisAsmFrame* disasm_frame; - const DisAsmModes m_mode; - - virtual void Write(const wxString value) + PPCDisAsm(CPUDisAsmMode mode) : CPUDisAsm(mode) { - switch(m_mode) - { - case DumpMode: - { - wxString mem = wxString::Format("\t%08llx:\t", dump_pc); - for(u8 i=0; i < 4; ++i) - { - mem += wxString::Format("%02x", Memory.Read8(dump_pc + i)); - if(i < 3) mem += " "; - } - - last_opcode = mem + "\t" + value + "\n"; - } - break; - - case InterpreterMode: - { - last_opcode = wxString::Format("[%08llx] %02x %02x %02x %02x: %s", dump_pc, - Memory.Read8(offset + dump_pc), - Memory.Read8(offset + dump_pc + 1), - Memory.Read8(offset + dump_pc + 2), - Memory.Read8(offset + dump_pc + 3), value); - } - break; - - case CompilerElfMode: last_opcode = value + "\n"; break; - - default: if(disasm_frame) disasm_frame->AddLine(value); break; - } - } - -public: - wxString last_opcode; - u64 dump_pc; - u64 offset; - -protected: - PPC_DisAsm(PPCThread& cpu, DisAsmModes mode = NormalMode) - : m_mode(mode) - , disasm_frame(NULL) - , offset(0) - { - if(m_mode != NormalMode) return; - - disasm_frame = new DisAsmFrame(cpu); - disasm_frame->Show(); } virtual u32 DisAsmBranchTarget(const s32 imm)=0; - wxString FixOp(wxString op) - { - op.Append(' ', max(8 - op.Len(), 0)); - return op; - } - void DisAsm_V4(const wxString& op, u32 v0, u32 v1, u32 v2, u32 v3) { Write(wxString::Format("%s v%d,v%d,v%d,v%d", FixOp(op), v0, v1, v2, v3)); @@ -153,7 +91,7 @@ protected: } void DisAsm_F1_R2(const wxString& op, u32 f0, u32 r0, u32 r1) { - if(m_mode == CompilerElfMode) + if(m_mode == CPUDisAsm_CompilerElfMode) { Write(wxString::Format("%s f%d,r%d,r%d", FixOp(op), f0, r0, r1)); return; @@ -163,7 +101,7 @@ protected: } void DisAsm_F1_IMM_R1_RC(const wxString& op, u32 f0, s32 imm0, u32 r0, bool rc) { - if(m_mode == CompilerElfMode) + if(m_mode == CPUDisAsm_CompilerElfMode) { Write(wxString::Format("%s%s f%d,r%d,%d #%x", FixOp(op), rc ? "." : "", f0, r0, imm0, imm0)); return; @@ -241,7 +179,7 @@ protected: } void DisAsm_R2_IMM(const wxString& op, u32 r0, u32 r1, s32 imm0) { - if(m_mode == CompilerElfMode) + if(m_mode == CPUDisAsm_CompilerElfMode) { Write(wxString::Format("%s r%d,r%d,%d #%x", FixOp(op), r0, r1, imm0, imm0)); return; diff --git a/rpcs3/Emu/Cell/PPCInstrTable.h b/rpcs3/Emu/Cell/PPCInstrTable.h index 97f701b02d..79942b9305 100644 --- a/rpcs3/Emu/Cell/PPCInstrTable.h +++ b/rpcs3/Emu/Cell/PPCInstrTable.h @@ -1,16 +1,5 @@ #pragma once - -template __forceinline static T sign(const T value) -{ - static_assert(size > 0 && size < sizeof(T) * 8, "Bad size"); - static const T sub_value = T(1) << size; - if(value & (T(1) << (size - 1))) - { - return value - sub_value; - } - - return value; -} +#include "Emu/CPU/CPUInstrTable.h" enum CodeFieldType { @@ -22,27 +11,6 @@ enum CodeFieldType FIELD_BRANCH, }; -class CodeFieldBase -{ -public: - CodeFieldType m_type; - -public: - CodeFieldBase(CodeFieldType type = FIELD_IMM) : m_type(type) - { - } - - virtual u32 operator ()(u32 data) const=0; - virtual void operator()(u32& data, u32 value) const=0; - - virtual u32 operator[](u32 value) const - { - u32 result = 0; - (*this)(result, value); - return result; - } -}; - template class CodeField : public CodeFieldBase { diff --git a/rpcs3/Emu/Cell/PPCThread.cpp b/rpcs3/Emu/Cell/PPCThread.cpp index 47cf5a3805..789efdb945 100644 --- a/rpcs3/Emu/Cell/PPCThread.cpp +++ b/rpcs3/Emu/Cell/PPCThread.cpp @@ -4,21 +4,19 @@ PPCThread* GetCurrentPPCThread() { - return (PPCThread*)GetCurrentNamedThread(); + CPUThread* thread = GetCurrentCPUThread(); + + if(!thread || (thread->GetType() != CPU_THREAD_PPU && thread->GetType() != CPU_THREAD_SPU && thread->GetType() != CPU_THREAD_RAW_SPU)) + { + throw wxString("GetCurrentPPCThread: bad thread"); + } + + return (PPCThread*)thread; } -PPCThread::PPCThread(PPCThreadType type) - : ThreadBase(true, "PPCThread") - , m_type(type) - , DisAsmFrame(nullptr) +PPCThread::PPCThread(CPUThreadType type) + : CPUThread(type) , m_dec(nullptr) - , stack_size(0) - , stack_addr(0) - , m_prio(0) - , m_offset(0) - , m_sync_wait(false) - , m_wait_thread_id(-1) - , m_free_data(false) { } @@ -27,146 +25,25 @@ PPCThread::~PPCThread() Close(); } -void PPCThread::Close() +void PPCThread::DoReset() { - if(IsAlive()) - { - m_free_data = true; - } - - if(DisAsmFrame) - { - DisAsmFrame->Close(); - DisAsmFrame = nullptr; - } - - Stop(); -} - -void PPCThread::Reset() -{ - CloseStack(); - - m_sync_wait = 0; - m_wait_thread_id = -1; memset(m_args, 0, sizeof(u64) * 4); - - SetPc(0); - cycle = 0; - - isBranch = false; - - m_status = Stopped; - m_error = 0; - - DoReset(); } void PPCThread::InitStack() { - if(stack_addr) return; - if(stack_size == 0) stack_size = 0x10000; - stack_addr = Memory.StackMem.Alloc(Memory.AlignAddr(stack_size, 0x100)); + if(m_stack_addr) return; + if(m_stack_size == 0) m_stack_size = 0x10000; + m_stack_addr = Memory.StackMem.Alloc(Memory.AlignAddr(m_stack_size, 0x100)); - stack_point = stack_addr + stack_size; + m_stack_point = m_stack_addr + m_stack_size; /* - stack_point += stack_size - 0x10; - stack_point &= -0x10; - Memory.Write64(stack_point, 0); - stack_point -= 0x60; - Memory.Write64(stack_point, stack_point + 0x60); + m_stack_point += m_stack_size - 0x10; + m_stack_point &= -0x10; + Memory.Write64(m_stack_point, 0); + m_stack_point -= 0x60; + Memory.Write64(m_stack_point, m_stack_point + 0x60); */ - if(wxFileExists("stack.dat")) - { - ConLog.Warning("loading stack.dat..."); - wxFile stack("stack.dat"); - stack.Read(Memory.GetMemFromAddr(stack_addr), 0x10000); - stack.Close(); - } -} - -void PPCThread::CloseStack() -{ - Memory.Free(stack_addr); - stack_addr = 0; - stack_size = 0; -} - -void PPCThread::SetId(const u32 id) -{ - m_id = id; -} - -void PPCThread::SetName(const wxString& name) -{ - m_name = name; -} - -void PPCThread::Wait(bool wait) -{ - wxCriticalSectionLocker lock(m_cs_sync); - m_sync_wait = wait; -} - -void PPCThread::Wait(const PPCThread& thr) -{ - wxCriticalSectionLocker lock(m_cs_sync); - m_wait_thread_id = thr.GetId(); - m_sync_wait = true; -} - -bool PPCThread::Sync() -{ - wxCriticalSectionLocker lock(m_cs_sync); - - return m_sync_wait; -} - -int PPCThread::ThreadStatus() -{ - if(m_is_step) - { - return PPCThread_Step; - } - - if(Emu.IsStopped()) - { - return PPCThread_Stopped; - } - - if(TestDestroy()) - { - return PPCThread_Break; - } - - if(Emu.IsPaused() || Sync()) - { - return PPCThread_Sleeping; - } - - return PPCThread_Running; -} - -void PPCThread::NextBranchPc() -{ - SetPc(nPC); -} - -void PPCThread::NextPc() -{ - if(isBranch) - { - NextBranchPc(); - isBranch = false; - return; - } - - SetPc(PC + 4); -} - -void PPCThread::PrevPc() -{ - SetPc(PC - 4); } void PPCThread::SetPc(const u64 pc) @@ -175,191 +52,3 @@ void PPCThread::SetPc(const u64 pc) nPC = PC + 4; } -void PPCThread::SetEntry(const u64 pc) -{ - entry = pc; -} - -void PPCThread::SetBranch(const u64 pc) -{ - if(!Memory.IsGoodAddr(m_offset + pc)) - { - ConLog.Error("%s branch error: bad address 0x%llx #pc: 0x%llx", GetFName(), m_offset+ pc, m_offset + PC); - Emu.Pause(); - } - nPC = pc; - isBranch = true; -} - -void PPCThread::SetError(const u32 error) -{ - if(error == 0) - { - m_error = 0; - } - else - { - m_error |= error; - } -} - -wxArrayString PPCThread::ErrorToString(const u32 error) -{ - wxArrayString earr; - - if(error == 0) return earr; - - earr.Add("Unknown error"); - - return earr; -} - -void PPCThread::Run() -{ - if(IsRunning()) Stop(); - if(IsPaused()) - { - Resume(); - return; - } - - wxGetApp().SendDbgCommand(DID_START_THREAD, this); - - m_status = Running; - - SetPc(entry); - InitStack(); - InitRegs(); - DoRun(); - Emu.CheckStatus(); - - wxGetApp().SendDbgCommand(DID_STARTED_THREAD, this); -} - -void PPCThread::Resume() -{ - if(!IsPaused()) return; - - wxGetApp().SendDbgCommand(DID_RESUME_THREAD, this); - - m_status = Running; - DoResume(); - Emu.CheckStatus(); - - ThreadBase::Start(); - - wxGetApp().SendDbgCommand(DID_RESUMED_THREAD, this); -} - -void PPCThread::Pause() -{ - if(!IsRunning()) return; - - wxGetApp().SendDbgCommand(DID_PAUSE_THREAD, this); - - m_status = Paused; - DoPause(); - Emu.CheckStatus(); - - ThreadBase::Stop(false); - wxGetApp().SendDbgCommand(DID_PAUSED_THREAD, this); -} - -void PPCThread::Stop() -{ - if(IsStopped()) return; - - wxGetApp().SendDbgCommand(DID_STOP_THREAD, this); - - m_status = Stopped; - ThreadBase::Stop(false); - Reset(); - DoStop(); - Emu.CheckStatus(); - - wxGetApp().SendDbgCommand(DID_STOPED_THREAD, this); -} - -void PPCThread::Exec() -{ - m_is_step = false; - wxGetApp().SendDbgCommand(DID_EXEC_THREAD, this); - ThreadBase::Start(); - //std::thread thr(std::bind(std::mem_fn(&PPCThread::Task), this)); -} - -void PPCThread::ExecOnce() -{ - m_is_step = true; - wxGetApp().SendDbgCommand(DID_EXEC_THREAD, this); - ThreadBase::Start(); - if(!ThreadBase::Wait()) while(m_is_step) Sleep(1); - wxGetApp().SendDbgCommand(DID_PAUSE_THREAD, this); - wxGetApp().SendDbgCommand(DID_PAUSED_THREAD, this); -} - -void PPCThread::Task() -{ - //ConLog.Write("%s enter", PPCThread::GetFName()); - - const Array& bp = Emu.GetBreakPoints(); - - try - { - for(uint i=0; i argv_addr; - u64 m_offset; - u32 m_exit_status; - bool m_free_data; - bool m_is_step; + Array m_argv_addr; public: - u64 stack_size; - u64 stack_addr; - u64 stack_point; - virtual void InitRegs()=0; - virtual void InitStack(); - virtual void CloseStack(); - - virtual u64 GetStackAddr() const { return stack_addr; } - virtual u64 GetStackSize() const { return stack_size; } - virtual u64 GetFreeStackSize() const=0; - void SetArg(const uint pos, const u64 arg) { assert(pos < 4); m_args[pos] = arg; } - - void SetId(const u32 id); - void SetName(const wxString& name); - void SetPrio(const u64 prio) { m_prio = prio; } - void SetOffset(const u64 offset) { m_offset = offset; } - void SetExitStatus(const u32 status) { m_exit_status = status; } - - u64 GetOffset() const { return m_offset; } - u32 GetExitStatus() const { return m_exit_status; } - u64 GetPrio() const { return m_prio; } - wxString GetName() const { return m_name; } - wxString GetFName() const - { - return - wxString::Format("%s[%d] Thread%s", - GetTypeString(), - m_id, - (GetName().IsEmpty() ? "" : " (" + GetName() + ")") - ); - } - - static wxString PPCThreadTypeToString(PPCThreadType type) - { - switch(type) - { - case PPC_THREAD_PPU: return "PPU"; - case PPC_THREAD_SPU: return "SPU"; - case PPC_THREAD_RAW_SPU: return "RawSPU"; - } - - return "Unknown"; - } - - wxString GetTypeString() const { return PPCThreadTypeToString(m_type); } + virtual void SetArg(const uint pos, const u64 arg) { assert(pos < 4); m_args[pos] = arg; } virtual wxString GetThreadName() const { return GetFName() + wxString::Format("[0x%08llx]", PC); } -public: - bool isBranch; - - u64 entry; - u64 PC; - u64 nPC; - u64 cycle; - protected: - PPCThread(PPCThreadType type); + PPCThread(CPUThreadType type); public: ~PPCThread(); - u32 m_wait_thread_id; - - wxCriticalSection m_cs_sync; - bool m_sync_wait; - void Wait(bool wait); - void Wait(const PPCThread& thr); - bool Sync(); - - template - void WaitFor(T func) - { - while(func(ThreadStatus())) - { - Sleep(1); - } - } - - int ThreadStatus(); - - void NextPc(); - void NextBranchPc(); - void PrevPc(); - void SetBranch(const u64 pc); - void SetPc(const u64 pc); - void SetEntry(const u64 entry); + virtual void SetPc(const u64 pc) override; void SetError(const u32 error); - static wxArrayString ErrorToString(const u32 error); - wxArrayString ErrorToString() { return ErrorToString(m_error); } - - bool IsOk() const { return m_error == 0; } - bool IsRunning() const { return m_status == Running; } - bool IsPaused() const { return m_status == Paused; } - bool IsStopped() const { return m_status == Stopped; } - - bool IsJoinable() const { return m_joinable; } - bool IsJoining() const { return m_joining; } - void SetJoinable(bool joinable) { m_joinable = joinable; } - void SetJoining(bool joining) { m_joining = joining; } - - u32 GetError() const { return m_error; } - u32 GetId() const { return m_id; } - PPCThreadType GetType() const { return m_type; } - - void Reset(); - void Close(); - void Run(); - void Pause(); - void Resume(); - void Stop(); - - virtual wxString RegsToString() { return wxEmptyString; } - virtual wxString ReadRegString(wxString reg) { return wxEmptyString; } - virtual bool WriteRegString(wxString reg, wxString value) { return false; } - - virtual void Exec(); - void ExecOnce(); - - virtual void AddArgv(const wxString& arg) {} - protected: - virtual void DoReset()=0; - virtual void DoRun()=0; - virtual void DoPause()=0; - virtual void DoResume()=0; - virtual void DoStop()=0; - -public: - virtual void Task(); - -private: - virtual void DoCode(const s32 code)=0; + virtual void DoReset() override; }; PPCThread* GetCurrentPPCThread(); \ No newline at end of file diff --git a/rpcs3/Emu/Cell/PPUDecoder.h b/rpcs3/Emu/Cell/PPUDecoder.h index cff3d3ec7a..d5973edb6a 100644 --- a/rpcs3/Emu/Cell/PPUDecoder.h +++ b/rpcs3/Emu/Cell/PPUDecoder.h @@ -4,18 +4,17 @@ #include "Emu/Cell/PPCDecoder.h" #include "PPUInstrTable.h" -class PPU_Decoder : public PPC_Decoder +class PPUDecoder : public PPCDecoder { - PPU_Opcodes* m_op; + PPUOpcodes* m_op; public: - PPU_Decoder(PPU_Opcodes& op) : m_op(&op) + PPUDecoder(PPUOpcodes& op) : m_op(&op) { } - ~PPU_Decoder() + ~PPUDecoder() { - m_op->Exit(); delete m_op; } diff --git a/rpcs3/Emu/Cell/PPUDisAsm.h b/rpcs3/Emu/Cell/PPUDisAsm.h index 2ac75b274e..458a578b3c 100644 --- a/rpcs3/Emu/Cell/PPUDisAsm.h +++ b/rpcs3/Emu/Cell/PPUDisAsm.h @@ -6,41 +6,243 @@ #include "Gui/DisAsmFrame.h" #include "Emu/Memory/Memory.h" -class PPU_DisAsm - : public PPU_Opcodes - , public PPC_DisAsm +class PPUDisAsm + : public PPUOpcodes + , public PPCDisAsm { public: - PPCThread& CPU; - - PPU_DisAsm() - : PPC_DisAsm(*(PPCThread*)NULL, DumpMode) - , CPU(*(PPCThread*)NULL) - { - } - - PPU_DisAsm(PPCThread& cpu, DisAsmModes mode = NormalMode) - : PPC_DisAsm(cpu, mode) - , CPU(cpu) - { - } - - ~PPU_DisAsm() + PPUDisAsm(CPUDisAsmMode mode) : PPCDisAsm(mode) { } private: - void Exit() - { - if(m_mode == NormalMode && !disasm_frame->exit) - { - disasm_frame->Close(); - } - } - u32 DisAsmBranchTarget(const s32 imm) { - return branchTarget(m_mode == NormalMode ? CPU.PC : dump_pc, imm); + return branchTarget(dump_pc, imm); + } + +private: + void DisAsm_V4(const wxString& op, u32 v0, u32 v1, u32 v2, u32 v3) + { + Write(wxString::Format("%s v%d,v%d,v%d,v%d", FixOp(op), v0, v1, v2, v3)); + } + void DisAsm_V3_UIMM(const wxString& op, u32 v0, u32 v1, u32 v2, u32 uimm) + { + Write(wxString::Format("%s v%d,v%d,v%d,%u #%x", FixOp(op), v0, v1, v2, uimm, uimm)); + } + void DisAsm_V3(const wxString& op, u32 v0, u32 v1, u32 v2) + { + Write(wxString::Format("%s v%d,v%d,v%d", FixOp(op), v0, v1, v2)); + } + void DisAsm_V2_UIMM(const wxString& op, u32 v0, u32 v1, u32 uimm) + { + Write(wxString::Format("%s v%d,v%d,%u #%x", FixOp(op), v0, v1, uimm, uimm)); + } + void DisAsm_V2(const wxString& op, u32 v0, u32 v1) + { + Write(wxString::Format("%s v%d,v%d", FixOp(op), v0, v1)); + } + void DisAsm_V1_SIMM(const wxString& op, u32 v0, s32 simm) + { + Write(wxString::Format("%s v%d,%d #%x", FixOp(op), v0, simm, simm)); + } + void DisAsm_V1(const wxString& op, u32 v0) + { + Write(wxString::Format("%s v%d", FixOp(op), v0)); + } + void DisAsm_V1_R2(const wxString& op, u32 v0, u32 r1, u32 r2) + { + Write(wxString::Format("%s v%d,r%d,r%d", FixOp(op), v0, r1, r2)); + } + void DisAsm_CR1_F2_RC(const wxString& op, u32 cr0, u32 f0, u32 f1, bool rc) + { + Write(wxString::Format("%s%s cr%d,f%d,f%d", FixOp(op), rc ? "." : "", cr0, f0, f1)); + } + void DisAsm_CR1_F2(const wxString& op, u32 cr0, u32 f0, u32 f1) + { + DisAsm_CR1_F2_RC(op, cr0, f0, f1, false); + } + void DisAsm_INT1_R2(const wxString& op, u32 i0, u32 r0, u32 r1) + { + Write(wxString::Format("%s %d,r%d,r%d", FixOp(op), i0, r0, r1)); + } + void DisAsm_INT1_R1_IMM(const wxString& op, u32 i0, u32 r0, s32 imm0) + { + Write(wxString::Format("%s %d,r%d,%d #%x", FixOp(op), i0, r0, imm0, imm0)); + } + void DisAsm_INT1_R1_RC(const wxString& op, u32 i0, u32 r0, bool rc) + { + Write(wxString::Format("%s%s %d,r%d", FixOp(op), rc ? "." : "", i0, r0)); + } + void DisAsm_INT1_R1(const wxString& op, u32 i0, u32 r0) + { + DisAsm_INT1_R1_RC(op, i0, r0, false); + } + void DisAsm_F4_RC(const wxString& op, u32 f0, u32 f1, u32 f2, u32 f3, bool rc) + { + Write(wxString::Format("%s%s f%d,f%d,f%d,f%d", FixOp(op), rc ? "." : "", f0, f1, f2, f3)); + } + void DisAsm_F3_RC(const wxString& op, u32 f0, u32 f1, u32 f2, bool rc) + { + Write(wxString::Format("%s%s f%d,f%d,f%d", FixOp(op), rc ? "." : "", f0, f1, f2)); + } + void DisAsm_F3(const wxString& op, u32 f0, u32 f1, u32 f2) + { + DisAsm_F3_RC(op, f0, f1, f2, false); + } + void DisAsm_F2_RC(const wxString& op, u32 f0, u32 f1, bool rc) + { + Write(wxString::Format("%s%s f%d,f%d", FixOp(op), rc ? "." : "", f0, f1)); + } + void DisAsm_F2(const wxString& op, u32 f0, u32 f1) + { + DisAsm_F2_RC(op, f0, f1, false); + } + void DisAsm_F1_R2(const wxString& op, u32 f0, u32 r0, u32 r1) + { + if(m_mode == CPUDisAsm_CompilerElfMode) + { + Write(wxString::Format("%s f%d,r%d,r%d", FixOp(op), f0, r0, r1)); + return; + } + + Write(wxString::Format("%s f%d,r%d(r%d)", FixOp(op), f0, r0, r1)); + } + void DisAsm_F1_IMM_R1_RC(const wxString& op, u32 f0, s32 imm0, u32 r0, bool rc) + { + if(m_mode == CPUDisAsm_CompilerElfMode) + { + Write(wxString::Format("%s%s f%d,r%d,%d #%x", FixOp(op), rc ? "." : "", f0, r0, imm0, imm0)); + return; + } + + Write(wxString::Format("%s%s f%d,%d(r%d) #%x", FixOp(op), rc ? "." : "", f0, imm0, r0, imm0)); + } + void DisAsm_F1_IMM_R1(const wxString& op, u32 f0, s32 imm0, u32 r0) + { + DisAsm_F1_IMM_R1_RC(op, f0, imm0, r0, false); + } + void DisAsm_F1_RC(const wxString& op, u32 f0, bool rc) + { + Write(wxString::Format("%s%s f%d", FixOp(op), rc ? "." : "", f0)); + } + void DisAsm_R1_RC(const wxString& op, u32 r0, bool rc) + { + Write(wxString::Format("%s%s r%d", FixOp(op), rc ? "." : "", r0)); + } + void DisAsm_R1(const wxString& op, u32 r0) + { + DisAsm_R1_RC(op, r0, false); + } + void DisAsm_R2_OE_RC(const wxString& op, u32 r0, u32 r1, u32 oe, bool rc) + { + Write(wxString::Format("%s%s%s r%d,r%d", FixOp(op), oe ? "o" : "", rc ? "." : "", r0, r1)); + } + void DisAsm_R2_RC(const wxString& op, u32 r0, u32 r1, bool rc) + { + DisAsm_R2_OE_RC(op, r0, r1, false, rc); + } + void DisAsm_R2(const wxString& op, u32 r0, u32 r1) + { + DisAsm_R2_RC(op, r0, r1, false); + } + void DisAsm_R3_OE_RC(const wxString& op, u32 r0, u32 r1, u32 r2, u32 oe, bool rc) + { + Write(wxString::Format("%s%s%s r%d,r%d,r%d", FixOp(op), oe ? "o" : "", rc ? "." : "", r0, r1, r2)); + } + void DisAsm_R3_INT2_RC(const wxString& op, u32 r0, u32 r1, u32 r2, s32 i0, s32 i1, bool rc) + { + Write(wxString::Format("%s%s r%d,r%d,r%d,%d,%d", FixOp(op), rc ? "." : "", r0, r1, r2, i0, i1)); + } + void DisAsm_R3_RC(const wxString& op, u32 r0, u32 r1, u32 r2, bool rc) + { + DisAsm_R3_OE_RC(op, r0, r1, r2, false, rc); + } + void DisAsm_R3(const wxString& op, u32 r0, u32 r1, u32 r2) + { + DisAsm_R3_RC(op, r0, r1, r2, false); + } + void DisAsm_R2_INT3_RC(const wxString& op, u32 r0, u32 r1, s32 i0, s32 i1, s32 i2, bool rc) + { + Write(wxString::Format("%s%s r%d,r%d,%d,%d,%d", FixOp(op), rc ? "." : "", r0, r1, i0, i1, i2)); + } + void DisAsm_R2_INT3(const wxString& op, u32 r0, u32 r1, s32 i0, s32 i1, s32 i2) + { + DisAsm_R2_INT3_RC(op, r0, r1, i0, i1, i2, false); + } + void DisAsm_R2_INT2_RC(const wxString& op, u32 r0, u32 r1, s32 i0, s32 i1, bool rc) + { + Write(wxString::Format("%s%s r%d,r%d,%d,%d", FixOp(op), rc ? "." : "", r0, r1, i0, i1)); + } + void DisAsm_R2_INT2(const wxString& op, u32 r0, u32 r1, s32 i0, s32 i1) + { + DisAsm_R2_INT2_RC(op, r0, r1, i0, i1, false); + } + void DisAsm_R2_INT1_RC(const wxString& op, u32 r0, u32 r1, s32 i0, bool rc) + { + Write(wxString::Format("%s%s r%d,r%d,%d", FixOp(op), rc ? "." : "", r0, r1, i0)); + } + void DisAsm_R2_INT1(const wxString& op, u32 r0, u32 r1, s32 i0) + { + DisAsm_R2_INT1_RC(op, r0, r1, i0, false); + } + void DisAsm_R2_IMM(const wxString& op, u32 r0, u32 r1, s32 imm0) + { + if(m_mode == CPUDisAsm_CompilerElfMode) + { + Write(wxString::Format("%s r%d,r%d,%d #%x", FixOp(op), r0, r1, imm0, imm0)); + return; + } + + Write(wxString::Format("%s r%d,%d(r%d) #%x", FixOp(op), r0, imm0, r1, imm0)); + } + void DisAsm_R1_IMM(const wxString& op, u32 r0, s32 imm0) + { + Write(wxString::Format("%s r%d,%d #%x", FixOp(op), r0, imm0, imm0)); + } + void DisAsm_IMM_R1(const wxString& op, s32 imm0, u32 r0) + { + Write(wxString::Format("%s %d,r%d #%x", FixOp(op), imm0, r0, imm0)); + } + void DisAsm_CR1_R1_IMM(const wxString& op, u32 cr0, u32 r0, s32 imm0) + { + Write(wxString::Format("%s cr%d,r%d,%d #%x", FixOp(op), cr0, r0, imm0, imm0)); + } + void DisAsm_CR1_R2_RC(const wxString& op, u32 cr0, u32 r0, u32 r1, bool rc) + { + Write(wxString::Format("%s%s cr%d,r%d,r%d", FixOp(op), rc ? "." : "", cr0, r0, r1)); + } + void DisAsm_CR1_R2(const wxString& op, u32 cr0, u32 r0, u32 r1) + { + DisAsm_CR1_R2_RC(op, cr0, r0, r1, false); + } + void DisAsm_CR2(const wxString& op, u32 cr0, u32 cr1) + { + Write(wxString::Format("%s cr%d,cr%d", FixOp(op), cr0, cr1)); + } + void DisAsm_INT3(const wxString& op, const int i0, const int i1, const int i2) + { + Write(wxString::Format("%s %d,%d,%d", FixOp(op), i0, i1, i2)); + } + void DisAsm_INT1(const wxString& op, const int i0) + { + Write(wxString::Format("%s %d", FixOp(op), i0)); + } + void DisAsm_BRANCH(const wxString& op, const int pc) + { + Write(wxString::Format("%s 0x%x", FixOp(op), DisAsmBranchTarget(pc))); + } + void DisAsm_BRANCH_A(const wxString& op, const int pc) + { + Write(wxString::Format("%s 0x%x", FixOp(op), pc)); + } + void DisAsm_B2_BRANCH(const wxString& op, u32 b0, u32 b1, const int pc) + { + Write(wxString::Format("%s %d,%d,0x%x ", FixOp(op), b0, b1, DisAsmBranchTarget(pc))); + } + void DisAsm_CR_BRANCH(const wxString& op, u32 cr, const int pc) + { + Write(wxString::Format("%s cr%d,0x%x ", FixOp(op), cr, DisAsmBranchTarget(pc))); } private: @@ -738,7 +940,7 @@ private: } void BC(u32 bo, u32 bi, s32 bd, u32 aa, u32 lk) { - if(m_mode == CompilerElfMode) + if(m_mode == CPUDisAsm_CompilerElfMode) { Write(wxString::Format("bc 0x%x, 0x%x, 0x%x, %d, %d", bo, bi, bd, aa, lk)); return; @@ -844,7 +1046,7 @@ private: } void B(s32 ll, u32 aa, u32 lk) { - if(m_mode == CompilerElfMode) + if(m_mode == CPUDisAsm_CompilerElfMode) { Write(wxString::Format("b 0x%x, %d, %d", ll, aa, lk)); return; diff --git a/rpcs3/Emu/Cell/PPUInstrTable.h b/rpcs3/Emu/Cell/PPUInstrTable.h index 82f3a6bc2a..ea524f4827 100644 --- a/rpcs3/Emu/Cell/PPUInstrTable.h +++ b/rpcs3/Emu/Cell/PPUInstrTable.h @@ -203,20 +203,20 @@ namespace PPU_instr static CodeField<9, 10> STRM; - static auto main_list = new_list(OPCD, instr_bind(&PPU_Opcodes::UNK, GetCode, OPCD, OPCD)); + static auto main_list = new_list(OPCD, instr_bind(&PPUOpcodes::UNK, GetCode, OPCD, OPCD)); static auto g04_list = new_list(main_list, PPU_opcodes::G_04, GD_04); - static auto g04_0_list = new_list(g04_list, GD_04_0, instr_bind(&PPU_Opcodes::UNK, GetCode, OPCD, GD_04_0)); - static auto g13_list = new_list(main_list, PPU_opcodes::G_13, GD_13, instr_bind(&PPU_Opcodes::UNK, GetCode, OPCD, GD_13)); - static auto g1e_list = new_list(main_list, PPU_opcodes::G_1e, GD_1e, instr_bind(&PPU_Opcodes::UNK, GetCode, OPCD, GD_1e)); - static auto g1f_list = new_list(main_list, PPU_opcodes::G_1f, GD_1f, instr_bind(&PPU_Opcodes::UNK, GetCode, OPCD, GD_1f)); - static auto g3a_list = new_list(main_list, PPU_opcodes::G_3a, GD_3a, instr_bind(&PPU_Opcodes::UNK, GetCode, OPCD, GD_3a)); - static auto g3b_list = new_list(main_list, PPU_opcodes::G_3b, GD_3b, instr_bind(&PPU_Opcodes::UNK, GetCode, OPCD, GD_3b)); - static auto g3e_list = new_list(main_list, PPU_opcodes::G_3e, GD_3e, instr_bind(&PPU_Opcodes::UNK, GetCode, OPCD, GD_3e)); + static auto g04_0_list = new_list(g04_list, GD_04_0, instr_bind(&PPUOpcodes::UNK, GetCode, OPCD, GD_04_0)); + static auto g13_list = new_list(main_list, PPU_opcodes::G_13, GD_13, instr_bind(&PPUOpcodes::UNK, GetCode, OPCD, GD_13)); + static auto g1e_list = new_list(main_list, PPU_opcodes::G_1e, GD_1e, instr_bind(&PPUOpcodes::UNK, GetCode, OPCD, GD_1e)); + static auto g1f_list = new_list(main_list, PPU_opcodes::G_1f, GD_1f, instr_bind(&PPUOpcodes::UNK, GetCode, OPCD, GD_1f)); + static auto g3a_list = new_list(main_list, PPU_opcodes::G_3a, GD_3a, instr_bind(&PPUOpcodes::UNK, GetCode, OPCD, GD_3a)); + static auto g3b_list = new_list(main_list, PPU_opcodes::G_3b, GD_3b, instr_bind(&PPUOpcodes::UNK, GetCode, OPCD, GD_3b)); + static auto g3e_list = new_list(main_list, PPU_opcodes::G_3e, GD_3e, instr_bind(&PPUOpcodes::UNK, GetCode, OPCD, GD_3e)); static auto g3f_list = new_list(main_list, PPU_opcodes::G_3f, GD_3f); - static auto g3f_0_list = new_list(g3f_list, GD_3f_0, instr_bind(&PPU_Opcodes::UNK, GetCode, OPCD, GD_3f_0)); + static auto g3f_0_list = new_list(g3f_list, GD_3f_0, instr_bind(&PPUOpcodes::UNK, GetCode, OPCD, GD_3f_0)); #define bind_instr(list, name, ...) \ - static const auto& name = make_instr(list, #name, &PPU_Opcodes::name, ##__VA_ARGS__) + static const auto& name = make_instr(list, #name, &PPUOpcodes::name, ##__VA_ARGS__) bind_instr(main_list, TDI, TO, RA, simm16); bind_instr(main_list, TWI, TO, RA, simm16); diff --git a/rpcs3/Emu/Cell/PPUInterpreter.h b/rpcs3/Emu/Cell/PPUInterpreter.h index ce08c505fc..604b3dd033 100644 --- a/rpcs3/Emu/Cell/PPUInterpreter.h +++ b/rpcs3/Emu/Cell/PPUInterpreter.h @@ -45,13 +45,13 @@ u64 rotr64(const u64 x, const u8 n) { return (x >> n) | (x << (64 - n)); } #define rotl64 _rotl64 #define rotr64 _rotr64 -class PPU_Interpreter : public PPU_Opcodes +class PPUInterpreter : public PPUOpcodes { private: PPUThread& CPU; public: - PPU_Interpreter(PPUThread& cpu) : CPU(cpu) + PPUInterpreter(PPUThread& cpu) : CPU(cpu) { InitRotateMask(); } @@ -61,7 +61,7 @@ private: void SysCall() { - CPU.DoSyscall(CPU.GPR[11]); + SysCalls::DoSyscall(CPU.GPR[11]); if(enable_log) ConLog.Warning("SysCall[%lld] done with code [0x%llx]! #pc: 0x%llx", CPU.GPR[11], CPU.GPR[3], CPU.PC); diff --git a/rpcs3/Emu/Cell/PPUOpcodes.h b/rpcs3/Emu/Cell/PPUOpcodes.h index 21e5fbf7c3..2f10abcfa1 100644 --- a/rpcs3/Emu/Cell/PPUOpcodes.h +++ b/rpcs3/Emu/Cell/PPUOpcodes.h @@ -428,11 +428,9 @@ namespace PPU_opcodes }; } -class PPU_Opcodes +class PPUOpcodes { public: - virtual void Exit()=0; - static u64 branchTarget(const u64 pc, const u64 imm) { return pc + (imm & ~0x3ULL); diff --git a/rpcs3/Emu/Cell/PPUProgramCompiler.cpp b/rpcs3/Emu/Cell/PPUProgramCompiler.cpp index c645a2cf7f..60c5d860c5 100644 --- a/rpcs3/Emu/Cell/PPUProgramCompiler.cpp +++ b/rpcs3/Emu/Cell/PPUProgramCompiler.cpp @@ -362,7 +362,7 @@ void CompilePPUProgram::DetectArgInfo(Arg& arg) return; } - if(GetInstruction(str)) + if(GetInstruction(str)) { arg.type = ARG_INSTR; return; @@ -1397,17 +1397,9 @@ void CompilePPUProgram::Compile() LoadArgs(); - auto instr = GetInstruction(op); + auto instr = GetInstruction(op); if(instr) { - /* - FIELD_IMM, - FIELD_R_GPR, - FIELD_R_FPR, - FIELD_R_VPR, - FIELD_R_CR, - FIELD_BRANCH, - */ uint type[] = { ARG_IMM, diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp index 2f329f4b16..fda484b112 100644 --- a/rpcs3/Emu/Cell/PPUThread.cpp +++ b/rpcs3/Emu/Cell/PPUThread.cpp @@ -10,14 +10,12 @@ PPUThread& GetCurrentPPUThread() { PPCThread* thread = GetCurrentPPCThread(); - if(!thread || thread->GetType() != PPC_THREAD_PPU) throw wxString("GetCurrentPPUThread: bad thread"); + if(!thread || thread->GetType() != CPU_THREAD_PPU) throw wxString("GetCurrentPPUThread: bad thread"); return *(PPUThread*)thread; } -PPUThread::PPUThread() - : PPCThread(PPC_THREAD_PPU) - , SysCalls(*this) +PPUThread::PPUThread() : PPCThread(CPU_THREAD_PPU) { Reset(); } @@ -29,6 +27,8 @@ PPUThread::~PPUThread() void PPUThread::DoReset() { + PPCThread::DoReset(); + //reset regs memset(VPR, 0, sizeof(VPR)); memset(FPR, 0, sizeof(FPR)); @@ -52,10 +52,10 @@ void PPUThread::DoReset() void PPUThread::AddArgv(const wxString& arg) { - stack_point -= arg.Len() + 1; - stack_point = Memory.AlignAddr(stack_point, 0x10) - 0x10; - argv_addr.AddCpy(stack_point); - Memory.WriteString(stack_point, arg); + m_stack_point -= arg.Len() + 1; + m_stack_point = Memory.AlignAddr(m_stack_point, 0x10) - 0x10; + m_argv_addr.AddCpy(m_stack_point); + Memory.WriteString(m_stack_point, arg); } void PPUThread::InitRegs() @@ -88,9 +88,9 @@ void PPUThread::InitRegs() } */ - stack_point = Memory.AlignAddr(stack_point, 0x200) - 0x200; + m_stack_point = Memory.AlignAddr(m_stack_point, 0x200) - 0x200; - GPR[1] = stack_point; + GPR[1] = m_stack_point; GPR[2] = rtoc; for(int i=4; i<32; ++i) @@ -99,14 +99,14 @@ void PPUThread::InitRegs() GPR[i] = (i+1) * 0x10000; } - if(argv_addr.GetCount()) + if(m_argv_addr.GetCount()) { - u64 argc = argv_addr.GetCount(); - stack_point -= 0xc + 4 * argc; - u64 argv = stack_point; + u64 argc = m_argv_addr.GetCount(); + m_stack_point -= 0xc + 4 * argc; + u64 argv = m_stack_point; mem64_ptr_t argv_list(argv); - for(int i=0; i> 16; + + ConLog.Warning("RawSPUThread[%d]: DMA %s:", m_index, 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.SkipLn(); + + MFC.CMDStatus.SetValue(dmac.Cmd(value, tag, lsa, ea, size)); + } + break; + + default: + ConLog.Error("RawSPUThread[%d]: Unknown MFC cmd. (opcode=0x%x, cmd=0x%x)", m_index, op, value); + break; + } + } + break; + case MFC_QStatus_offs: ConLog.Warning("RawSPUThread[%d]: Write32(MFC_QStatus, 0x%x)", m_index, value); MFC.QStatus.SetValue(value); break; + case Prxy_QueryType_offs: + { + ConLog.Warning("RawSPUThread[%d]: Write32(Prxy_QueryType, 0x%x)", m_index, value); + Prxy.QueryType.SetValue(value); + + switch(value) + { + case 2: + ConLog.Warning("RawSPUThread[%d]: Prxy Query Immediate.", m_index); + break; + + default: + ConLog.Error("RawSPUThread[%d]: Unknown Prxy Query Type. (prxy_query=0x%x)", m_index, value); + break; + } + + Prxy.QueryType.SetValue(0); + MFC.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); SPU.Out_MBox.SetValue(value); break; + case SPU_In_MBox_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_In_MBox, 0x%x)", m_index, value); SPU.In_MBox.SetValue(value); 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; + + default: + ConLog.Error("RawSPUThread[%d]: Write32(0x%x, 0x%x)", m_index, offset, value); + Emu.Pause(); + break; + } + + return true; +} + +bool RawSPUThread::Write64(const u64 addr, const u64 value) +{ + if(addr < GetStartAddr() + RAW_SPU_PROB_OFFSET) + { + return MemoryBlock::Write64(addr, value); + } + + u32 offset = addr - GetStartAddr() - RAW_SPU_PROB_OFFSET; + ConLog.Error("RawSPUThread[%d]: Write64(0x%x, 0x%llx)", m_index, offset, value); + Emu.Pause(); + return false; +} + +bool RawSPUThread::Write128(const u64 addr, const u128 value) +{ + if(addr < GetStartAddr() + RAW_SPU_PROB_OFFSET) + { + return MemoryBlock::Write128(addr, value); + } + + u32 offset = addr - GetStartAddr() - RAW_SPU_PROB_OFFSET; + ConLog.Error("RawSPUThread[%d]: Write128(0x%x, 0x%llx_%llx)", m_index, offset, value._u64[1], value._u64[0]); + Emu.Pause(); + return false; } void RawSPUThread::InitRegs() { - GPR[3]._u64[1] = m_args[0]; - GPR[4]._u64[1] = m_args[1]; - GPR[5]._u64[1] = m_args[2]; - GPR[6]._u64[1] = m_args[3]; + m_offset = GetStartAddr() + RAW_SPU_LS_OFFSET; + SPUThread::InitRegs(); +} - u32 num = Emu.GetCPU().GetThreadNumById(GetType(), GetId()); - - m_offset = RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * num + RAW_SPU_LS_OFFSET; - mfc.dmac.ls_offset = m_offset; - mfc.dmac.proxy_pos = 0; - mfc.dmac.queue_pos = 0; - mfc.MFC_LSA.SetAddr(GetRawSPURegAddrByNum(num, MFC_LSA_offs)); - mfc.MFC_EAH.SetAddr(GetRawSPURegAddrByNum(num, MFC_EAH_offs)); - mfc.MFC_EAL.SetAddr(GetRawSPURegAddrByNum(num, MFC_EAL_offs)); - mfc.MFC_Size_Tag.SetAddr(GetRawSPURegAddrByNum(num, MFC_Size_Tag_offs)); - mfc.MFC_CMDStatus.SetAddr(GetRawSPURegAddrByNum(num, MFC_CMDStatus_offs)); - mfc.MFC_QStatus.SetAddr(GetRawSPURegAddrByNum(num, MFC_QStatus_offs)); - mfc.Prxy_QueryType.SetAddr(GetRawSPURegAddrByNum(num, Prxy_QueryType_offs)); - mfc.Prxy_QueryMask.SetAddr(GetRawSPURegAddrByNum(num, Prxy_QueryMask_offs)); - mfc.Prxy_TagStatus.SetAddr(GetRawSPURegAddrByNum(num, Prxy_TagStatus_offs)); - mfc.SPU_Out_MBox.SetAddr(GetRawSPURegAddrByNum(num, SPU_Out_MBox_offs)); - mfc.SPU_In_MBox.SetAddr(GetRawSPURegAddrByNum(num, SPU_In_MBox_offs)); - mfc.SPU_MBox_Status.SetAddr(GetRawSPURegAddrByNum(num, SPU_MBox_Status_offs)); - mfc.SPU_RunCntl.SetAddr(GetRawSPURegAddrByNum(num, SPU_RunCntl_offs)); - mfc.SPU_Status.SetAddr(GetRawSPURegAddrByNum(num, SPU_Status_offs)); - mfc.SPU_NPC.SetAddr(GetRawSPURegAddrByNum(num, SPU_NPC_offs)); - mfc.SPU_RdSigNotify1.SetAddr(GetRawSPURegAddrByNum(num, SPU_RdSigNotify1_offs)); - mfc.SPU_RdSigNotify2.SetAddr(GetRawSPURegAddrByNum(num, SPU_RdSigNotify2_offs)); - - mfc.SPU_RunCntl.SetValue(SPU_RUNCNTL_STOP); - mfc.SPU_Status.SetValue(SPU_STATUS_RUNNING); - mfc.Prxy_QueryType.SetValue(0); - mfc.MFC_CMDStatus.SetValue(0); - PC = mfc.SPU_NPC.GetValue(); +u32 RawSPUThread::GetIndex() const +{ + return m_index; } void RawSPUThread::Task() @@ -70,27 +278,25 @@ void RawSPUThread::Task() { int status = ThreadStatus(); - if(status == PPCThread_Stopped || status == PPCThread_Break) + if(status == CPUThread_Stopped || status == CPUThread_Break) { break; } - if(status == PPCThread_Sleeping) + if(status == CPUThread_Sleeping) { Sleep(1); continue; } - mfc.Handle(); - - if(mfc.SPU_RunCntl.GetValue() != SPU_RUNCNTL_RUNNABLE) + if(SPU.RunCntl.GetValue() != SPU_RUNCNTL_RUNNABLE) { if(!is_last_paused) { - if(is_last_paused = mfc.SPU_RunCntl.GetValue() != SPU_RUNCNTL_RUNNABLE) + if(is_last_paused = SPU.RunCntl.GetValue() != SPU_RUNCNTL_RUNNABLE) { - mfc.SPU_NPC.SetValue(PC); - mfc.SPU_Status.SetValue(SPU_STATUS_WAITING_FOR_CHANNEL); + SPU.NPC.SetValue(PC); + SPU.Status.SetValue(SPU_STATUS_WAITING_FOR_CHANNEL); } } @@ -101,11 +307,11 @@ void RawSPUThread::Task() if(is_last_paused) { is_last_paused = false; - PC = mfc.SPU_NPC.GetValue(); - mfc.SPU_Status.SetValue(SPU_STATUS_RUNNING); + PC = SPU.NPC.GetValue(); + SPU.Status.SetValue(SPU_STATUS_RUNNING); } - DoCode(Memory.Read32(m_offset + PC)); + DoCode(); NextPc(); for(uint i=0; iExit(); delete m_op; } diff --git a/rpcs3/Emu/Cell/SPUDisAsm.h b/rpcs3/Emu/Cell/SPUDisAsm.h index c82b9d7a2e..ac1008273f 100644 --- a/rpcs3/Emu/Cell/SPUDisAsm.h +++ b/rpcs3/Emu/Cell/SPUDisAsm.h @@ -6,43 +6,23 @@ #include "Gui/DisAsmFrame.h" #include "Emu/Memory/Memory.h" -class SPU_DisAsm - : public SPU_Opcodes - , public PPC_DisAsm +class SPUDisAsm + : public SPUOpcodes + , public PPCDisAsm { public: - PPCThread& CPU; - - SPU_DisAsm() - : PPC_DisAsm(*(PPCThread*)NULL, DumpMode) - , CPU(*(PPCThread*)NULL) + SPUDisAsm(CPUDisAsmMode mode) : PPCDisAsm(mode) { } - SPU_DisAsm(PPCThread& cpu, DisAsmModes mode = NormalMode) - : PPC_DisAsm(cpu, mode) - , CPU(cpu) - { - } - - ~SPU_DisAsm() + ~SPUDisAsm() { } private: - void Exit() - { - if(m_mode == NormalMode && !disasm_frame->exit) - { - disasm_frame->Close(); - } - - this->~SPU_DisAsm(); - } - virtual u32 DisAsmBranchTarget(const s32 imm) { - return branchTarget(m_mode == NormalMode ? CPU.PC : dump_pc, imm); + return branchTarget(dump_pc, imm); } private: diff --git a/rpcs3/Emu/Cell/SPUInstrTable.h b/rpcs3/Emu/Cell/SPUInstrTable.h index e8446b18a4..bfbe113237 100644 --- a/rpcs3/Emu/Cell/SPUInstrTable.h +++ b/rpcs3/Emu/Cell/SPUInstrTable.h @@ -39,15 +39,15 @@ namespace SPU_instr static CodeField<18, 31> L_18_31; static CodeField<11> L_11; - static auto rrr_list = new_list(RRR); + static auto rrr_list = new_list(RRR); static auto ri18_list = new_list(rrr_list, RI18); static auto ri10_list = new_list(ri18_list, RI10); static auto ri16_list = new_list(ri10_list, RI16); static auto ri8_list = new_list(ri16_list, RI8); - static auto ri7_list = new_list(ri8_list, RI7, instr_bind(&SPU_Opcodes::UNK, GetCode, RRR, RI7)); + static auto ri7_list = new_list(ri8_list, RI7, instr_bind(&SPUOpcodes::UNK, GetCode, RRR, RI7)); #define bind_instr(list, name, ...) \ - static const auto& name = make_instr(list, #name, &SPU_Opcodes::name, ##__VA_ARGS__) + static const auto& name = make_instr(list, #name, &SPUOpcodes::name, ##__VA_ARGS__) bind_instr(ri7_list, STOP, L_18_31); bind_instr(ri7_list, LNOP); diff --git a/rpcs3/Emu/Cell/SPUInterpreter.h b/rpcs3/Emu/Cell/SPUInterpreter.h index 2097e6fe9b..0926dae80d 100644 --- a/rpcs3/Emu/Cell/SPUInterpreter.h +++ b/rpcs3/Emu/Cell/SPUInterpreter.h @@ -7,19 +7,17 @@ #define UNIMPLEMENTED() UNK(__FUNCTION__) -class SPU_Interpreter : public SPU_Opcodes +class SPUInterpreter : public SPUOpcodes { private: SPUThread& CPU; public: - SPU_Interpreter(SPUThread& cpu) : CPU(cpu) + SPUInterpreter(SPUThread& cpu) : CPU(cpu) { } private: - void Exit(){} - void SysCall() { } diff --git a/rpcs3/Emu/Cell/SPUOpcodes.h b/rpcs3/Emu/Cell/SPUOpcodes.h index e3bff38d3e..8356f962a5 100644 --- a/rpcs3/Emu/Cell/SPUOpcodes.h +++ b/rpcs3/Emu/Cell/SPUOpcodes.h @@ -226,15 +226,13 @@ namespace SPU_opcodes }; }; -class SPU_Opcodes +class SPUOpcodes { public: static u32 branchTarget(const u64 pc, const s32 imm) { return (pc + (imm << 2)) & 0x3fffc; } - - virtual void Exit()=0; //0 - 10 virtual void STOP(u32 code) = 0; diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index badacc7256..81491dec69 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -8,13 +8,18 @@ SPUThread& GetCurrentSPUThread() { PPCThread* thread = GetCurrentPPCThread(); - if(!thread || thread->GetType() == PPC_THREAD_PPU) throw wxString("GetCurrentSPUThread: bad thread"); + if(!thread || (thread->GetType() != CPU_THREAD_SPU && thread->GetType() != CPU_THREAD_RAW_SPU)) + { + throw wxString("GetCurrentSPUThread: bad thread"); + } return *(SPUThread*)thread; } -SPUThread::SPUThread(PPCThreadType type) : PPCThread(type) +SPUThread::SPUThread(CPUThreadType type) : PPCThread(type) { + assert(type == CPU_THREAD_SPU || type == CPU_THREAD_RAW_SPU); + Reset(); } @@ -24,8 +29,10 @@ SPUThread::~SPUThread() void SPUThread::DoReset() { + PPCThread::DoReset(); + //reset regs - for(u32 i=0; i<128; ++i) GPR[i].Reset(); + memset(GPR, 0, sizeof(SPU_GPR_hdr) * 128); } void SPUThread::InitRegs() @@ -35,6 +42,16 @@ void SPUThread::InitRegs() GPR[4]._u64[1] = m_args[1]; GPR[5]._u64[1] = m_args[2]; GPR[6]._u64[1] = m_args[3]; + + dmac.ls_offset = m_offset; + dmac.proxy_pos = 0; + dmac.queue_pos = 0; + + SPU.RunCntl.SetValue(SPU_RUNCNTL_STOP); + SPU.Status.SetValue(SPU_STATUS_RUNNING); + Prxy.QueryType.SetValue(0); + MFC.CMDStatus.SetValue(0); + PC = SPU.NPC.GetValue(); } u64 SPUThread::GetFreeStackSize() const @@ -47,12 +64,12 @@ void SPUThread::DoRun() switch(Ini.CPUDecoderMode.GetValue()) { case 0: - m_dec = new SPU_Decoder(*new SPU_DisAsm(*this)); + //m_dec = new SPUDecoder(*new SPUDisAsm()); break; case 1: case 2: - m_dec = new SPU_Decoder(*new SPU_Interpreter(*this)); + m_dec = new SPUDecoder(*new SPUInterpreter(*this)); break; } } @@ -71,7 +88,7 @@ void SPUThread::DoStop() m_dec = 0; } -void SPUThread::DoCode(const s32 code) +void SPUThread::DoCode() { - m_dec->Decode(code); + m_dec->Decode(Memory.Read32(m_offset + PC)); } diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index 77a260989b..63ba2a2b47 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -130,28 +130,95 @@ class SPUThread : public PPCThread { public: SPU_GPR_hdr GPR[128]; //General-Purpose Register - /* - SPUReg<1> MFC_LSA; - SPUReg<1> MFC_EAH; - SPUReg<1> MFC_EAL; - SPUReg<1> MFC_Size_Tag; - SPUReg<1> MFC_CMDStatus; - SPUReg<1> MFC_QStatus; - SPUReg<1> Prxy_QueryType; - SPUReg<1> Prxy_QueryMask; - SPUReg<1> Prxy_TagStatus; - SPUReg<1> SPU_Out_MBox; - SPUReg<4> SPU_In_MBox; - SPUReg<1> SPU_MBox_Status; - SPUReg<1> SPU_RunCntl; - SPUReg<1> SPU_Status; - SPUReg<1> SPU_NPC; - SPUReg<1> SPU_RdSigNotify1; - SPUReg<1> SPU_RdSigNotify2; - */ - SizedStack SPU_OutIntr_Mbox; + + template + class Channel + { + public: + static const size_t max_count = _max_count; + + private: + u32 m_value[max_count]; + u32 m_index; + + public: + + Channel() + { + Init(); + } + + void Init() + { + m_index = 0; + } + + __forceinline bool Pop(u32& res) + { + if(!m_index) return false; + res = m_value[--m_index]; + return true; + } + + __forceinline bool Push(u32 value) + { + if(m_index >= max_count) return false; + m_value[m_index++] = value; + return true; + } + + u32 GetCount() const + { + return m_index; + } + + u32 GetFreeCount() const + { + return max_count - m_index; + } + + void SetValue(u32 value) + { + m_value[0] = value; + } + + u32 GetValue() const + { + return m_value[0]; + } + }; + + struct + { + Channel<1> LSA; + Channel<1> EAH; + Channel<1> EAL; + Channel<1> Size_Tag; + Channel<1> CMDStatus; + Channel<1> QStatus; + } MFC; + + struct + { + Channel<1> QueryType; + Channel<1> QueryMask; + Channel<1> TagStatus; + } Prxy; + + struct + { + Channel<1> Out_MBox; + Channel<1> OutIntr_Mbox; + Channel<4> In_MBox; + Channel<1> MBox_Status; + Channel<1> RunCntl; + Channel<1> Status; + Channel<1> NPC; + Channel<1> RdSigNotify1; + Channel<1> RdSigNotify2; + } SPU; + u32 LSA; - MFC mfc; union { @@ -159,18 +226,20 @@ public: struct { u32 EAH, EAL; }; }; + DMAC dmac; + u32 GetChannelCount(u32 ch) { switch(ch) { case SPU_WrOutMbox: - return mfc.SPU_Out_MBox.GetFreeCount(); + return SPU.Out_MBox.GetFreeCount(); case SPU_RdInMbox: - return mfc.SPU_In_MBox.GetCount(); + return SPU.In_MBox.GetFreeCount(); case SPU_WrOutIntrMbox: - return 0;//return SPU_OutIntr_Mbox.GetFreeCount(); + return 0;//return SPU.OutIntr_Mbox.GetFreeCount(); default: ConLog.Error("%s error: unknown/illegal channel (%d).", __FUNCTION__, ch); @@ -188,7 +257,7 @@ public: { case SPU_WrOutIntrMbox: ConLog.Warning("SPU_WrOutIntrMbox = 0x%x", v); - if(!SPU_OutIntr_Mbox.Push(v)) + if(!SPU.OutIntr_Mbox.Push(v)) { ConLog.Warning("Not enought free rooms."); } @@ -196,11 +265,11 @@ public: case SPU_WrOutMbox: ConLog.Warning("SPU_WrOutMbox = 0x%x", v); - if(!mfc.SPU_Out_MBox.Push(v)) + if(!SPU.Out_MBox.Push(v)) { ConLog.Warning("Not enought free rooms."); } - mfc.SPU_Status.SetValue((mfc.SPU_Status.GetValue() & ~0xff) | 1); + SPU.Status.SetValue((SPU.Status.GetValue() & ~0xff) | 1); break; default: @@ -217,8 +286,8 @@ public: switch(ch) { case SPU_RdInMbox: - if(!mfc.SPU_In_MBox.Pop(v)) v = 0; - mfc.SPU_Status.SetValue((mfc.SPU_Status.GetValue() & ~0xff00) | (mfc.SPU_In_MBox.GetCount() << 8)); + if(!SPU.In_MBox.Pop(v)) v = 0; + SPU.Status.SetValue((SPU.Status.GetValue() & ~0xff00) | (SPU.In_MBox.GetCount() << 8)); break; default: @@ -241,13 +310,15 @@ public: virtual void WriteLS128(const u32 lsa, const u128& data) const { Memory.Write128(lsa + m_offset, data); } public: - SPUThread(PPCThreadType type = PPC_THREAD_SPU); + SPUThread(CPUThreadType type = CPU_THREAD_SPU); ~SPUThread(); virtual wxString RegsToString() { - wxString ret = PPCThread::RegsToString(); + wxString ret; + for(uint i=0; i<128; ++i) ret += wxString::Format("GPR[%d] = 0x%s\n", i, GPR[i].ToString()); + return ret; } @@ -262,7 +333,8 @@ public: return wxEmptyString; } - bool WriteRegString(wxString reg, wxString value) { + bool WriteRegString(wxString reg, wxString value) + { while (value.Len() < 32) value = "0"+value; if (reg.Contains("[")) { @@ -294,7 +366,7 @@ protected: virtual void DoStop(); protected: - virtual void DoCode(const s32 code); + virtual void DoCode(); }; SPUThread& GetCurrentSPUThread(); \ No newline at end of file diff --git a/rpcs3/Emu/GS/GL/FragmentProgram.cpp b/rpcs3/Emu/GS/GL/FragmentProgram.cpp index a8adf334ac..c093029007 100644 --- a/rpcs3/Emu/GS/GL/FragmentProgram.cpp +++ b/rpcs3/Emu/GS/GL/FragmentProgram.cpp @@ -72,7 +72,8 @@ void FragmentDecompilerThread::AddCode(wxString code, bool append_mask) code = "clamp(" + code + ", 0.0, 1.0)"; } - code = cond + (dst.set_cond ? AddCond(dst.fp16) : AddReg(dst.dest_reg, dst.fp16)) + mask + code = cond + (dst.set_cond ? m_parr.AddParam(PARAM_NONE , "vec4", wxString::Format(dst.fp16 ? "hc%d" : "rc%d", src0.cond_reg_index)) + : AddReg(dst.dest_reg, dst.fp16)) + mask + " = " + code + (append_mask ? mask : wxEmptyString); main += "\t" + code + ";\n"; @@ -97,20 +98,27 @@ wxString FragmentDecompilerThread::GetMask() wxString FragmentDecompilerThread::AddReg(u32 index, int fp16) { - //if(!index && !fp16) return "gl_FragColor"; - return m_parr.AddParam((index || fp16) ? PARAM_NONE : PARAM_OUT, "vec4", - wxString::Format((fp16 ? "h%u" : "r%u"), index), (index || fp16) ? -1 : 0); + /* + if(HasReg(index, fp16)) + { + return wxString::Format((fp16 ? "h%u" : "r%u"), index); + } + */ + + //ConLog.Warning("%c%d: %d %d", (fp16 ? 'h' : 'r'), index, dst.tex_num, src2.use_index_reg); + return m_parr.AddParam(fp16 ? PARAM_NONE : PARAM_OUT, "vec4", + wxString::Format((fp16 ? "h%u" : "r%u"), index), fp16 ? -1 : index); } bool FragmentDecompilerThread::HasReg(u32 index, int fp16) { - return m_parr.HasParam((index || fp16) ? PARAM_NONE : PARAM_OUT, "vec4", + return m_parr.HasParam(PARAM_OUT, "vec4", wxString::Format((fp16 ? "h%u" : "r%u"), index)); } wxString FragmentDecompilerThread::AddCond(int fp16) { - return m_parr.AddParam(PARAM_NONE , "vec4", (fp16 ? "hc" : "rc"), -1); + return m_parr.AddParam(PARAM_NONE , "vec4", wxString::Format(fp16 ? "hc%d" : "rc%d", src0.cond_mod_reg_index)); } wxString FragmentDecompilerThread::AddConst() @@ -200,11 +208,6 @@ wxString FragmentDecompilerThread::BuildCode() { wxString p = wxEmptyString; - if(!m_parr.HasParam(PARAM_OUT, "vec4", "r0") && m_parr.HasParam(PARAM_NONE, "vec4", "h0")) - { - main += "\t" + m_parr.AddParam(PARAM_OUT, "vec4", "r0", 0) + " = " + "h0;\n"; - } - for(u32 i=0; iFlip(); - //glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } m_gcm_current_buffer = args[0]; @@ -773,54 +770,9 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u m_surface_offset_b = args[4]; m_surface_pitch_b = args[5]; - m_depth_offset = m_surface_offset_z; - gcmBuffer* buffers = (gcmBuffer*)Memory.GetMemFromAddr(m_gcm_buffers_addr); m_width = re(buffers[m_gcm_current_buffer].width); m_height = re(buffers[m_gcm_current_buffer].height); - - break; - m_rbo.Create(2); - checkForGlError("m_rbo.Create"); - m_rbo.Bind(0); - m_rbo.Storage(GL_RGBA, m_width, m_height); - checkForGlError("m_rbo.Storage(GL_RGBA)"); - m_rbo.Bind(1); - - switch(m_surface_depth_format) - { - case 1: - m_rbo.Storage(GL_DEPTH_COMPONENT16, m_width, m_height); - break; - - case 2: - m_rbo.Storage(GL_DEPTH24_STENCIL8, m_width, m_height); - break; - - default: - ConLog.Error("Bad depth format! (%d)", m_surface_depth_format); - assert(0); - break; - } - checkForGlError("m_rbo.Storage(GL_DEPTH24_STENCIL8)"); - m_fbo.Create(); - checkForGlError("m_fbo.Create"); - m_fbo.Bind(); - m_fbo.Renderbuffer(GL_COLOR_ATTACHMENT0, m_rbo.GetId(0)); - checkForGlError("m_fbo.Renderbuffer(GL_COLOR_ATTACHMENT0)"); - - if(m_surface_depth_format == 2) - { - m_fbo.Renderbuffer(GL_DEPTH_STENCIL_ATTACHMENT, m_rbo.GetId(1)); - checkForGlError("m_fbo.Renderbuffer(GL_DEPTH_STENCIL_ATTACHMENT)"); - } - else - { - m_fbo.Renderbuffer(GL_DEPTH_ATTACHMENT, m_rbo.GetId(1)); - checkForGlError("m_fbo.Renderbuffer(GL_DEPTH_STENCIL_ATTACHMENT)"); - } - //CMD_LOG("color_format=%d, depth_format=%d, type=%d, antialias=%d, width=%d, height=%d, pitch_a=%d, offset_a=0x%x, offset_z=0x%x, offset_b=0x%x, pitch_b=%d", - // color_format, depth_format, type, antialias, width, height, pitch_a, offset_a, offset_z, offset_b, pitch_b); } break; @@ -928,15 +880,16 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u case NV4097_CLEAR_SURFACE: { - if(m_set_clear_surface) - { - m_clear_surface_mask |= args[0]; - } - else - { - m_clear_surface_mask = args[0]; - m_set_clear_surface = true; - } + u32 a0 = args[0]; + + if(a0 & 0x01) m_clear_surface_z = m_clear_z; + if(a0 & 0x02) m_clear_surface_s = m_clear_s; + if(a0 & 0x10) m_clear_surface_color_r = m_clear_color_r; + if(a0 & 0x20) m_clear_surface_color_g = m_clear_color_g; + if(a0 & 0x40) m_clear_surface_color_b = m_clear_color_b; + if(a0 & 0x80) m_clear_surface_color_a = m_clear_color_a; + + m_clear_surface_mask |= a0; } break; @@ -1082,18 +1035,10 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u case NV4097_SET_COLOR_CLEAR_VALUE: { const u32 color = args[0]; - //m_set_clear_color = true; m_clear_color_a = (color >> 24) & 0xff; m_clear_color_r = (color >> 16) & 0xff; m_clear_color_g = (color >> 8) & 0xff; m_clear_color_b = color & 0xff; - - glClearColor( - m_clear_color_r / 255.0f, - m_clear_color_g / 255.0f, - m_clear_color_b / 255.0f, - m_clear_color_a / 255.0f); - checkForGlError("glClearColor"); } break; @@ -1452,6 +1397,12 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u { m_set_context_dma_color_c = true; m_context_dma_color_c = args[0]; + + if(count > 1) + { + m_set_context_dma_color_d = true; + m_context_dma_color_d = args[1]; + } } break; @@ -1461,7 +1412,7 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u m_context_dma_z = args[0]; } break; - + /* case NV4097_SET_SURFACE_PITCH_A: { //TODO @@ -1473,22 +1424,34 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u //TODO } break; - + */ case NV4097_SET_SURFACE_PITCH_C: { - //TODO + if(count != 4) + { + ConLog.Error("NV4097_SET_SURFACE_PITCH_C: Bad count (%d)", count); + break; + } + + m_surface_pitch_c = args[0]; + m_surface_pitch_d = args[1]; + m_surface_offset_c = args[2]; + m_surface_offset_d = args[3]; } break; case NV4097_SET_SURFACE_PITCH_Z: { - m_depth_pitch = args[0]; + m_surface_pitch_z = args[0]; } break; case NV4097_SET_SHADER_WINDOW: { - //TODO + u32 a0 = args[0]; + m_shader_window_height = a0 & 0xfff; + m_shader_window_origin = (a0 >> 12) & 0xf; + m_shader_window_pixel_centers = a0 >> 16; } break; @@ -1527,7 +1490,7 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u case NV4097_SET_SURFACE_COLOR_TARGET: { - //TODO + m_surface_colour_target = args[0]; } break; @@ -1553,10 +1516,9 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u case NV4097_SET_ZSTENCIL_CLEAR_VALUE: { - u32 clear_valuei = args[0]; - double clear_valuef = (double)clear_valuei / 0xffffffff; - glClearDepth(clear_valuef); - glClearStencil(clear_valuei); + u32 a0 = args[0]; + m_clear_s = a0 & 0xff; + m_clear_z = a0 >> 8; } break; @@ -1877,59 +1839,251 @@ void GLGSRender::WriteDepthBuffer() return; } - u32 address = GetAddress(m_depth_offset, m_context_dma_z - 0xfeed0000); + u32 address = GetAddress(m_surface_offset_z, m_context_dma_z - 0xfeed0000); if(!Memory.IsGoodAddr(address)) { - ConLog.Warning("Bad depth address: address=0x%x, offset=0x%x, dma=0x%x", address, m_depth_offset, m_context_dma_z); + ConLog.Warning("Bad depth address: address=0x%x, offset=0x%x, dma=0x%x", address, m_surface_offset_z, m_context_dma_z); return; } - u8* dst = &Memory[address]; - //m_fbo.Bind(GL_READ_FRAMEBUFFER); - //glPixelStorei(GL_PACK_ROW_LENGTH, m_depth_pitch); + glReadPixels(0, 0, m_width, m_height, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, &Memory[address]); + checkForGlError("glReadPixels"); - m_fbo.Bind(GL_READ_FRAMEBUFFER); GLuint depth_tex; glGenTextures(1, &depth_tex); glBindTexture(GL_TEXTURE_2D, depth_tex); - glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, 0, 0, m_width, m_height, 0); - checkForGlError("glCopyTexImage2D"); - glGetTexImage(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, GL_FLOAT, dst); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, &Memory[address]); + checkForGlError("glTexImage2D"); + glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, &Memory[address]); checkForGlError("glGetTexImage"); glDeleteTextures(1, &depth_tex); - wxFile f("depth.raw", wxFile::write); - f.Write(dst, m_width * m_height * 4); - m_fbo.Bind(); - /* - GLBufferObject pbo; - pbo.Create(GL_PIXEL_PACK_BUFFER); - pbo.Bind(); - glReadPixels(0, 0, m_width, m_height, GL_DEPTH_COMPONENT, GL_FLOAT, 0); - GLuint *src = (GLuint*)glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY); - if(src) +} + +void GLGSRender::WriteColourBufferA() +{ + if(!m_set_context_dma_color_a) { - wxFile f("depth.raw", wxFile::write); - f.Write(src, m_width * m_height * 4); - memcpy(dst, src, m_width * m_height * 4); - glUnmapBuffer(GL_PIXEL_PACK_BUFFER); + return; } - else + + u32 address = GetAddress(m_surface_offset_a, m_context_dma_color_a - 0xfeed0000); + if(!Memory.IsGoodAddr(address)) { - ConLog.Error("glMapBuffer failed."); + ConLog.Warning("Bad colour buffer a address: address=0x%x, offset=0x%x, dma=0x%x", address, m_surface_offset_a, m_context_dma_color_a); + return; + } + + glReadBuffer(GL_COLOR_ATTACHMENT0); + checkForGlError("glReadBuffer(GL_COLOR_ATTACHMENT0)"); + glReadPixels(0, 0, m_width, m_height, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, &Memory[address]); + checkForGlError("glReadPixels(GL_RGBA, GL_UNSIGNED_INT_8_8_8_8)"); +} + +void GLGSRender::WriteColourBufferB() +{ + if(!m_set_context_dma_color_b) + { + return; + } + + u32 address = GetAddress(m_surface_offset_b, m_context_dma_color_b - 0xfeed0000); + if(!Memory.IsGoodAddr(address)) + { + ConLog.Warning("Bad colour buffer b address: address=0x%x, offset=0x%x, dma=0x%x", address, m_surface_offset_b, m_context_dma_color_b); + return; + } + + glReadBuffer(GL_COLOR_ATTACHMENT1); + checkForGlError("glReadBuffer(GL_COLOR_ATTACHMENT1)"); + glReadPixels(0, 0, m_width, m_height, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, &Memory[address]); + checkForGlError("glReadPixels(GL_RGBA, GL_UNSIGNED_INT_8_8_8_8)"); +} + +void GLGSRender::WriteColourBufferC() +{ + if(!m_set_context_dma_color_c) + { + return; + } + + u32 address = GetAddress(m_surface_offset_c, m_context_dma_color_c - 0xfeed0000); + if(!Memory.IsGoodAddr(address)) + { + ConLog.Warning("Bad colour buffer c address: address=0x%x, offset=0x%x, dma=0x%x", address, m_surface_offset_c, m_context_dma_color_c); + return; + } + + glReadBuffer(GL_COLOR_ATTACHMENT2); + checkForGlError("glReadBuffer(GL_COLOR_ATTACHMENT2)"); + glReadPixels(0, 0, m_width, m_height, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, &Memory[address]); + checkForGlError("glReadPixels(GL_RGBA, GL_UNSIGNED_INT_8_8_8_8)"); +} + +void GLGSRender::WriteColourBufferD() +{ + if(!m_set_context_dma_color_d) + { + return; + } + + u32 address = GetAddress(m_surface_offset_d, m_context_dma_color_d - 0xfeed0000); + if(!Memory.IsGoodAddr(address)) + { + ConLog.Warning("Bad colour buffer d address: address=0x%x, offset=0x%x, dma=0x%x", address, m_surface_offset_d, m_context_dma_color_d); + return; + } + + glReadBuffer(GL_COLOR_ATTACHMENT3); + checkForGlError("glReadBuffer(GL_COLOR_ATTACHMENT3)"); + glReadPixels(0, 0, m_width, m_height, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, &Memory[address]); + checkForGlError("glReadPixels(GL_RGBA, GL_UNSIGNED_INT_8_8_8_8)"); +} + +void GLGSRender::WriteBuffers() +{ + glPixelStorei(GL_PACK_ROW_LENGTH, 0); + glPixelStorei(GL_PACK_ALIGNMENT, 4); + + switch(m_surface_colour_target) + { + case 0x0: + return; + + case 0x1: + WriteColourBufferA(); + break; + + case 0x2: + WriteColourBufferB(); + break; + + case 0x13: + WriteColourBufferA(); + WriteColourBufferB(); + break; + + case 0x17: + WriteColourBufferA(); + WriteColourBufferB(); + WriteColourBufferC(); + break; + + case 0x1f: + WriteColourBufferA(); + WriteColourBufferB(); + WriteColourBufferC(); + WriteColourBufferD(); + break; } - pbo.UnBind(); - pbo.Delete(); - */ - Emu.Pause(); } void GLGSRender::ExecCMD() { if(LoadProgram()) { - if(m_set_surface_clip_horizontal && m_set_surface_clip_vertical) + static int last_width = 0, last_height = 0, last_depth_format = 0; + + if(m_width != last_width || m_height != last_height || last_depth_format != m_surface_depth_format) { - //ConLog.Write("surface clip width: %d, height: %d, x: %d, y: %d", m_width, m_height, m_surface_clip_x, m_surface_clip_y); + ConLog.Warning("New FBO (%dx%d)", m_width, m_height); + last_width = m_width; + last_height = m_height; + last_depth_format = m_surface_depth_format; + + m_fbo.Create(); + checkForGlError("m_fbo.Create"); + m_fbo.Bind(); + + m_rbo.Create(4 + 1); + checkForGlError("m_rbo.Create"); + + for(int i=0; i<4; ++i) + { + m_rbo.Bind(i); + m_rbo.Storage(GL_RGBA, m_width, m_height); + checkForGlError("m_rbo.Storage(GL_RGBA)"); + } + + m_rbo.Bind(4); + + switch(m_surface_depth_format) + { + case 1: + m_rbo.Storage(GL_DEPTH_COMPONENT16, m_width, m_height); + checkForGlError("m_rbo.Storage(GL_DEPTH_COMPONENT16)"); + break; + + case 2: + m_rbo.Storage(GL_DEPTH24_STENCIL8, m_width, m_height); + checkForGlError("m_rbo.Storage(GL_DEPTH24_STENCIL8)"); + break; + + default: + ConLog.Error("Bad depth format! (%d)", m_surface_depth_format); + assert(0); + break; + } + + for(int i=0; i<4; ++i) + { + m_fbo.Renderbuffer(GL_COLOR_ATTACHMENT0 + i, m_rbo.GetId(i)); + checkForGlError(wxString::Format("m_fbo.Renderbuffer(GL_COLOR_ATTACHMENT%d)", i)); + } + + m_fbo.Renderbuffer(GL_DEPTH_ATTACHMENT, m_rbo.GetId(4)); + checkForGlError("m_fbo.Renderbuffer(GL_DEPTH_ATTACHMENT)"); + + if(m_surface_depth_format == 2) + { + m_fbo.Renderbuffer(GL_STENCIL_ATTACHMENT, m_rbo.GetId(4)); + checkForGlError("m_fbo.Renderbuffer(GL_STENCIL_ATTACHMENT)"); + } + } + + if(!m_set_surface_clip_horizontal) + { + m_surface_clip_x = 0; + m_surface_clip_w = m_width; + } + + if(!m_set_surface_clip_vertical) + { + m_surface_clip_y = 0; + m_surface_clip_h = m_height; + } + + m_fbo.Bind(); + WriteDepthBuffer(); + static const GLenum draw_buffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3 }; + + switch(m_surface_colour_target) + { + case 0x0: + break; + + case 0x1: + glDrawBuffer(draw_buffers[0]); + break; + + case 0x2: + glDrawBuffer(draw_buffers[1]); + break; + + case 0x13: + glDrawBuffers(2, draw_buffers); + break; + + case 0x17: + glDrawBuffers(3, draw_buffers); + break; + + case 0x1f: + glDrawBuffers(4, draw_buffers); + break; + + default: + ConLog.Error("Bad surface colour target: %d", m_surface_colour_target); + break; } if(m_set_color_mask) @@ -1950,21 +2104,35 @@ void GLGSRender::ExecCMD() checkForGlError("glScissor"); } - if(m_set_clear_color) - { - glClearColor( - m_clear_color_r / 255.0f, - m_clear_color_g / 255.0f, - m_clear_color_b / 255.0f, - m_clear_color_a / 255.0f); - } - - if(m_set_clear_surface) + if(m_clear_surface_mask) { GLbitfield f = 0; - if (m_clear_surface_mask & 0x1) f |= GL_DEPTH_BUFFER_BIT; - if (m_clear_surface_mask & 0x2) f |= GL_STENCIL_BUFFER_BIT; - if ((m_clear_surface_mask & 0xF0) == 0xF0) f |= GL_COLOR_BUFFER_BIT; + + if (m_clear_surface_mask & 0x1) + { + glClearDepth(m_clear_surface_z / (float)0xffffff); + + f |= GL_DEPTH_BUFFER_BIT; + } + + if (m_clear_surface_mask & 0x2) + { + glClearStencil(m_clear_surface_s); + + f |= GL_STENCIL_BUFFER_BIT; + } + + if (m_clear_surface_mask & 0xF0) + { + glClearColor( + m_clear_surface_color_r / 255.0f, + m_clear_surface_color_g / 255.0f, + m_clear_surface_color_b / 255.0f, + m_clear_surface_color_a / 255.0f); + + f |= GL_COLOR_BUFFER_BIT; + } + glClear(f); } @@ -1984,7 +2152,6 @@ void GLGSRender::ExecCMD() Enable(m_set_stencil_test, GL_STENCIL_TEST); Enable(m_set_line_smooth, GL_LINE_SMOOTH); Enable(m_set_poly_smooth, GL_POLYGON_SMOOTH); - checkForGlError("glEnable"); if(m_set_clip_plane) { @@ -1998,26 +2165,28 @@ void GLGSRender::ExecCMD() checkForGlError("m_set_clip_plane"); } - if(m_set_stencil_fail && m_set_stencil_zfail && m_set_stencil_zpass) - { - glStencilOp(m_stencil_fail, m_stencil_zfail, m_stencil_zpass); - checkForGlError("glStencilOp"); - } - - if(m_set_stencil_mask) - { - glStencilMask(m_stencil_mask); - checkForGlError("glStencilMask"); - } - - if(m_set_stencil_func && m_set_stencil_func_ref && m_set_stencil_func_mask) - { - glStencilFunc(m_stencil_func, m_stencil_func_ref, m_stencil_func_mask); - checkForGlError("glStencilFunc"); - } + checkForGlError("glEnable"); if(m_set_two_sided_stencil_test_enable) { + if(m_set_stencil_fail && m_set_stencil_zfail && m_set_stencil_zpass) + { + glStencilOpSeparate(GL_FRONT, m_stencil_fail, m_stencil_zfail, m_stencil_zpass); + checkForGlError("glStencilOpSeparate"); + } + + if(m_set_stencil_mask) + { + glStencilMaskSeparate(GL_FRONT, m_stencil_mask); + checkForGlError("glStencilMaskSeparate"); + } + + if(m_set_stencil_func && m_set_stencil_func_ref && m_set_stencil_func_mask) + { + glStencilFuncSeparate(GL_FRONT, m_stencil_func, m_stencil_func_ref, m_stencil_func_mask); + checkForGlError("glStencilFuncSeparate"); + } + if(m_set_back_stencil_fail && m_set_back_stencil_zfail && m_set_back_stencil_zpass) { glStencilOpSeparate(GL_BACK, m_back_stencil_fail, m_back_stencil_zfail, m_back_stencil_zpass); @@ -2036,6 +2205,26 @@ void GLGSRender::ExecCMD() checkForGlError("glStencilFuncSeparate(GL_BACK)"); } } + else + { + if(m_set_stencil_fail && m_set_stencil_zfail && m_set_stencil_zpass) + { + glStencilOp(m_stencil_fail, m_stencil_zfail, m_stencil_zpass); + checkForGlError("glStencilOp"); + } + + if(m_set_stencil_mask) + { + glStencilMask(m_stencil_mask); + checkForGlError("glStencilMask"); + } + + if(m_set_stencil_func && m_set_stencil_func_ref && m_set_stencil_func_mask) + { + glStencilFunc(m_stencil_func, m_stencil_func_ref, m_stencil_func_mask); + checkForGlError("glStencilFunc"); + } + } if(m_set_shade_mode) { @@ -2176,7 +2365,7 @@ void GLGSRender::ExecCMD() m_fragment_constants.Clear(); - //WriteDepthBuffer(); + WriteBuffers(); } else { diff --git a/rpcs3/Emu/GS/GL/GLGSRender.h b/rpcs3/Emu/GS/GL/GLGSRender.h index cf23ab5444..2b307d4cf3 100644 --- a/rpcs3/Emu/GS/GL/GLGSRender.h +++ b/rpcs3/Emu/GS/GL/GLGSRender.h @@ -189,11 +189,10 @@ public: //TODO: safe init checkForGlError("GLTexture::Init() -> glBindTexture"); - glPixelStorei(GL_PACK_ROW_LENGTH, m_pitch); - int format = m_format & ~(0x20 | 0x40); bool is_swizzled = (m_format & 0x20) == 0; + glPixelStorei(GL_PACK_ALIGNMENT, m_pitch); char* pixels = (char*)Memory.GetMemFromAddr(m_offset); switch(format) @@ -267,10 +266,8 @@ public: default: ConLog.Error("Init tex error: Bad tex format (0x%x | 0x%x | 0x%x)", format, m_format & 0x20, m_format & 0x40); break; } - if(m_mipmap > 1) - { - glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); - } + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, m_mipmap - 1); + glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, m_mipmap > 1); if(format != 0x81 && format != 0x94) { @@ -292,7 +289,7 @@ public: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, gl_remap[remap_g]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, gl_remap[remap_b]); } - + static const int gl_tex_zfunc[] = { GL_NEVER, @@ -304,17 +301,16 @@ public: GL_GEQUAL, GL_ALWAYS, }; - + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GetGlWrap(m_wraps)); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GetGlWrap(m_wrapt)); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GetGlWrap(m_wrapr)); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, gl_tex_zfunc[m_zfunc]); - - glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, m_bias); + + glTexEnvi(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, m_bias); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, m_minlod); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, m_maxlod); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, m_maxaniso); - + static const int gl_tex_filter[] = { GL_NEAREST, @@ -496,6 +492,105 @@ struct GLRSXThread : public ThreadBase virtual void Task(); }; +class PostDrawObj +{ +protected: + ShaderProgram m_fp; + VertexProgram m_vp; + Program m_program; + GLfbo m_fbo; + GLrbo m_rbo; + +public: + virtual void Draw() + { + static bool s_is_initialized = false; + + if(!s_is_initialized) + { + s_is_initialized = true; + Initialize(); + } + } + + virtual void InitializeShaders() = 0; + virtual void InitializeLocations() = 0; + + void Initialize() + { + InitializeShaders(); + m_fp.Compile(); + m_vp.Compile(); + m_program.Create(m_vp.id, m_fp.id); + m_program.Use(); + InitializeLocations(); + } +}; + +class DrawCursorObj : PostDrawObj +{ + u32 m_tex_id; + +public: + DrawCursorObj() : m_tex_id(0) + { + } + + virtual void Draw() + { + PostDrawObj::Draw(); + } + + virtual void InitializeShaders() + { + m_vp.shader = + "layout (location = 0) in vec4 in_pos;\n" + "layout (location = 1) in vec2 in_tc;\n" + "out vec2 tc;\n" + "\n" + "void main()\n" + "{\n" + " tc = in_tc;\n" + " gl_Position = in_pos;\n" + "}\n"; + + m_fp.shader = + "#version 330\n" + "\n" + "in vec2 tc;\n" + "uniform sampler2D tex;\n" + "layout (location = 0) out vec4 res;\n" + "\n" + "void main()\n" + "{\n" + " res = texture(tex, tc);\n" + "}\n"; + } + + void SetTexture(void* pixels, int width, int hight) + { + glUniform2i(1, width, hight); + if(!m_tex_id) + { + glGenTextures(1, &m_tex_id); + } + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, m_tex_id); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, hight, 0, GL_BLUE, GL_UNSIGNED_BYTE, pixels); + m_program.SetTex(0); + } + + void SetPosition(float x, float y, float z = 0.0f) + { + glUniform4f(0, x, y, z, 1.0f); + } + + void InitializeLocations() + { + } +}; + class GLGSRender : public wxWindow , public GSRender @@ -520,6 +615,7 @@ private: VertexProgram* m_cur_vertex_prog; Array m_transform_constants; Array m_fragment_constants; + ArrayF m_post_draw_objs; Program m_program; int m_fp_buf_num; @@ -557,6 +653,13 @@ private: virtual void Close(); bool LoadProgram(); void WriteDepthBuffer(); + void WriteColourBufferA(); + void WriteColourBufferB(); + void WriteColourBufferC(); + void WriteColourBufferD(); + void WriteBuffers(); + + void DrawObjects(); public: void DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u32 count); diff --git a/rpcs3/Emu/GS/GL/GLProcTable.tbl b/rpcs3/Emu/GS/GL/GLProcTable.tbl index 6aeb2c8be4..ca6f1ca1f2 100644 --- a/rpcs3/Emu/GS/GL/GLProcTable.tbl +++ b/rpcs3/Emu/GS/GL/GLProcTable.tbl @@ -25,7 +25,7 @@ OPENGL_PROC(PFNGLDELETEPROGRAMPROC, DeleteProgram); OPENGL_PROC(PFNGLATTACHSHADERPROC, AttachShader); OPENGL_PROC(PFNGLGETATTRIBLOCATIONPROC, GetAttribLocation); OPENGL_PROC(PFNGLLINKPROGRAMPROC, LinkProgram); -OPENGL_PROC(PFNGLBINDFRAGDATALOCATIONPROC, BindFragDataLocation); +//OPENGL_PROC(PFNGLBINDFRAGDATALOCATIONPROC, BindFragDataLocation); OPENGL_PROC(PFNGLBINDATTRIBLOCATIONPROC, BindAttribLocation); OPENGL_PROC(PFNGLGETUNIFORMLOCATIONPROC, GetUniformLocation); OPENGL_PROC(PFNGLGETPROGRAMIVPROC, GetProgramiv); @@ -38,6 +38,9 @@ OPENGL_PROC(PFNGLVERTEXATTRIB3SVPROC, VertexAttrib3sv); OPENGL_PROC(PFNGLVERTEXATTRIB4SVPROC, VertexAttrib4sv); OPENGL_PROC(PFNGLVERTEXATTRIB4IVPROC, VertexAttrib4iv); OPENGL_PROC(PFNGLVERTEXATTRIB1FPROC, VertexAttrib1f); +OPENGL_PROC(PFNGLVERTEXATTRIB2FPROC, VertexAttrib2f); +OPENGL_PROC(PFNGLVERTEXATTRIB3FPROC, VertexAttrib3f); +OPENGL_PROC(PFNGLVERTEXATTRIB4FPROC, VertexAttrib4f); OPENGL_PROC(PFNGLVERTEXATTRIB2FVPROC, VertexAttrib2fv); OPENGL_PROC(PFNGLVERTEXATTRIB3FVPROC, VertexAttrib3fv); OPENGL_PROC(PFNGLVERTEXATTRIB4FVPROC, VertexAttrib4fv); @@ -95,4 +98,5 @@ OPENGL_PROC(PFNGLFRAMEBUFFERTEXTURE1DPROC, FramebufferTexture1D); OPENGL_PROC(PFNGLFRAMEBUFFERTEXTURE2DPROC, FramebufferTexture2D); OPENGL_PROC(PFNGLFRAMEBUFFERTEXTURE3DPROC, FramebufferTexture3D); OPENGL_PROC(PFNGLFRAMEBUFFERRENDERBUFFERPROC, FramebufferRenderbuffer); -OPENGL_PROC(PFNGLBLITFRAMEBUFFERPROC, BlitFramebuffer); \ No newline at end of file +OPENGL_PROC(PFNGLBLITFRAMEBUFFERPROC, BlitFramebuffer); +OPENGL_PROC(PFNGLDRAWBUFFERSPROC, DrawBuffers); \ No newline at end of file diff --git a/rpcs3/Emu/GS/GL/VertexProgram.cpp b/rpcs3/Emu/GS/GL/VertexProgram.cpp index bec0ae6e98..100e88fa53 100644 --- a/rpcs3/Emu/GS/GL/VertexProgram.cpp +++ b/rpcs3/Emu/GS/GL/VertexProgram.cpp @@ -295,10 +295,10 @@ void VertexDecompilerThread::Task() case 0x02: AddVecCode("(" + GetSRC(0) + " * " + GetSRC(1) + ")"); break; //MUL case 0x03: AddVecCode("(" + GetSRC(0) + " + " + GetSRC(2) + ")"); break; //ADD case 0x04: AddVecCode("(" + GetSRC(0) + " * " + GetSRC(1) + " + " + GetSRC(2) + ")"); break; //MAD - case 0x05: AddVecCode("vec4(dot(" + GetSRC(0) + ".xyz, " + GetSRC(1) + ".xyz), 0, 0, 0).xxxx"); break; //DP3 - case 0x06: AddVecCode("vec4(dot(vec4(" + GetSRC(0) + ".xyz, 1), " + GetSRC(1) + "), 0, 0, 0).xxxx"); break; //DPH - case 0x07: AddVecCode("vec4(dot(" + GetSRC(0) + ", " + GetSRC(1) + "), 0, 0, 0).xxxx"); break; //DP4 - case 0x08: AddVecCode("vec4(distance(" + GetSRC(0) + ", " + GetSRC(1) + "), 0, 0, 0).xxxx"); break; //DST + case 0x05: AddVecCode("vec2(dot(" + GetSRC(0) + ".xyz, " + GetSRC(1) + ".xyz), 0).xxxx"); break; //DP3 + case 0x06: AddVecCode("vec2(dot(vec4(" + GetSRC(0) + ".xyz, 1), " + GetSRC(1) + "), 0).xxxx"); break; //DPH + case 0x07: AddVecCode("vec2(dot(" + GetSRC(0) + ", " + GetSRC(1) + "), 0).xxxx"); break; //DP4 + case 0x08: AddVecCode("vec2(distance(" + GetSRC(0) + ", " + GetSRC(1) + "), 0).xxxx"); break; //DST case 0x09: AddVecCode("min(" + GetSRC(0) + ", " + GetSRC(1) + ")"); break; //MIN case 0x0a: AddVecCode("max(" + GetSRC(0) + ", " + GetSRC(1) + ")"); break; //MAX case 0x0b: AddVecCode("vec4(lessThan(" + GetSRC(0) + ", " + GetSRC(1) + "))"); break; //SLT @@ -306,11 +306,11 @@ void VertexDecompilerThread::Task() case 0x0e: AddVecCode("fract(" + GetSRC(0) + ")"); break; //FRC case 0x0f: AddVecCode("floor(" + GetSRC(0) + ")"); break; //FLR case 0x10: AddVecCode("vec4(equal(" + GetSRC(0) + ", " + GetSRC(1) + "))"); break; //SEQ - //case 0x11: AddVecCode("vec4(0.0f, 0.0f, 0.0f, 0.0f)"); break; //SFL + //case 0x11: AddVecCode("vec4(equal(" + GetSRC(0) + ", vec4(0, 0, 0, 0)))"); break; //SFL case 0x12: AddVecCode("vec4(greaterThan(" + GetSRC(0) + ", " + GetSRC(1) + "))"); break; //SGT case 0x13: AddVecCode("vec4(lessThanEqual(" + GetSRC(0) + ", " + GetSRC(1) + "))"); break; //SLE case 0x14: AddVecCode("vec4(notEqual(" + GetSRC(0) + ", " + GetSRC(1) + "))"); break; //SNE - //case 0x15: AddVecCode("vec4(1.0f, 1.0f, 1.0f, 1.0f)"); break; //STR + //case 0x15: AddVecCode("vec4(notEqual(" + GetSRC(0) + ", vec4(0, 0, 0, 0)))"); break; //STR case 0x16: AddVecCode("sign(" + GetSRC(0) + ")"); break; //SSG default: diff --git a/rpcs3/Emu/GS/RSXThread.h b/rpcs3/Emu/GS/RSXThread.h index 4705dfd354..1333d31a5c 100644 --- a/rpcs3/Emu/GS/RSXThread.h +++ b/rpcs3/Emu/GS/RSXThread.h @@ -45,8 +45,9 @@ public: bool m_set_front_polygon_mode; u32 m_front_polygon_mode; - bool m_set_clear_surface; u32 m_clear_surface_mask; + u32 m_clear_surface_z; + u8 m_clear_surface_s; u8 m_clear_surface_color_r; u8 m_clear_surface_color_g; u8 m_clear_surface_color_b; @@ -123,11 +124,12 @@ public: u8 m_blend_color_b; u8 m_blend_color_a; - bool m_set_clear_color; u8 m_clear_color_r; u8 m_clear_color_g; u8 m_clear_color_b; u8 m_clear_color_a; + u8 m_clear_s; + u32 m_clear_z; u32 m_context_dma_img_src; u32 m_context_dma_img_dst; @@ -175,11 +177,6 @@ public: u8 m_surface_antialias; u8 m_surface_width; u8 m_surface_height; - u32 m_surface_pitch_a; - u32 m_surface_offset_a; - u32 m_surface_offset_z; - u32 m_surface_offset_b; - u32 m_surface_pitch_b; bool m_set_context_dma_color_a; u32 m_context_dma_color_a; @@ -190,6 +187,9 @@ public: bool m_set_context_dma_color_c; u32 m_context_dma_color_c; + bool m_set_context_dma_color_d; + u32 m_context_dma_color_d; + bool m_set_context_dma_z; u32 m_context_dma_z; @@ -209,8 +209,23 @@ public: bool m_set_alpha_ref; u32 m_alpha_ref; - u32 m_depth_offset; - u32 m_depth_pitch; + u32 m_surface_pitch_a; + u32 m_surface_pitch_b; + u32 m_surface_pitch_c; + u32 m_surface_pitch_d; + u32 m_surface_pitch_z; + + u32 m_surface_offset_a; + u32 m_surface_offset_b; + u32 m_surface_offset_c; + u32 m_surface_offset_d; + u32 m_surface_offset_z; + + u16 m_shader_window_height; + u8 m_shader_window_origin; + u16 m_shader_window_pixel_centers; + + u32 m_surface_colour_target; u8 m_begin_end; @@ -227,6 +242,14 @@ public: m_set_stencil_test = false; m_set_line_smooth = false; m_set_poly_smooth = false; + m_set_two_sided_stencil_test_enable = false; + m_set_surface_clip_horizontal = false; + m_set_surface_clip_vertical = false; + + m_clear_color_r = 0; + m_clear_color_g = 0; + m_clear_color_b = 0; + m_clear_color_a = 0; Reset(); } @@ -241,7 +264,7 @@ public: m_set_scissor_horizontal = false; m_set_scissor_vertical = false; m_set_front_polygon_mode = false; - m_set_clear_surface = false; + m_clear_surface_mask = 0; m_set_blend_sfactor = false; m_set_blend_dfactor = false; m_set_stencil_mask = false; @@ -251,7 +274,6 @@ public: m_set_stencil_fail = false; m_set_stencil_zfail = false; m_set_stencil_zpass = false; - m_set_two_sided_stencil_test_enable = false; m_set_back_stencil_mask = false; m_set_back_stencil_func = false; m_set_back_stencil_func_ref = false; @@ -264,7 +286,6 @@ public: m_set_line_width = false; m_set_shade_mode = false; m_set_blend_color = false; - m_set_clear_color = false; m_set_semaphore_offset = false; m_set_fog_mode = false; m_set_fog_params = false; @@ -273,9 +294,8 @@ public: m_set_context_dma_color_a = false; m_set_context_dma_color_b = false; m_set_context_dma_color_c = false; + m_set_context_dma_color_d = false; m_set_context_dma_z = false; - m_set_surface_clip_horizontal = false; - m_set_surface_clip_vertical = false; m_set_cull_face = false; m_set_alpha_func = false; m_set_alpha_ref = false; diff --git a/rpcs3/Emu/Memory/Memory.cpp b/rpcs3/Emu/Memory/Memory.cpp index 60d60a838b..92e2160a24 100644 --- a/rpcs3/Emu/Memory/Memory.cpp +++ b/rpcs3/Emu/Memory/Memory.cpp @@ -466,52 +466,24 @@ u8* DynamicMemoryBlock::GetMem(u64 addr) const return nullptr; } -#define DEBUG_RAWSPU_MEM 1 //MemoryBase void MemoryBase::Write8(u64 addr, const u8 data) { -#if DEBUG_RAWSPU_MEM - if(SpuRawMem.IsMyAddress(addr)) - { - ConLog.Warning("Write8(addr=0x%llx,data=0x%x)", addr, data); - } -#endif GetMemByAddr(addr).Write8(addr, data); } void MemoryBase::Write16(u64 addr, const u16 data) { -#if DEBUG_RAWSPU_MEM - if(SpuRawMem.IsMyAddress(addr)) - { - ConLog.Warning("Write16(addr=0x%llx,data=0x%x)", addr, data); - } -#endif - GetMemByAddr(addr).Write16(addr, data); } void MemoryBase::Write32(u64 addr, const u32 data) { -#if DEBUG_RAWSPU_MEM - if(SpuRawMem.IsMyAddress(addr)) - { - ConLog.Warning("Write32(addr=0x%llx,data=0x%x)", addr, data); - } -#endif - GetMemByAddr(addr).Write32(addr, data); } void MemoryBase::Write64(u64 addr, const u64 data) { -#if DEBUG_RAWSPU_MEM - if(SpuRawMem.IsMyAddress(addr)) - { - ConLog.Warning("Write64(addr=0x%llx,data=0x%llx)", addr, data); - } -#endif - GetMemByAddr(addr).Write64(addr, data); } @@ -557,83 +529,35 @@ bool MemoryBase::Write128NN(u64 addr, const u128 data) u8 MemoryBase::Read8(u64 addr) { -#if DEBUG_RAWSPU_MEM - if(SpuRawMem.IsMyAddress(addr)) - { - ConLog.Warning("Read8(addr=0x%llx)", addr); - } -#endif - - MemoryBlock& mem = GetMemByAddr(addr); - if(mem.IsNULL()) - { - mem.Read8(addr, NULL); - return 0; - } - return mem.FastRead8(mem.FixAddr(addr)); + u8 res; + GetMemByAddr(addr).Read8(addr, &res); + return res; } u16 MemoryBase::Read16(u64 addr) { -#if DEBUG_RAWSPU_MEM - if(SpuRawMem.IsMyAddress(addr)) - { - ConLog.Warning("Read16(addr=0x%llx)", addr); - } -#endif - - MemoryBlock& mem = GetMemByAddr(addr); - if(mem.IsNULL()) - { - mem.Read16(addr, NULL); - return 0; - } - return mem.FastRead16(mem.FixAddr(addr)); + u16 res; + GetMemByAddr(addr).Read16(addr, &res); + return res; } u32 MemoryBase::Read32(u64 addr) { -#if DEBUG_RAWSPU_MEM - if(SpuRawMem.IsMyAddress(addr) && !(GetCurrentPPCThread() && GetCurrentPPCThread()->GetType() == PPC_THREAD_RAW_SPU)) - { - ConLog.Warning("Read32(addr=0x%llx)", addr); - } -#endif - - MemoryBlock& mem = GetMemByAddr(addr); - if(mem.IsNULL()) - { - mem.Read32(addr, NULL); - return 0; - } - return mem.FastRead32(mem.FixAddr(addr)); + u32 res; + GetMemByAddr(addr).Read32(addr, &res); + return res; } u64 MemoryBase::Read64(u64 addr) { -#if DEBUG_RAWSPU_MEM - if(SpuRawMem.IsMyAddress(addr)) - { - ConLog.Warning("Read64(addr=0x%llx)", addr); - } -#endif - - MemoryBlock& mem = GetMemByAddr(addr); - if(mem.IsNULL()) - { - mem.Read64(addr, NULL); - return 0; - } - return mem.FastRead64(mem.FixAddr(addr)); + u64 res; + GetMemByAddr(addr).Read64(addr, &res); + return res; } u128 MemoryBase::Read128(u64 addr) { - MemoryBlock& mem = GetMemByAddr(addr); - if(mem.IsNULL()) - { - mem.Read128(addr, NULL); - return u128::From32(0); - } - return mem.FastRead128(mem.FixAddr(addr)); + u128 res; + GetMemByAddr(addr).Read128(addr, &res); + return res; } diff --git a/rpcs3/Emu/Memory/Memory.h b/rpcs3/Emu/Memory/Memory.h index 37576f9982..fafb463102 100644 --- a/rpcs3/Emu/Memory/Memory.h +++ b/rpcs3/Emu/Memory/Memory.h @@ -1,6 +1,12 @@ #pragma once #include "MemoryBlock.h" +enum MemoryType +{ + Memory_PS3, + Memory_Vita, +}; + class MemoryBase { NullMemoryBlock NullMem; @@ -126,21 +132,29 @@ public: return true; } - void Init() + void Init(MemoryType type) { if(m_inited) return; m_inited = true; ConLog.Write("Initing memory..."); - MemoryBlocks.Add(MainMem.SetRange(0x00010000, 0x2FFF0000)); - MemoryBlocks.Add(PRXMem.SetRange(0x30000000, 0x10000000)); - MemoryBlocks.Add(RSXCMDMem.SetRange(0x40000000, 0x10000000)); - MemoryBlocks.Add(MmaperMem.SetRange(0xB0000000, 0x10000000)); - MemoryBlocks.Add(RSXFBMem.SetRange(0xC0000000, 0x10000000)); - MemoryBlocks.Add(StackMem.SetRange(0xD0000000, 0x10000000)); - //MemoryBlocks.Add(SpuRawMem.SetRange(0xE0000000, 0x10000000)); - //MemoryBlocks.Add(SpuThrMem.SetRange(0xF0000000, 0x10000000)); + switch(type) + { + case Memory_PS3: + MemoryBlocks.Add(MainMem.SetRange(0x00010000, 0x2FFF0000)); + MemoryBlocks.Add(PRXMem.SetRange(0x30000000, 0x10000000)); + MemoryBlocks.Add(RSXCMDMem.SetRange(0x40000000, 0x10000000)); + MemoryBlocks.Add(MmaperMem.SetRange(0xB0000000, 0x10000000)); + MemoryBlocks.Add(RSXFBMem.SetRange(0xC0000000, 0x10000000)); + MemoryBlocks.Add(StackMem.SetRange(0xD0000000, 0x10000000)); + //MemoryBlocks.Add(SpuRawMem.SetRange(0xE0000000, 0x10000000)); + //MemoryBlocks.Add(SpuThrMem.SetRange(0xF0000000, 0x10000000)); + break; + + case Memory_Vita: + break; + } ConLog.Write("Memory initialized."); } @@ -181,15 +195,6 @@ public: MemoryBlocks.Clear(); } - void Reset() - { - if(!m_inited) return; - - ConLog.Write("Resetting memory..."); - Close(); - Init(); - } - void Write8(const u64 addr, const u8 data); void Write16(const u64 addr, const u16 data); void Write32(const u64 addr, const u32 data); diff --git a/rpcs3/Emu/SysCalls/Callback.cpp b/rpcs3/Emu/SysCalls/Callback.cpp index def71a0e83..c062292092 100644 --- a/rpcs3/Emu/SysCalls/Callback.cpp +++ b/rpcs3/Emu/SysCalls/Callback.cpp @@ -50,11 +50,11 @@ void Callback::Branch(bool wait) { m_has_data = false; - PPCThread& new_thread = Emu.GetCPU().AddThread(PPC_THREAD_PPU); + CPUThread& new_thread = Emu.GetCPU().AddThread(CPU_THREAD_PPU); new_thread.SetEntry(m_addr); new_thread.SetPrio(1001); - new_thread.stack_size = 0x10000; + new_thread.SetStackSize(0x10000); new_thread.SetName("Callback"); new_thread.SetArg(0, a1); diff --git a/rpcs3/Emu/SysCalls/FuncList.cpp b/rpcs3/Emu/SysCalls/FuncList.cpp index 5c5d90e433..0bd28091c4 100644 --- a/rpcs3/Emu/SysCalls/FuncList.cpp +++ b/rpcs3/Emu/SysCalls/FuncList.cpp @@ -356,8 +356,8 @@ s64 SysCalls::DoFunc(const u32 id) case 0xc8f3bd09: FUNC_LOG_ERROR("TODO: cellGcmGetCurrentField"); case 0xcaabd992: FUNC_LOG_ERROR("TODO: cellGcmInitDefaultFifoMode"); case 0xd01b570d: FUNC_LOG_ERROR("TODO: cellGcmSetGraphicsHandler"); - case 0xd0b1d189: ConLog.Error("TODO: cellGcmSetTile"); return SC_ARGS_1; - case 0xd34a420d: ConLog.Error("TODO: cellGcmSetZcull"); return SC_ARGS_1; + case 0xd0b1d189: FUNC_LOG_ERROR("TODO: cellGcmSetTile"); + case 0xd34a420d: FUNC_LOG_ERROR("TODO: cellGcmSetZcull"); case 0xd8f88e1a: FUNC_LOG_ERROR("TODO: _cellGcmSetFlipCommandWithWaitLabel"); case 0xd9a0a879: FUNC_LOG_ERROR("TODO: cellGcmGetZcullInfo"); case 0xd9b7653e: FUNC_LOG_ERROR("TODO: cellGcmUnbindTile"); @@ -817,9 +817,9 @@ s64 SysCalls::DoFunc(const u32 id) case 0x516ee89e: FUNC_LOG_ERROR("TODO: cellRescInit"); case 0x5a338cdb: FUNC_LOG_ERROR("TODO: cellRescGetBufferSize"); case 0x66f5e388: FUNC_LOG_ERROR("TODO: cellRescGetLastFlipTime"); - case 0x6cd0f95f: return cellRescSetSrc(SC_ARGS_2);//FUNC_LOG_ERROR("TODO: cellRescSetSrc"); + case 0x6cd0f95f: FUNC_LOG_ERROR("TODO: cellRescSetSrc"); case 0x7af8a37f: FUNC_LOG_ERROR("TODO: cellRescSetRegisterCount"); - case 0x8107277c: return cellRescSetBufferAddress(SC_ARGS_3); //FUNC_LOG_ERROR("TODO: cellRescSetBufferAddress"); + case 0x8107277c: FUNC_LOG_ERROR("TODO: cellRescSetBufferAddress"); case 0xc47c5c22: FUNC_LOG_ERROR("TODO: cellRescGetFlipStatus"); case 0xd1ca0503: FUNC_LOG_ERROR("TODO: cellRescVideoOutResolutionId2RescBufferMode"); case 0xd3758645: FUNC_LOG_ERROR("TODO: cellRescSetVBlankHandler"); @@ -1410,19 +1410,19 @@ s64 SysCalls::DoFunc(const u32 id) case 0xa193143c: FUNC_LOG_ERROR("TODO: cellSysmoduleSetMemcontainer"); case 0x018a1381: FUNC_LOG_ERROR("TODO: cellSysutilAvcSetLayoutMode"); case 0x01f04d94: FUNC_LOG_ERROR("TODO: cellSysutilGamePowerOff_I"); - case 0x02ff3c1b: return cellSysutilUnregisterCallback(SC_ARGS_1); //FUNC_LOG_ERROR("TODO: cellSysutilUnregisterCallback"); + case 0x02ff3c1b: FUNC_LOG_ERROR("TODO: cellSysutilUnregisterCallback"); case 0x073b89d5: FUNC_LOG_ERROR("TODO: cellSysutilAvcGetSpeakerVolumeLevel"); case 0x08269f37: FUNC_LOG_ERROR("TODO: cellSysutilAvcGetShowStatus"); - case 0x0bae8772: return cellVideoOutConfigure(SC_ARGS_4); //FUNC_LOG_ERROR("TODO: cellVideoOutConfigure"); + case 0x0bae8772: FUNC_LOG_ERROR("TODO: cellVideoOutConfigure"); case 0x0c316b87: FUNC_LOG_ERROR("TODO: cellWebBrowserConfigGetHeapSize2"); case 0x0e091c36: FUNC_LOG_ERROR("TODO: cellSaveDataUserListAutoSave"); case 0x0f03cfb0: FUNC_LOG_ERROR("TODO: cellSaveDataUserListSave"); case 0x0f8a3b6b: FUNC_LOG_ERROR("TODO: cellWebBrowserConfigSetMimeSet"); case 0x10cabeff: FUNC_LOG_ERROR("TODO: cellWebBrowserGetUsrdataOnGameExit"); - case 0x15b0b0cd: return cellVideoOutGetConfiguration(SC_ARGS_3); //FUNC_LOG_ERROR("TODO: cellVideoOutGetConfiguration"); + case 0x15b0b0cd: FUNC_LOG_ERROR("TODO: cellVideoOutGetConfiguration"); case 0x15df71ed: FUNC_LOG_ERROR("TODO: cellSysutilAvcLoadAsync"); case 0x17dbe8b3: FUNC_LOG_ERROR("TODO: cellSysutilAvcJoinRequest"); - case 0x189a74da: return cellSysutilCheckCallback(); //FUNC_LOG_ERROR("TODO: cellSysutilCheckCallback"); + case 0x189a74da: FUNC_LOG_ERROR("TODO: cellSysutilCheckCallback"); case 0x1a91874b: FUNC_LOG_ERROR("TODO: cellWebBrowserConfigSetFullScreen2"); case 0x1d99c3ee: FUNC_LOG_ERROR("TODO: cellOskDialogGetInputText"); case 0x1dfbfdd6: FUNC_LOG_ERROR("TODO: cellSaveDataListLoad2"); @@ -1484,8 +1484,8 @@ s64 SysCalls::DoFunc(const u32 id) case 0x71acb8d3: FUNC_LOG_ERROR("TODO: cellSysutilAvcSetVideoMuting"); case 0x744c1544: FUNC_LOG_ERROR("TODO: cellSysCacheClear"); case 0x749c9b5f: FUNC_LOG_ERROR("TODO: cellWebBrowserInitialize"); - case 0x75bbb672: return cellVideoOutGetNumberOfDevice(SC_ARGS_1); //FUNC_LOG_ERROR("TODO: cellVideoOutGetNumberOfDevice"); - case 0x7603d3db: return cellMsgDialogOpen2(SC_ARGS_5); //FUNC_LOG_ERROR("TODO: cellMsgDialogOpen2"); + case 0x75bbb672: FUNC_LOG_ERROR("TODO: cellVideoOutGetNumberOfDevice"); + case 0x7603d3db: FUNC_LOG_ERROR("TODO: cellMsgDialogOpen2"); case 0x7663e368: FUNC_LOG_ERROR("TODO: cellAudioOutGetDeviceInfo"); case 0x76948bfc: FUNC_LOG_ERROR("TODO: cellSysconfAbort"); case 0x76fc8fb1: FUNC_LOG_ERROR("TODO: cellWebBrowserConfigSetHeapSize"); @@ -1498,7 +1498,7 @@ s64 SysCalls::DoFunc(const u32 id) case 0x7fb3c6a5: FUNC_LOG_ERROR("TODO: cellWebBrowserConfig2"); case 0x7fcfc915: FUNC_LOG_ERROR("TODO: cellOskDialogLoadAsync"); case 0x83668b8e: FUNC_LOG_ERROR("TODO: cellWebBrowserConfig"); - case 0x887572d5: return cellVideoOutGetState(SC_ARGS_3);//FUNC_LOG_ERROR("TODO: cellVideoOutGetState"); + case 0x887572d5: FUNC_LOG_ERROR("TODO: cellVideoOutGetState"); case 0x8a4cb646: FUNC_LOG_ERROR("TODO: cellWebBrowserCreateWithConfig"); case 0x8a5dbb58: FUNC_LOG_ERROR("TODO: cellWebComponentCreate"); case 0x8b7ed64b: FUNC_LOG_ERROR("TODO: cellSaveDataAutoSave2"); @@ -1515,11 +1515,11 @@ s64 SysCalls::DoFunc(const u32 id) case 0x9c9fe6a4: FUNC_LOG_ERROR("TODO: cellWebBrowserConfigSetFunction"); case 0x9ca9ffa7: FUNC_LOG_ERROR("TODO: cellHddGameSetSystemVer"); case 0x9d6af72a: FUNC_LOG_ERROR("TODO: cellMsgDialogProgressBarSetMsg"); - case 0x9d98afa0: return cellSysutilRegisterCallback(SC_ARGS_3); //FUNC_LOG_ERROR("TODO: cellSysutilRegisterCallback"); + case 0x9d98afa0: FUNC_LOG_ERROR("TODO: cellSysutilRegisterCallback"); case 0x9dfdad46: FUNC_LOG_ERROR("TODO: cellAudioOutUnregisterCallback"); case 0x9fb97b10: FUNC_LOG_ERROR("TODO: cellWebBrowserNavigate2"); case 0xa11552f6: FUNC_LOG_ERROR("TODO: cellSysutilGetBgmPlaybackStatus"); - case 0xa322db75: return cellVideoOutGetResolutionAvailability(SC_ARGS_4); //FUNC_LOG_ERROR("TODO: cellVideoOutGetResolutionAvailability"); + case 0xa322db75: FUNC_LOG_ERROR("TODO: cellVideoOutGetResolutionAvailability"); case 0xa36335a5: FUNC_LOG_ERROR("TODO: cellSysutilDisableBgmPlaybackEx"); case 0xa4dd11cc: FUNC_LOG_ERROR("TODO: cellWebBrowserConfigGetHeapSize"); case 0xa4ed7dfe: FUNC_LOG_ERROR("TODO: cellSaveDataDelete"); @@ -1556,7 +1556,7 @@ s64 SysCalls::DoFunc(const u32 id) case 0xdce51399: FUNC_LOG_ERROR("TODO: cellWebComponentDestroy"); case 0xdfdd302e: FUNC_LOG_ERROR("TODO: cellDiscGameRegisterDiscChangeCallback"); case 0xe22ed55d: FUNC_LOG_ERROR("TODO: cellWebBrowserConfigSetFunction2"); - case 0xe558748d: return cellVideoOutGetResolution(SC_ARGS_2); //FUNC_LOG_ERROR("TODO: cellVideoOutGetResolution"); + case 0xe558748d: FUNC_LOG_ERROR("TODO: cellVideoOutGetResolution"); case 0xe5e2b09d: FUNC_LOG_ERROR("TODO: cellAudioOutGetNumberOfDevice"); case 0xe7951dee: FUNC_LOG_ERROR("TODO: cellGameDataCheckCreate"); case 0xe7fa820b: FUNC_LOG_ERROR("TODO: cellSaveDataEnableOverlay"); @@ -3563,28 +3563,25 @@ s64 SysCalls::DoFunc(const u32 id) case 0x05c65656: FUNC_LOG_ERROR("TODO: sys_mempool_try_allocate_block"); case 0x0618936b: FUNC_LOG_ERROR("TODO: _sys_vsnprintf"); case 0x06574237: FUNC_LOG_ERROR("TODO: _sys_snprintf"); - case 0x1573dc3f: return sys_lwmutex_lock(SC_ARGS_2);//FUNC_LOG_ERROR("TODO: sys_lwmutex_lock"); + case 0x1573dc3f: FUNC_LOG_ERROR("TODO: sys_lwmutex_lock"); case 0x191f0c4a: FUNC_LOG_ERROR("TODO: _sys_strrchr"); case 0x1ae10b92: FUNC_LOG_ERROR("TODO: _sys_spu_printf_attach_thread"); - case 0x1bc200f4: return sys_lwmutex_unlock(SC_ARGS_1);//FUNC_LOG_ERROR("TODO: sys_lwmutex_unlock"); + case 0x1bc200f4: FUNC_LOG_ERROR("TODO: sys_lwmutex_unlock"); case 0x1c9a942c: FUNC_LOG_ERROR("TODO: sys_lwcond_destroy"); case 0x1ca525a2: FUNC_LOG_ERROR("TODO: _sys_strncasecmp"); case 0x1ed454ce: FUNC_LOG_ERROR("TODO: sys_spu_elf_get_information"); - case 0x24a1ea07: return sys_ppu_thread_create(SC_ARGS_7);//FUNC_LOG_ERROR("TODO: sys_ppu_thread_create"); + case 0x24a1ea07: FUNC_LOG_ERROR("TODO: sys_ppu_thread_create"); case 0x25596f51: FUNC_LOG_ERROR("TODO: sys_mempool_get_count"); case 0x26090058: FUNC_LOG_ERROR("TODO: sys_prx_load_module"); case 0x27427742: FUNC_LOG_ERROR("TODO: _sys_memmove"); case 0x2a6d9d51: FUNC_LOG_ERROR("TODO: sys_lwcond_wait"); case 0x2c847572: FUNC_LOG_ERROR("TODO: _sys_process_atexitspawn"); - case 0x2d36462b: - //FUNC_LOG_ERROR("TODO: _sys_strlen"); - ConLog.Write("sys_strlen(addr=0x%x(%s))", SC_ARGS_1, Memory.ReadString(SC_ARGS_1)); - return strlen((const char*)&Memory[SC_ARGS_1]); - case 0x2f85c0ef: return sys_lwmutex_create(SC_ARGS_2);//FUNC_LOG_ERROR("TODO: sys_lwmutex_create"); + case 0x2d36462b: FUNC_LOG_ERROR("TODO: _sys_strlen"); + case 0x2f85c0ef: FUNC_LOG_ERROR("TODO: sys_lwmutex_create"); case 0x3172759d: FUNC_LOG_ERROR("TODO: sys_game_get_temperature"); case 0x318f17e1: FUNC_LOG_ERROR("TODO: _sys_memalign"); - case 0x350d454e: return sys_ppu_thread_get_id(SC_ARGS_1);//FUNC_LOG_ERROR("TODO: sys_ppu_thread_get_id"); - case 0x35168520: return sys_heap_malloc(SC_ARGS_2); //FUNC_LOG_ERROR("TODO: _sys_heap_malloc"); + case 0x350d454e: FUNC_LOG_ERROR("TODO: sys_ppu_thread_get_id"); + case 0x35168520: FUNC_LOG_ERROR("TODO: _sys_heap_malloc"); case 0x3bd53c7b: FUNC_LOG_ERROR("TODO: _sys_memchr"); case 0x3dd4a957: FUNC_LOG_ERROR("TODO: sys_ppu_thread_register_atexit"); case 0x409ad939: FUNC_LOG_ERROR("TODO: sys_mmapper_free_memory"); @@ -3602,28 +3599,18 @@ s64 SysCalls::DoFunc(const u32 id) case 0x608212fc: FUNC_LOG_ERROR("TODO: sys_mempool_free_block"); case 0x620e35a7: FUNC_LOG_ERROR("TODO: sys_game_get_system_sw_version"); case 0x67f9fedb: FUNC_LOG_ERROR("TODO: sys_game_process_exitspawn2"); - case 0x68b9b011: - ConLog.Warning("_sys_memset(0x%llx, 0x%lld, 0x%lld)", SC_ARGS_3); - return - (u32)memset(Memory.GetMemFromAddr(CPU.GPR[3]), CPU.GPR[4], CPU.GPR[5]) - - Memory.GetMemByAddr(CPU.GPR[3]).GetStartAddr(); - FUNC_LOG_ERROR("TODO: _sys_memset"); + case 0x68b9b011: FUNC_LOG_ERROR("TODO: _sys_memset"); case 0x6bf66ea7: FUNC_LOG_ERROR("TODO: _sys_memcpy"); case 0x6e05231d: FUNC_LOG_ERROR("TODO: sys_game_watchdog_stop"); case 0x70258515: FUNC_LOG_ERROR("TODO: sys_mmapper_allocate_memory_from_container"); case 0x71a8472a: FUNC_LOG_ERROR("TODO: sys_get_random_number"); case 0x722a0254: FUNC_LOG_ERROR("TODO: sys_spinlock_trylock"); case 0x74311398: FUNC_LOG_ERROR("TODO: sys_prx_get_my_module_id"); - case 0x744680a2: - // FUNC_LOG_ERROR("TODO: sys_initialize_tls"); - ConLog.Warning("sys_initialize_tls()"); - //CPU.GPR[4] = Emu.GetTLSFilesz(); - //CPU.GPR[5] = Emu.GetTLSMemsz(); - return 0;//Memory.MainMem.Alloc(Emu.GetTLSMemsz());//Emu.GetTLSAddr(); + case 0x744680a2: FUNC_LOG_ERROR("TODO: sys_initialize_tls"); case 0x7498887b: FUNC_LOG_ERROR("TODO: _sys_strchr"); case 0x791b9219: FUNC_LOG_ERROR("TODO: _sys_vsprintf"); case 0x80fb0c19: FUNC_LOG_ERROR("TODO: sys_prx_stop_module"); - case 0x8461e528: return sys_time_get_system_time();//FUNC_LOG_ERROR("TODO: sys_time_get_system_time"); + case 0x8461e528: FUNC_LOG_ERROR("TODO: sys_time_get_system_time"); case 0x84bb6774: FUNC_LOG_ERROR("TODO: sys_prx_get_module_info"); case 0x893305fa: FUNC_LOG_ERROR("TODO: sys_raw_spu_load"); case 0x8985b5b6: FUNC_LOG_ERROR("TODO: _sys_heap_stats"); @@ -3640,33 +3627,27 @@ s64 SysCalls::DoFunc(const u32 id) case 0x9f18429d: FUNC_LOG_ERROR("TODO: sys_prx_start_module"); case 0x9f950780: FUNC_LOG_ERROR("TODO: sys_game_get_rtc_status"); case 0xa146a143: FUNC_LOG_ERROR("TODO: sys_mempool_allocate_block"); - case 0xa1f9eafe: - ConLog.Warning("_sys_sprintf(0x%llx, 0x%llx(%s), 0x%llx)", CPU.GPR[3], CPU.GPR[4], Memory.ReadString(CPU.GPR[4]), CPU.GPR[5]); - return vsprintf((char*)Memory.GetMemFromAddr(CPU.GPR[3]), Memory.ReadString(CPU.GPR[4]), (char*)Memory.GetMemFromAddr(CPU.GPR[5])); - FUNC_LOG_ERROR("TODO: _sys_sprintf"); + case 0xa1f9eafe: FUNC_LOG_ERROR("TODO: _sys_sprintf"); case 0xa285139d: FUNC_LOG_ERROR("TODO: sys_spinlock_lock"); case 0xa2c7ba64: FUNC_LOG_ERROR("TODO: sys_prx_exitspawn_with_level"); case 0xa330ad84: FUNC_LOG_ERROR("TODO: sys_prx_load_module_on_memcontainer_by_fd"); - case 0xa3e3be68: sys_ppu_thread_once(SC_ARGS_2); return SC_ARGS_1;//FUNC_LOG_ERROR("TODO: sys_ppu_thread_once"); + case 0xa3e3be68: FUNC_LOG_ERROR("TODO: sys_ppu_thread_once"); case 0xa5d06bf0: FUNC_LOG_ERROR("TODO: sys_prx_get_module_list"); case 0xaa6d9bff: FUNC_LOG_ERROR("TODO: sys_prx_load_module_on_memcontainer"); case 0xac6fc404: FUNC_LOG_ERROR("TODO: sys_ppu_thread_unregister_atexit"); case 0xacad8fb6: FUNC_LOG_ERROR("TODO: sys_game_watchdog_clear"); - case 0xaeb78725: return sys_lwmutex_trylock(SC_ARGS_1);//FUNC_LOG_ERROR("TODO: sys_lwmutex_trylock"); + case 0xaeb78725: FUNC_LOG_ERROR("TODO: sys_lwmutex_trylock"); case 0xaede4b03: FUNC_LOG_ERROR("TODO: _sys_heap_delete_heap"); - case 0xaff080a4: return sys_ppu_thread_exit(SC_ARGS_1);//FUNC_LOG_ERROR("TODO: sys_ppu_thread_exit"); - case 0xb257540b: return sys_mmapper_allocate_memory(SC_ARGS_3); //FUNC_LOG_ERROR("TODO: sys_mmapper_allocate_memory"); + case 0xaff080a4: FUNC_LOG_ERROR("TODO: sys_ppu_thread_exit"); + case 0xb257540b: FUNC_LOG_ERROR("TODO: sys_mmapper_allocate_memory"); case 0xb27c8ae7: FUNC_LOG_ERROR("TODO: sys_prx_load_module_list"); - case 0xb2fcf2c8: return sys_heap_create_heap(SC_ARGS_3);//FUNC_LOG_ERROR("TODO: _sys_heap_create_heap"); + case 0xb2fcf2c8: FUNC_LOG_ERROR("TODO: _sys_heap_create_heap"); case 0xb3bbcf2a: FUNC_LOG_ERROR("TODO: _sys_spu_printf_detach_thread"); case 0xb6369393: FUNC_LOG_ERROR("TODO: _sys_heap_get_total_free_size"); case 0xb995662e: FUNC_LOG_ERROR("TODO: sys_raw_spu_image_load"); case 0xb9bf1078: FUNC_LOG_ERROR("TODO: _sys_heap_alloc_heap_memory"); - case 0xbdb18f83: - ConLog.Warning("_sys_malloc(0x%llx)", SC_ARGS_1); - return Memory.Alloc(CPU.GPR[3], Emu.GetMallocPageSize()); - FUNC_LOG_ERROR("TODO: _sys_malloc"); - case 0xc3476d0c: return sys_lwmutex_destroy(SC_ARGS_1);////FUNC_LOG_ERROR("TODO: sys_lwmutex_destroy"); + case 0xbdb18f83: FUNC_LOG_ERROR("TODO: _sys_malloc"); + case 0xc3476d0c: FUNC_LOG_ERROR("TODO: sys_lwmutex_destroy"); case 0xc4fd6121: FUNC_LOG_ERROR("TODO: _sys_qsort"); case 0xca9a60bf: FUNC_LOG_ERROR("TODO: sys_mempool_create"); case 0xd0ea47a7: FUNC_LOG_ERROR("TODO: sys_prx_unregister_library"); @@ -3674,13 +3655,13 @@ s64 SysCalls::DoFunc(const u32 id) case 0xd3039d4d: FUNC_LOG_ERROR("TODO: _sys_strncpy"); case 0xda0eb71a: FUNC_LOG_ERROR("TODO: sys_lwcond_create"); case 0xdb6b3250: FUNC_LOG_ERROR("TODO: sys_spu_elf_get_segments"); - case 0xdc578057: return sys_mmapper_map_memory(SC_ARGS_3); //FUNC_LOG_ERROR("TODO: sys_mmapper_map_memory"); + case 0xdc578057: FUNC_LOG_ERROR("TODO: sys_mmapper_map_memory"); case 0xdd0c1e09: FUNC_LOG_ERROR("TODO: _sys_spu_printf_attach_group"); case 0xdd3b27ac: FUNC_LOG_ERROR("TODO: _sys_spu_printf_finalize"); case 0xe0998dbf: FUNC_LOG_ERROR("TODO: sys_prx_get_module_id_by_name"); case 0xe0da8efd: FUNC_LOG_ERROR("TODO: sys_spu_image_close"); case 0xe66bac36: FUNC_LOG_ERROR("TODO: console_putc"); - case 0xe6f2c1e7: return sys_process_exit(SC_ARGS_1);///FUNC_LOG_ERROR("TODO: sys_process_exit"); + case 0xe6f2c1e7: FUNC_LOG_ERROR("TODO: sys_process_exit"); case 0xe76964f5: FUNC_LOG_ERROR("TODO: sys_game_board_storage_read"); case 0xe7ef3a80: FUNC_LOG_ERROR("TODO: sys_prx_load_module_list_on_memcontainer"); case 0xe9a1bd84: FUNC_LOG_ERROR("TODO: sys_lwcond_signal_all"); @@ -3693,7 +3674,7 @@ s64 SysCalls::DoFunc(const u32 id) case 0xf7f7fb20: FUNC_LOG_ERROR("TODO: _sys_free"); case 0xfa7f693d: FUNC_LOG_ERROR("TODO: _sys_vprintf"); case 0xfb5db080: FUNC_LOG_ERROR("TODO: _sys_memcmp"); - case 0xfc52a7a9: return sys_game_process_exitspawn(SC_ARGS_7); FUNC_LOG_ERROR("TODO: sys_game_process_exitspawn"); + case 0xfc52a7a9: FUNC_LOG_ERROR("TODO: sys_game_process_exitspawn"); } ConLog.Error("Unknown func id: 0x%08x", id); diff --git a/rpcs3/Emu/SysCalls/SysCalls.cpp b/rpcs3/Emu/SysCalls/SysCalls.cpp index e76bf979e3..497368a740 100644 --- a/rpcs3/Emu/SysCalls/SysCalls.cpp +++ b/rpcs3/Emu/SysCalls/SysCalls.cpp @@ -267,14 +267,6 @@ void default_syscall() return; } -SysCalls::SysCalls(PPUThread& cpu) : CPU(cpu) -{ -} - -SysCalls::~SysCalls() -{ -} - void SysCalls::DoSyscall(u32 code) { if(code < 1024) @@ -291,5 +283,6 @@ void SysCalls::DoSyscall(u32 code) //return 0; //TODO: remove this + declCPU(); RESULT(DoFunc(code)); } \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/SysCalls.h b/rpcs3/Emu/SysCalls/SysCalls.h index bb03c128e7..eb8efcf4bb 100644 --- a/rpcs3/Emu/SysCalls/SysCalls.h +++ b/rpcs3/Emu/SysCalls/SysCalls.h @@ -305,32 +305,12 @@ extern u64 sys_time_get_timebase_frequency(); #define SC_ARGS_12 SC_ARGS_11,SC_ARG_11 extern bool dump_enable; -class PPUThread; class SysCalls { - PPUThread& CPU; - public: - //process - int lv2ProcessGetPid(PPUThread& CPU); - int lv2ProcessWaitForChild(PPUThread& CPU); - int lv2ProcessGetStatus(PPUThread& CPU); - int lv2ProcessDetachChild(PPUThread& CPU); - int lv2ProcessGetNumberOfObject(PPUThread& CPU); - int lv2ProcessGetId(PPUThread& CPU); - int lv2ProcessGetPpid(PPUThread& CPU); - int lv2ProcessKill(PPUThread& CPU); - int lv2ProcessWaitForChild2(PPUThread& CPU); - int lv2ProcessGetSdkVersion(PPUThread& CPU); - -protected: - SysCalls(PPUThread& cpu); - ~SysCalls(); - -public: - void DoSyscall(u32 code); - s64 DoFunc(const u32 id); + static void DoSyscall(u32 code); + static s64 DoFunc(const u32 id); }; //extern SysCalls SysCallsManager; \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Event.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Event.cpp index 8aa6f3fa00..28044cdc06 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Event.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Event.cpp @@ -47,7 +47,7 @@ int sys_event_queue_receive(u32 equeue_id, u32 event_addr, u32 timeout) int result; auto queue_receive = [&](int status) -> bool { - if(status == PPCThread_Stopped) + if(status == CPUThread_Stopped) { result = CELL_ECANCELED; return false; @@ -59,11 +59,11 @@ int sys_event_queue_receive(u32 equeue_id, u32 event_addr, u32 timeout) if(!equeue->ports[i]->has_data && equeue->ports[i]->thread) { SPUThread* thr = (SPUThread*)equeue->ports[i]->thread; - if(thr->SPU_OutIntr_Mbox.GetCount()) + if(thr->SPU.OutIntr_Mbox.GetCount()) { u32 val; - thr->SPU_OutIntr_Mbox.Pop(val); - if(!thr->mfc.SPU_Out_MBox.Pop(val)) val = 0; + thr->SPU.OutIntr_Mbox.Pop(val); + if(!thr->SPU.Out_MBox.Pop(val)) val = 0; equeue->ports[i]->data1 = val; equeue->ports[i]->data2 = 0; equeue->ports[i]->data3 = 0; diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp index 8177530f34..f483e90e00 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp @@ -109,7 +109,7 @@ int sys_lwmutex_unlock(u64 lwmutex_addr) if(lmtx.lock_var.info.owner = lmtx.lock_var.info.waiter) { lmtx.lock_var.info.waiter = 0; - PPCThread* thr = Emu.GetCPU().GetThread(lmtx.lock_var.info.owner); + CPUThread* thr = Emu.GetCPU().GetThread(lmtx.lock_var.info.owner); if(thr) { thr->Wait(false); diff --git a/rpcs3/Emu/SysCalls/lv2/SC_PPU_Thread.cpp b/rpcs3/Emu/SysCalls/lv2/SC_PPU_Thread.cpp index fddb80a40e..66db9f3f4b 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_PPU_Thread.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_PPU_Thread.cpp @@ -38,7 +38,7 @@ int sys_ppu_thread_join(u32 thread_id, u32 vptr_addr) { sysPrxForUser.Warning("sys_ppu_thread_join(thread_id=%d, vptr_addr=0x%x)", thread_id, vptr_addr); - PPCThread* thr = Emu.GetCPU().GetThread(thread_id); + CPUThread* thr = Emu.GetCPU().GetThread(thread_id); if(!thr) return CELL_ESRCH; GetCurrentPPUThread().Wait(*thr); @@ -62,7 +62,7 @@ int sys_ppu_thread_set_priority(u32 thread_id, int prio) { sysPrxForUser.Warning("sys_ppu_thread_set_priority(thread_id=%d, prio=%d)", thread_id, prio); - PPCThread* thr = Emu.GetCPU().GetThread(thread_id); + CPUThread* thr = Emu.GetCPU().GetThread(thread_id); if(!thr) return CELL_ESRCH; thr->SetPrio(prio); @@ -74,7 +74,7 @@ int sys_ppu_thread_get_priority(u32 thread_id, u32 prio_addr) { sysPrxForUser.Log("sys_ppu_thread_get_priority(thread_id=%d, prio_addr=0x%x)", thread_id, prio_addr); - PPCThread* thr = Emu.GetCPU().GetThread(thread_id); + CPUThread* thr = Emu.GetCPU().GetThread(thread_id); if(!thr) return CELL_ESRCH; if(!Memory.IsGoodAddr(prio_addr)) return CELL_EFAULT; @@ -101,7 +101,7 @@ int sys_ppu_thread_stop(u32 thread_id) { sysPrxForUser.Warning("sys_ppu_thread_stop(thread_id=%d)", thread_id); - PPCThread* thr = Emu.GetCPU().GetThread(thread_id); + CPUThread* thr = Emu.GetCPU().GetThread(thread_id); if(!thr) return CELL_ESRCH; thr->Stop(); @@ -113,7 +113,7 @@ int sys_ppu_thread_restart(u32 thread_id) { sysPrxForUser.Warning("sys_ppu_thread_restart(thread_id=%d)", thread_id); - PPCThread* thr = Emu.GetCPU().GetThread(thread_id); + CPUThread* thr = Emu.GetCPU().GetThread(thread_id); if(!thr) return CELL_ESRCH; thr->Stop(); @@ -132,13 +132,13 @@ int sys_ppu_thread_create(u32 thread_id_addr, u32 entry, u32 arg, int prio, u32 return CELL_EFAULT; } - PPCThread& new_thread = Emu.GetCPU().AddThread(PPC_THREAD_PPU); + CPUThread& new_thread = Emu.GetCPU().AddThread(CPU_THREAD_PPU); Memory.Write32(thread_id_addr, new_thread.GetId()); new_thread.SetEntry(entry); new_thread.SetArg(0, arg); new_thread.SetPrio(prio); - new_thread.stack_size = stacksize; + new_thread.SetStackSize(stacksize); //new_thread.flags = flags; new_thread.SetName(Memory.ReadString(threadname_addr)); new_thread.Run(); @@ -155,7 +155,7 @@ void sys_ppu_thread_once(u32 once_ctrl_addr, u32 entry) { Memory.Write32(once_ctrl_addr, SYS_PPU_THREAD_DONE_INIT); - PPCThread& new_thread = Emu.GetCPU().AddThread(PPC_THREAD_PPU); + CPUThread& new_thread = Emu.GetCPU().AddThread(CPU_THREAD_PPU); new_thread.SetEntry(entry); new_thread.Run(); new_thread.Exec(); diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Process.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Process.cpp index 14a1b70868..ed6573fc3b 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Process.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Process.cpp @@ -32,7 +32,7 @@ int sys_game_process_exitspawn( u32 path_addr, u32 argv_addr, u32 envp_addr, sc_p.Log("flags: %d", flags); return CELL_OK; } - +/* int SysCalls::lv2ProcessWaitForChild(PPUThread& CPU) { ConLog.Warning("lv2ProcessWaitForChild"); @@ -73,14 +73,7 @@ int SysCalls::lv2ProcessKill(PPUThread& CPU) CPU.Close(); return CELL_OK; } -/* -int SysCalls::lv2ProcessExit(PPUThread& CPU) -{ - ConLog.Warning("lv2ProcessExit(%lld)", CPU.GPR[3]); - Emu.Pause(); - return CELL_OK; -} -*/ + int SysCalls::lv2ProcessWaitForChild2(PPUThread& CPU) { ConLog.Warning("lv2ProcessWaitForChild2[r3: 0x%llx, r4: 0x%llx, r5: 0x%llx, r6: 0x%llx, r7: 0x%llx, r8: 0x%llx]", @@ -92,4 +85,5 @@ int SysCalls::lv2ProcessGetSdkVersion(PPUThread& CPU) ConLog.Warning("lv2ProcessGetSdkVersion[r3: 0x%llx, r4: 0x%llx]", CPU.GPR[3], CPU.GPR[4]); CPU.GPR[4] = 0x360001; //TODO return CELL_OK; -} \ No newline at end of file +} +*/ \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp b/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp index 5ecad4f566..faebb1e416 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp @@ -1,7 +1,7 @@ #include "stdafx.h" #include "Emu/SysCalls/SysCalls.h" #include "Loader/ELF.h" -#include "Emu/Cell/SPUThread.h" +#include "Emu/Cell/RawSPUThread.h" SysCallBase sc_spu("sys_spu"); @@ -40,12 +40,12 @@ static const u32 g_spu_group_thr_count = 255; struct SpuGroupInfo { - PPCThread* threads[g_spu_group_thr_count]; + CPUThread* threads[g_spu_group_thr_count]; sys_spu_thread_group_attribute& attr; SpuGroupInfo(sys_spu_thread_group_attribute& attr) : attr(attr) { - memset(threads, 0, sizeof(PPCThread*) * g_spu_group_thr_count); + memset(threads, 0, sizeof(CPUThread*) * g_spu_group_thr_count); } }; @@ -150,7 +150,7 @@ int sys_spu_thread_initialize(u32 thread_addr, u32 group, u32 spu_num, u32 img_a ConLog.Write("a4 = 0x%x", a4); ConLog.SkipLn(); - PPCThread& new_thread = Emu.GetCPU().AddThread(PPC_THREAD_SPU); + CPUThread& new_thread = Emu.GetCPU().AddThread(CPU_THREAD_SPU); new_thread.SetOffset(g_spu_offset); new_thread.SetEntry(entry - g_spu_offset); new_thread.SetName(name); @@ -170,9 +170,9 @@ int sys_spu_thread_initialize(u32 thread_addr, u32 group, u32 spu_num, u32 img_a int sys_spu_thread_set_argument(u32 id, u32 arg_addr) { sc_spu.Warning("sys_spu_thread_set_argument(id=0x%x, arg_addr=0x%x)", id, arg_addr); - PPCThread* thr = Emu.GetCPU().GetThread(id); + CPUThread* thr = Emu.GetCPU().GetThread(id); - if(!thr || thr->GetType() == PPC_THREAD_PPU) + if(!thr || (thr->GetType() != CPU_THREAD_SPU && thr->GetType() != CPU_THREAD_RAW_SPU)) { return CELL_ESRCH; } @@ -268,8 +268,8 @@ int sys_raw_spu_create(u32 id_addr, u32 attr_addr) sc_spu.Warning("sys_raw_spu_create(id_addr=0x%x, attr_addr=0x%x)", id_addr, attr_addr); //Emu.GetIdManager().GetNewID("sys_raw_spu", new u32(attr_addr)); - PPCThread& new_thread = Emu.GetCPU().AddThread(PPC_THREAD_RAW_SPU); - Memory.Write32(id_addr, Emu.GetCPU().GetThreadNumById(PPC_THREAD_RAW_SPU, new_thread.GetId())); + CPUThread& new_thread = Emu.GetCPU().AddThread(CPU_THREAD_RAW_SPU); + Memory.Write32(id_addr, ((RawSPUThread&)new_thread).GetIndex()); new_thread.Run(); new_thread.Exec(); @@ -286,10 +286,10 @@ int sys_spu_initialize(u32 max_usable_spu, u32 max_raw_spu) return CELL_EINVAL; } - if(!Memory.InitSpuRawMem(max_raw_spu)) - { - return CELL_ENOMEM; - } + //if(!Memory.InitSpuRawMem(max_raw_spu)) + //{ + // return CELL_ENOMEM; + //} //enable_log = true; //dump_enable = true; @@ -303,9 +303,9 @@ int sys_spu_thread_write_ls(u32 id, u32 address, u64 value, u32 type) sc_spu.Warning("sys_spu_thread_write_ls(id=0x%x, address=0x%x, value=0x%llx, type=0x%x)", id, address, value, type); - PPCThread* thr = Emu.GetCPU().GetThread(id); + CPUThread* thr = Emu.GetCPU().GetThread(id); - if(!thr || thr->GetType() == PPC_THREAD_PPU) + if(!thr || (thr->GetType() != CPU_THREAD_SPU && thr->GetType() != CPU_THREAD_RAW_SPU)) { return CELL_ESRCH; } @@ -321,9 +321,9 @@ int sys_spu_thread_read_ls(u32 id, u32 address, u32 value_addr, u32 type) sc_spu.Warning("sys_spu_thread_read_ls(id=0x%x, address=0x%x, value_addr=0x%x, type=0x%x)", id, address, value_addr, type); - PPCThread* thr = Emu.GetCPU().GetThread(id); + CPUThread* thr = Emu.GetCPU().GetThread(id); - if(!thr || thr->GetType() == PPC_THREAD_PPU) + if(!thr || (thr->GetType() != CPU_THREAD_SPU && thr->GetType() != CPU_THREAD_RAW_SPU)) { return CELL_ESRCH; } @@ -343,14 +343,14 @@ int sys_spu_thread_write_spu_mb(u32 id, u32 value) { sc_spu.Warning("sys_spu_thread_write_spu_mb(id=0x%x, value=0x%x)", id, value); - PPCThread* thr = Emu.GetCPU().GetThread(id); + CPUThread* thr = Emu.GetCPU().GetThread(id); - if(!thr || !thr->GetType() == PPC_THREAD_PPU) + if(!thr || (thr->GetType() != CPU_THREAD_SPU && thr->GetType() != CPU_THREAD_RAW_SPU)) { return CELL_ESRCH; } - if(!(*(SPUThread*)thr).mfc.SPU_In_MBox.Push(value)) + if(!(*(SPUThread*)thr).SPU.In_MBox.Push(value)) { ConLog.Warning("sys_spu_thread_write_spu_mb(id=0x%x, value=0x%x): used all mbox items."); return CELL_EBUSY; //? diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index 6b3572d0e3..e90174a866 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -3,7 +3,6 @@ #include "Emu/Memory/Memory.h" #include "Ini.h" -#include "Emu/Cell/PPCThreadManager.h" #include "Emu/Cell/PPUThread.h" #include "Emu/Cell/SPUThread.h" #include "Emu/Cell/PPUInstrTable.h" @@ -44,7 +43,7 @@ void Emulator::SetPath(const wxString& path, const wxString& elf_path) void Emulator::CheckStatus() { - ArrayF& threads = GetCPU().GetThreads(); + ArrayF& threads = GetCPU().GetThreads(); if(!threads.GetCount()) { Stop(); @@ -83,7 +82,6 @@ void Emulator::Load() { if(!wxFileExists(m_path)) return; ConLog.Write("Loading '%s'...", m_path); - Memory.Init(); GetInfo().Reset(); m_vfs.Init(m_path); //m_vfs.Mount("/", vfsDevice::GetRoot(m_path), new vfsLocalFile()); @@ -117,7 +115,19 @@ void Emulator::Load() try { - is_error = !l.Load() || l.GetMachine() == MACHINE_Unknown; + if(!(is_error = !l.Analyze() || l.GetMachine() == MACHINE_Unknown)) + { + switch(l.GetMachine()) + { + case MACHINE_SPU: + case MACHINE_PPC64: + Memory.Init(Memory_PS3); + break; + } + + is_error = !l.Load(); + } + } catch(const wxString& e) { @@ -130,6 +140,21 @@ void Emulator::Load() is_error = true; } + CPUThreadType thread_type; + + if(!is_error) + { + switch(l.GetMachine()) + { + case MACHINE_PPC64: thread_type = CPU_THREAD_PPU; break; + case MACHINE_SPU: thread_type = CPU_THREAD_SPU; break; + + default: + is_error = true; + break; + } + } + if(is_error) { Memory.Close(); @@ -138,17 +163,20 @@ void Emulator::Load() } LoadPoints(BreakPointsDBName); - PPCThread& thread = GetCPU().AddThread(l.GetMachine() == MACHINE_PPC64 ? PPC_THREAD_PPU : PPC_THREAD_SPU); - if(l.GetMachine() == MACHINE_SPU) + CPUThread& thread = GetCPU().AddThread(thread_type); + + switch(l.GetMachine()) { + case MACHINE_SPU: ConLog.Write("offset = 0x%llx", Memory.MainMem.GetStartAddr()); ConLog.Write("max addr = 0x%x", l.GetMaxAddr()); thread.SetOffset(Memory.MainMem.GetStartAddr()); Memory.MainMem.Alloc(Memory.MainMem.GetStartAddr() + l.GetMaxAddr(), 0xFFFFED - l.GetMaxAddr()); thread.SetEntry(l.GetEntry() - Memory.MainMem.GetStartAddr()); - } - else + break; + + case MACHINE_PPC64: { thread.SetEntry(l.GetEntry()); Memory.StackMem.Alloc(0x1000); @@ -172,6 +200,12 @@ void Emulator::Load() ppu_thr_exit_data += SC(2); ppu_thr_exit_data += BCLR(0x10 | 0x04, 0, 0, 0); } + break; + + default: + thread.SetEntry(l.GetEntry()); + break; + } if(!m_dbg_console) { diff --git a/rpcs3/Emu/System.h b/rpcs3/Emu/System.h index 670e951788..bed7c5c332 100644 --- a/rpcs3/Emu/System.h +++ b/rpcs3/Emu/System.h @@ -1,7 +1,7 @@ #pragma once #include "Gui/MemoryViewer.h" -#include "Emu/Cell/PPCThreadManager.h" +#include "Emu/CPU/CPUThreadManager.h" #include "Emu/Io/Pad.h" #include "Emu/Io/Keyboard.h" #include "Emu/Io/Mouse.h" @@ -78,7 +78,7 @@ class Emulator Array m_break_points; Array m_marked_points; - PPCThreadManager m_thread_manager; + CPUThreadManager m_thread_manager; PadManager m_pad_manager; KeyboardManager m_keyboard_manager; MouseManager m_mouse_manager; @@ -109,7 +109,7 @@ public: return std::shared_ptr(m_vfs.Open(path, mode)); } - PPCThreadManager& GetCPU() { return m_thread_manager; } + CPUThreadManager& GetCPU() { return m_thread_manager; } PadManager& GetPadManager() { return m_pad_manager; } KeyboardManager& GetKeyboardManager() { return m_keyboard_manager; } MouseManager& GetMouseManager() { return m_mouse_manager; } diff --git a/rpcs3/Emu/event.h b/rpcs3/Emu/event.h index c3f72157d7..ed4084bc32 100644 --- a/rpcs3/Emu/event.h +++ b/rpcs3/Emu/event.h @@ -24,7 +24,7 @@ struct EventPort u64 data2; u64 data3; bool has_data; - PPCThread* thread; + CPUThread* thread; EventQueue* queue[127]; int pos; }; diff --git a/rpcs3/Gui/DisAsmFrame.cpp b/rpcs3/Gui/DisAsmFrame.cpp index ffc2266060..9932953eed 100644 --- a/rpcs3/Gui/DisAsmFrame.cpp +++ b/rpcs3/Gui/DisAsmFrame.cpp @@ -87,7 +87,7 @@ void DisAsmFrame::AddLine(const wxString line) { if(Emu.IsRunning()) Emu.Pause(); finished = true; - CPU.PrevPc(); + CPU.PC -= 4; return; } @@ -113,8 +113,8 @@ bool ElfType64 = false; class DumperThread : public ThreadBase { volatile uint id; - PPC_DisAsm* disasm; - PPC_Decoder* decoder; + PPCDisAsm* disasm; + PPCDecoder* decoder; volatile bool* done; volatile u8 cores; MTProgressDialog* prog_dial; @@ -135,16 +135,16 @@ public: *done = false; - if(Emu.GetCPU().GetThreads()[0].GetType() != PPC_THREAD_PPU) + if(Emu.GetCPU().GetThreads()[0].GetType() != CPU_THREAD_PPU) { - SPU_DisAsm& dis_asm = *new SPU_DisAsm(*(PPCThread*)NULL, DumpMode); - decoder = new SPU_Decoder(dis_asm); + SPUDisAsm& dis_asm = *new SPUDisAsm(CPUDisAsm_DumpMode); + decoder = new SPUDecoder(dis_asm); disasm = &dis_asm; } else { - PPU_DisAsm& dis_asm = *new PPU_DisAsm(*(PPCThread*)NULL, DumpMode); - decoder = new PPU_Decoder(dis_asm); + PPUDisAsm& dis_asm = *new PPUDisAsm(CPUDisAsm_DumpMode); + decoder = new PPUDecoder(dis_asm); disasm = &dis_asm; } } @@ -338,21 +338,28 @@ void DisAsmFrame::Dump(wxCommandEvent& WXUNUSED(event)) default: ConLog.Error("Corrupted ELF!"); return; } - PPC_DisAsm* disasm; - PPC_Decoder* decoder; + PPCDisAsm* disasm; + PPCDecoder* decoder; - if(Emu.GetCPU().GetThreads()[0].GetType() != PPC_THREAD_PPU) + switch(Emu.GetCPU().GetThreads()[0].GetType()) { - SPU_DisAsm& dis_asm = *new SPU_DisAsm(*(PPCThread*)NULL, DumpMode); - decoder = new SPU_Decoder(dis_asm); + case CPU_THREAD_PPU: + { + PPUDisAsm& dis_asm = *new PPUDisAsm(CPUDisAsm_DumpMode); + decoder = new PPUDecoder(dis_asm); disasm = &dis_asm; } - else + break; + + case CPU_THREAD_SPU: + case CPU_THREAD_RAW_SPU: { - PPU_DisAsm& dis_asm = *new PPU_DisAsm(*(PPCThread*)NULL, DumpMode); - decoder = new PPU_Decoder(dis_asm); + SPUDisAsm& dis_asm = *new SPUDisAsm(CPUDisAsm_DumpMode); + decoder = new SPUDecoder(dis_asm); disasm = &dis_asm; } + break; + } const u32 shdr_count = ElfType64 ? shdr_arr_64->GetCount() : shdr_arr_32->GetCount(); diff --git a/rpcs3/Gui/InstructionEditor.cpp b/rpcs3/Gui/InstructionEditor.cpp index 8344119a0e..a33cf8f915 100644 --- a/rpcs3/Gui/InstructionEditor.cpp +++ b/rpcs3/Gui/InstructionEditor.cpp @@ -2,8 +2,8 @@ class InstructionEditorDialog : public wxDialog { u64 pc; - PPC_DisAsm* disasm; - PPC_Decoder* decoder; + PPCDisAsm* disasm; + PPCDecoder* decoder; wxTextCtrl* t2_instr; wxStaticText* t3_preview; @@ -11,12 +11,12 @@ public: PPCThread* CPU; public: - InstructionEditorDialog(wxPanel *parent, u64 _pc, PPCThread* _CPU, PPC_Decoder* _decoder, PPC_DisAsm* _disasm); + InstructionEditorDialog(wxPanel *parent, u64 _pc, PPCThread* _CPU, PPCDecoder* _decoder, PPCDisAsm* _disasm); void updatePreview(wxCommandEvent& event); }; -InstructionEditorDialog::InstructionEditorDialog(wxPanel *parent, u64 _pc, PPCThread* _CPU, PPC_Decoder* _decoder, PPC_DisAsm* _disasm) +InstructionEditorDialog::InstructionEditorDialog(wxPanel *parent, u64 _pc, PPCThread* _CPU, PPCDecoder* _decoder, PPCDisAsm* _disasm) : wxDialog(parent, wxID_ANY, "Edit instruction", wxDefaultPosition) , pc(_pc) , CPU(_CPU) diff --git a/rpcs3/Gui/InterpreterDisAsm.cpp b/rpcs3/Gui/InterpreterDisAsm.cpp index ed139a17ee..a7dad86be3 100644 --- a/rpcs3/Gui/InterpreterDisAsm.cpp +++ b/rpcs3/Gui/InterpreterDisAsm.cpp @@ -110,18 +110,25 @@ void InterpreterDisAsmFrame::OnSelectUnit(wxCommandEvent& event) if(CPU) { - if(CPU->GetType() != PPC_THREAD_PPU) + switch(CPU->GetType()) { - SPU_DisAsm& dis_asm = *new SPU_DisAsm(*CPU, InterpreterMode); - decoder = new SPU_Decoder(dis_asm); + case CPU_THREAD_PPU: + { + PPUDisAsm& dis_asm = *new PPUDisAsm(CPUDisAsm_InterpreterMode); + decoder = new PPUDecoder(dis_asm); disasm = &dis_asm; } - else + break; + + case CPU_THREAD_SPU: + case CPU_THREAD_RAW_SPU: { - PPU_DisAsm& dis_asm = *new PPU_DisAsm(*CPU, InterpreterMode); - decoder = new PPU_Decoder(dis_asm); + SPUDisAsm& dis_asm = *new SPUDisAsm(CPUDisAsm_InterpreterMode); + decoder = new SPUDecoder(dis_asm); disasm = &dis_asm; } + break; + } } DoUpdate(); diff --git a/rpcs3/Gui/InterpreterDisAsm.h b/rpcs3/Gui/InterpreterDisAsm.h index 0ef18bcd83..22a8c423cd 100644 --- a/rpcs3/Gui/InterpreterDisAsm.h +++ b/rpcs3/Gui/InterpreterDisAsm.h @@ -8,8 +8,8 @@ class InterpreterDisAsmFrame : public wxPanel { wxListView* m_list; - PPC_DisAsm* disasm; - PPC_Decoder* decoder; + PPCDisAsm* disasm; + PPCDecoder* decoder; u64 PC; Array remove_markedPC; wxTextCtrl* m_regs; diff --git a/rpcs3/Gui/RegisterEditor.cpp b/rpcs3/Gui/RegisterEditor.cpp index da190f2e11..7069da3b4b 100644 --- a/rpcs3/Gui/RegisterEditor.cpp +++ b/rpcs3/Gui/RegisterEditor.cpp @@ -1,9 +1,8 @@ -class RegisterEditorDialog - : public wxDialog +class RegisterEditorDialog : public wxDialog { u64 pc; - PPC_DisAsm* disasm; - PPC_Decoder* decoder; + PPCDisAsm* disasm; + PPCDecoder* decoder; wxComboBox* t1_register; wxTextCtrl* t2_value; wxStaticText* t3_preview; @@ -12,13 +11,13 @@ public: PPCThread* CPU; public: - RegisterEditorDialog(wxPanel *parent, u64 _pc, PPCThread* _CPU, PPC_Decoder* _decoder, PPC_DisAsm* _disasm); + RegisterEditorDialog(wxPanel *parent, u64 _pc, PPCThread* _CPU, PPCDecoder* _decoder, PPCDisAsm* _disasm); void updateRegister(wxCommandEvent& event); void updatePreview(wxCommandEvent& event); }; -RegisterEditorDialog::RegisterEditorDialog(wxPanel *parent, u64 _pc, PPCThread* _CPU, PPC_Decoder* _decoder, PPC_DisAsm* _disasm) +RegisterEditorDialog::RegisterEditorDialog(wxPanel *parent, u64 _pc, PPCThread* _CPU, PPCDecoder* _decoder, PPCDisAsm* _disasm) : wxDialog(parent, wxID_ANY, "Edit registers", wxDefaultPosition) , pc(_pc) , CPU(_CPU) @@ -64,10 +63,11 @@ RegisterEditorDialog::RegisterEditorDialog(wxPanel *parent, u64 _pc, PPCThread* s_panel_margin_x->Add(s_panel_margin_y); s_panel_margin_x->AddSpacer(12); - this->Connect(wxEVT_COMMAND_COMBOBOX_SELECTED, wxCommandEventHandler(RegisterEditorDialog::updateRegister)); + Connect(wxEVT_COMMAND_COMBOBOX_SELECTED, wxCommandEventHandler(RegisterEditorDialog::updateRegister)); - if (CPU->GetType() == PPC_THREAD_PPU) + switch(CPU->GetType()) { + case CPU_THREAD_PPU: for (int i=0; i<32; i++) t1_register->Append(wxString::Format("GPR[%d]",i)); for (int i=0; i<32; i++) t1_register->Append(wxString::Format("FPR[%d]",i)); for (int i=0; i<32; i++) t1_register->Append(wxString::Format("VPR[%d]",i)); @@ -76,20 +76,17 @@ RegisterEditorDialog::RegisterEditorDialog(wxPanel *parent, u64 _pc, PPCThread* t1_register->Append("CTR"); t1_register->Append("XER"); t1_register->Append("FPSCR"); - } - if (CPU->GetType() == PPC_THREAD_SPU) - { + break; + + case CPU_THREAD_SPU: + case CPU_THREAD_RAW_SPU: for (int i=0; i<128; i++) t1_register->Append(wxString::Format("GPR[%d]",i)); - } - if (CPU->GetType() == PPC_THREAD_RAW_SPU) - { - wxMessageBox("RawSPU threads not yet supported.","Error"); - return; + break; } - this->SetSizerAndFit(s_panel_margin_x); + SetSizerAndFit(s_panel_margin_x); - if(this->ShowModal() == wxID_OK) + if(ShowModal() == wxID_OK) { wxString reg = t1_register->GetStringSelection(); wxString value = t2_value->GetValue(); diff --git a/rpcs3/Loader/Loader.cpp b/rpcs3/Loader/Loader.cpp index bae0e06a3e..cec0a3a09d 100644 --- a/rpcs3/Loader/Loader.cpp +++ b/rpcs3/Loader/Loader.cpp @@ -5,6 +5,8 @@ #include "PSF.h" #include "Emu/FS/vfsLocalFile.h" +static const u64 g_spu_offset = 0x10000; + const wxString Ehdr_DataToString(const u8 data) { if(data > 1) return wxString::Format("%d's complement, big endian", data); @@ -39,7 +41,7 @@ const wxString Ehdr_MachineToString(const u16 machine) { switch(machine) { - case MACHINE_MIPS: return "MIPS"; + case MACHINE_MIPS: return "MIPS"; case MACHINE_PPC64: return "PowerPC64"; case MACHINE_SPU: return "SPU"; }; @@ -92,14 +94,24 @@ const wxString Phdr_TypeToString(const u32 type) return wxString::Format("Unknown (%x)", type); } -Loader::Loader() : m_stream(nullptr) +Loader::Loader() + : m_stream(nullptr) + , m_loader(nullptr) { } -Loader::Loader(vfsFileBase& stream) : m_stream(&stream) +Loader::Loader(vfsFileBase& stream) + : m_stream(&stream) + , m_loader(nullptr) { } +Loader::~Loader() +{ + delete m_loader; + m_loader = nullptr; +} + void Loader::Open(vfsFileBase& stream) { m_stream = &stream; @@ -120,27 +132,35 @@ LoaderBase* Loader::SearchLoader() return nullptr; } -bool Loader::Load() +bool Loader::Analyze() { - static const u64 spu_offset = 0x10000; + delete m_loader; - ScopedPtr l = SearchLoader(); + m_loader = SearchLoader(); - if(!l) + if(!m_loader) { ConLog.Error("Unknown file type"); return false; } - if(!l->LoadData(l->GetMachine() == MACHINE_SPU ? spu_offset : 0)) + machine = m_loader->GetMachine(); + entry = m_loader->GetMachine() == MACHINE_SPU ? m_loader->GetEntry() + g_spu_offset : m_loader->GetEntry(); + + return true; +} + +bool Loader::Load() +{ + if(!m_loader) + return false; + + if(!m_loader->LoadData(m_loader->GetMachine() == MACHINE_SPU ? g_spu_offset : 0)) { ConLog.Error("Broken file"); return false; } - machine = l->GetMachine(); - entry = l->GetMachine() == MACHINE_SPU ? l->GetEntry() + spu_offset : l->GetEntry(); - const wxString& root = wxFileName(wxFileName(m_stream->GetPath()).GetPath()).GetPath(); const wxString& psf_path = root + "\\" + "PARAM.SFO"; if(wxFileExists(psf_path)) diff --git a/rpcs3/Loader/Loader.h b/rpcs3/Loader/Loader.h index 32c31d3056..f1f96df344 100644 --- a/rpcs3/Loader/Loader.h +++ b/rpcs3/Loader/Loader.h @@ -105,17 +105,16 @@ __forceinline static void Write16LE(wxFile& f, const u16 data) __forceinline static void Write32LE(wxFile& f, const u32 data) { - Write16(f, data); - Write16(f, data >> 16); + Write16LE(f, data); + Write16LE(f, data >> 16); } __forceinline static void Write64LE(wxFile& f, const u64 data) { - Write32(f, data); - Write32(f, data >> 32); + Write32LE(f, data); + Write32LE(f, data >> 32); } - const wxString Ehdr_DataToString(const u8 data); const wxString Ehdr_TypeToString(const u16 type); const wxString Ehdr_OS_ABIToString(const u8 os_abi); @@ -194,6 +193,7 @@ public: virtual bool LoadInfo() { return false; } virtual bool LoadData(u64 offset = 0) { return false; } Elf_Machine GetMachine() { return machine; } + u32 GetEntry() { return entry; } u32 GetMinAddr() { return min_addr; } u32 GetMaxAddr() { return min_addr; } @@ -202,13 +202,16 @@ public: class Loader : public LoaderBase { vfsFileBase* m_stream; + LoaderBase* m_loader; public: Loader(); Loader(vfsFileBase& stream); + ~Loader(); void Open(const wxString& path); void Open(vfsFileBase& stream); + bool Analyze(); bool Load(); diff --git a/rpcs3/rpcs3.cpp b/rpcs3/rpcs3.cpp index f716e8b532..31aff4fa1f 100644 --- a/rpcs3/rpcs3.cpp +++ b/rpcs3/rpcs3.cpp @@ -45,7 +45,7 @@ void Rpcs3App::Exit() wxApp::Exit(); } -void Rpcs3App::SendDbgCommand(DbgCommand id, PPCThread* thr) +void Rpcs3App::SendDbgCommand(DbgCommand id, CPUThread* thr) { wxCommandEvent event(wxEVT_DBG_COMMAND, id); event.SetClientData(thr); diff --git a/rpcs3/rpcs3.h b/rpcs3/rpcs3.h index 94dddbae9b..a740a34eec 100644 --- a/rpcs3/rpcs3.h +++ b/rpcs3/rpcs3.h @@ -61,7 +61,7 @@ public: virtual bool OnInit(); virtual void Exit(); - void SendDbgCommand(DbgCommand id, PPCThread* thr=nullptr); + void SendDbgCommand(DbgCommand id, CPUThread* thr=nullptr); }; DECLARE_APP(Rpcs3App) diff --git a/rpcs3/rpcs3.vcxproj b/rpcs3/rpcs3.vcxproj index 507900e07a..afe5bce6af 100644 --- a/rpcs3/rpcs3.vcxproj +++ b/rpcs3/rpcs3.vcxproj @@ -104,11 +104,13 @@ Disabled EditAndContinue Use + true true adv.lib;base.lib;core.lib;aui.lib;wxtiff.lib;wxjpeg.lib;wxpng.lib;wxzlib.lib;odbc32.lib;odbccp32.lib;comctl32.lib;ws2_32.lib;shlwapi.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;rpcrt4.lib;%(AdditionalDependencies) %(IgnoreSpecificDefaultLibraries) + false @@ -126,6 +128,7 @@ true adv.lib;base.lib;core.lib;aui.lib;wxtiff.lib;wxjpeg.lib;wxpng.lib;wxzlib.lib;odbc32.lib;odbccp32.lib;comctl32.lib;ws2_32.lib;shlwapi.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;rpcrt4.lib;%(AdditionalDependencies) %(IgnoreSpecificDefaultLibraries) + false $(SolutionDir)\Utilities\git-version-gen.cmd @@ -156,6 +159,7 @@ %(IgnoreSpecificDefaultLibraries) + false @@ -187,6 +191,7 @@ %(IgnoreSpecificDefaultLibraries) + false @@ -196,13 +201,15 @@ + - + + diff --git a/rpcs3/rpcs3.vcxproj.filters b/rpcs3/rpcs3.vcxproj.filters index 8204d53309..50c8918ded 100644 --- a/rpcs3/rpcs3.vcxproj.filters +++ b/rpcs3/rpcs3.vcxproj.filters @@ -17,9 +17,6 @@ {adfec460-d940-4482-9fdb-18cb0814c3d5} true - - {f66e37f9-5e58-443b-bcff-2e9e002ac89e} - {6c36f15e-07fd-45d6-a81c-1ab43ee1b58b} @@ -47,6 +44,15 @@ {718bc358-b7ef-4988-8547-2148d14bb08b} + + {f66e37f9-5e58-443b-bcff-2e9e002ac89e} + + + {041a844e-9f8b-4b4b-a4c5-6c72ecbde475} + + + {bee6a4b4-6371-4c1b-8558-fc7888b1574e} + @@ -116,13 +122,10 @@ Loader - Emu\CPU - - - Emu\CPU + Emu\Cell - Emu\CPU + Emu\Cell Emu\SysCalls @@ -188,7 +191,7 @@ Emu\GS - Emu\CPU + Emu\Cell Emu\SysCalls\lv2 @@ -251,7 +254,7 @@ rpcs3 - Emu\CPU + Emu\Cell Emu\SysCalls\lv2 @@ -263,10 +266,10 @@ Emu\SysCalls\Modules - Emu\CPU + Emu\Cell - Emu\CPU + Emu\Cell Emu\HDD @@ -310,6 +313,15 @@ Emu\FS + + Emu\CPU + + + Emu\CPU + + + Emu\ARM9 +