- Implemented ARM9Thread.

- Improved OpenGL Renderer.
- Improved RAW SPU mfc.
This commit is contained in:
DH 2013-11-03 21:23:16 +02:00
parent 6622dc42b5
commit 0b35be32a4
65 changed files with 3255 additions and 2207 deletions

View File

@ -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()
{
}

View File

@ -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();
};

873
rpcs3/Emu/CPU/CPUDecoder.h Normal file
View File

@ -0,0 +1,873 @@
#pragma once
#include "CPUInstrTable.h"
#pragma warning( disable : 4800 )
template<typename TO>
class InstrCaller
{
public:
virtual ~InstrCaller()
{
}
virtual void operator ()(TO* op, u32 code) const = 0;
virtual u32 operator [](u32) const
{
return 0;
}
};
template<typename TO>
class InstrBinder_0 : public InstrCaller<TO>
{
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<typename TO, typename T1>
class InstrBinder_1 : public InstrCaller<TO>
{
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<typename TO, typename T1, typename T2>
class InstrBinder_2 : public InstrCaller<TO>
{
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<typename TO, typename T1, typename T2, typename T3>
class InstrBinder_3 : public InstrCaller<TO>
{
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<typename TO, typename T1, typename T2, typename T3, typename T4>
class InstrBinder_4 : public InstrCaller<TO>
{
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<typename TO, typename T1, typename T2, typename T3, typename T4, typename T5>
class InstrBinder_5 : public InstrCaller<TO>
{
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<typename TO, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
class InstrBinder_6 : public InstrCaller<TO>
{
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<typename TO>
InstrCaller<TO>* instr_bind(void (TO::*func)())
{
return new InstrBinder_0<TO>(func);
}
template<typename TO, typename T1>
InstrCaller<TO>* instr_bind(void (TO::*func)(T1), const CodeFieldBase& arg_func_1)
{
return new InstrBinder_1<TO, T1>(func, arg_func_1);
}
template<typename TO, typename T1, typename T2>
InstrCaller<TO>* instr_bind(void (TO::*func)(T1, T2),
const CodeFieldBase& arg_func_1,
const CodeFieldBase& arg_func_2)
{
return new InstrBinder_2<TO, T1, T2>(func, arg_func_1, arg_func_2);
}
template<typename TO, typename T1, typename T2, typename T3>
InstrCaller<TO>* 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<TO, T1, T2, T3>(func, arg_func_1, arg_func_2, arg_func_3);
}
template<typename TO, typename T1, typename T2, typename T3, typename T4>
InstrCaller<TO>* 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<TO, T1, T2, T3, T4>(func, arg_func_1, arg_func_2, arg_func_3, arg_func_4);
}
template<typename TO, typename T1, typename T2, typename T3, typename T4, typename T5>
InstrCaller<TO>* 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<TO, T1, T2, T3, T4, T5>(func, arg_func_1, arg_func_2, arg_func_3, arg_func_4, arg_func_5);
}
template<typename TO, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
InstrCaller<TO>* 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<TO, T1, T2, T3, T4, T5, T6>(func, arg_func_1, arg_func_2, arg_func_3, arg_func_4, arg_func_5, arg_func_6);
}
template<typename TO>
class InstrBase : public InstrCaller<TO>
{
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<TO>()
, 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<u32>& args) const
{
return encode(args);
}
virtual void decode(TO* op, u32 code) const=0;
virtual u32 encode(const Array<u32>& args) const=0;
};
template<int _count, typename TO>
class InstrList : public InstrCaller<TO>
{
public:
static const int count = _count;
protected:
const CodeFieldBase& m_func;
InstrCaller<TO>* m_instrs[count];
InstrBase<TO>* m_instrs_info[count];
InstrCaller<TO>* m_error_func;
InstrCaller<TO>* m_parent;
int m_opcode;
public:
InstrList(const CodeFieldBase& func, InstrCaller<TO>* error_func)
: InstrCaller<TO>()
, m_func(func)
, m_error_func(error_func)
, m_parent(nullptr)
, m_opcode(-1)
{
for(int i=0; i<count; ++i)
{
m_instrs[i] = error_func;
}
memset(m_instrs_info, 0, sizeof(InstrBase<TO>*) * count);
}
virtual ~InstrList()
{
for(int i=0; i<count; ++i)
{
delete m_instrs[i];
}
delete m_error_func;
}
void set_parent(InstrCaller<TO>* parent, int opcode)
{
m_opcode = opcode;
m_parent = parent;
}
InstrCaller<TO>* get_parent() const
{
return m_parent;
}
u32 get_opcode() const
{
return m_opcode;
}
void set_error_func(InstrCaller<TO>* error_func)
{
for(int i=0; i<count; ++i)
{
if(m_instrs[i] == m_error_func || !m_instrs[i])
{
m_instrs[i] = error_func;
}
}
m_error_func = error_func;
}
void set_instr(uint pos, InstrCaller<TO>* func, InstrBase<TO>* info = nullptr)
{
assert(pos < count);
m_instrs[pos] = func;
m_instrs_info[pos] = info;
}
InstrCaller<TO>* get_instr(int pos) const
{
assert(pos < count);
return m_instrs[pos];
}
InstrBase<TO>* 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<int count1, int count2, typename TO>
static InstrList<count2, TO>* connect_list(InstrList<count1, TO>* parent, InstrList<count2, TO>* child, int opcode)
{
parent->set_instr(opcode, child);
child->set_parent(parent, opcode);
return child;
}
template<int count1, int count2, typename TO>
static InstrList<count2, TO>* connect_list(InstrList<count1, TO>* parent, InstrList<count2, TO>* child)
{
parent->set_error_func(child);
child->set_parent(parent->get_parent(), parent->get_opcode());
return child;
}
template<typename TO, int opcode, int count>
class Instr0 : public InstrBase<TO>
{
InstrList<count, TO>& m_list;
public:
Instr0(InstrList<count, TO>* 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<u32>& 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<typename TO, int opcode, int count, typename T1>
class Instr1 : public InstrBase<TO>
{
InstrList<count, TO>& m_list;
public:
Instr1(InstrList<count, TO>* 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<u32>& 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<typename TO, int opcode, int count, typename T1, typename T2>
class Instr2 : public InstrBase<TO>
{
InstrList<count, TO>& m_list;
public:
Instr2(InstrList<count, TO>* 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<u32>& 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<typename TO, int opcode, int count, typename T1, typename T2, typename T3>
class Instr3 : public InstrBase<TO>
{
InstrList<count, TO>& m_list;
public:
Instr3(InstrList<count, TO>* 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<u32>& 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<typename TO, int opcode, int count, typename T1, typename T2, typename T3, typename T4>
class Instr4 : public InstrBase<TO>
{
InstrList<count, TO>& m_list;
public:
Instr4(InstrList<count, TO>* 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<u32>& 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<typename TO, int opcode, int count, typename T1, typename T2, typename T3, typename T4, typename T5>
class Instr5 : public InstrBase<TO>
{
InstrList<count, TO>& m_list;
public:
Instr5(InstrList<count, TO>* 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<u32>& 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<typename TO, int opcode, int count, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
class Instr6 : public InstrBase<TO>
{
InstrList<count, TO>& m_list;
public:
Instr6(InstrList<count, TO>* 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<u32>& 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<int opcode, typename TO, int count>
static Instr0<TO, opcode, count>& make_instr(InstrList<count, TO>* list, const wxString& name, void (TO::*func)())
{
return *new Instr0<TO, opcode, count>(list, name, func);
}
template<int opcode, typename TO, int count, typename T1>
static Instr1<TO, opcode, count, T1>& make_instr(InstrList<count, TO>* list, const wxString& name,
void (TO::*func)(T1),
CodeFieldBase& arg_1)
{
return *new Instr1<TO, opcode, count, T1>(list, name, func, arg_1);
}
template<int opcode, typename TO, int count, typename T1, typename T2>
static Instr2<TO, opcode, count, T1, T2>& make_instr(InstrList<count, TO>* list, const wxString& name,
void (TO::*func)(T1, T2),
CodeFieldBase& arg_1,
CodeFieldBase& arg_2)
{
return *new Instr2<TO, opcode, count, T1, T2>(list, name, func, arg_1, arg_2);
}
template<int opcode, typename TO, int count, typename T1, typename T2, typename T3>
static Instr3<TO, opcode, count, T1, T2, T3>& make_instr(InstrList<count, TO>* list, const wxString& name,
void (TO::*func)(T1, T2, T3),
CodeFieldBase& arg_1,
CodeFieldBase& arg_2,
CodeFieldBase& arg_3)
{
return *new Instr3<TO, opcode, count, T1, T2, T3>(list, name, func, arg_1, arg_2, arg_3);
}
template<int opcode, typename TO, int count, typename T1, typename T2, typename T3, typename T4>
static Instr4<TO, opcode, count, T1, T2, T3, T4>& make_instr(InstrList<count, TO>* 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<TO, opcode, count, T1, T2, T3, T4>(list, name, func, arg_1, arg_2, arg_3, arg_4);
}
template<int opcode, typename TO, int count, typename T1, typename T2, typename T3, typename T4, typename T5>
static Instr5<TO, opcode, count, T1, T2, T3, T4, T5>& make_instr(InstrList<count, TO>* 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<TO, opcode, count, T1, T2, T3, T4, T5>(list, name, func, arg_1, arg_2, arg_3, arg_4, arg_5);
}
template<int opcode, typename TO, int count, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
static Instr6<TO, opcode, count, T1, T2, T3, T4, T5, T6>& make_instr(InstrList<count, TO>* 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<TO, opcode, count, T1, T2, T3, T4, T5, T6>(list, name, func, arg_1, arg_2, arg_3, arg_4, arg_5, arg_6);
}

63
rpcs3/Emu/CPU/CPUDisAsm.h Normal file
View File

@ -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<int>(8 - op.Len(), 0));
return op;
}
};

View File

@ -0,0 +1,34 @@
#pragma once
template<uint size, typename T> __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;
}
};

311
rpcs3/Emu/CPU/CPUThread.cpp Normal file
View File

@ -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<u64>& bp = Emu.GetBreakPoints();
try
{
for(uint i=0; i<bp.GetCount(); ++i)
{
if(bp[i] == m_offset + PC)
{
Emu.Pause();
break;
}
}
while(true)
{
int status = ThreadStatus();
if(status == CPUThread_Stopped || status == CPUThread_Break)
{
break;
}
if(status == CPUThread_Sleeping)
{
Sleep(1);
continue;
}
DoCode();
NextPc();
if(status == CPUThread_Step)
{
m_is_step = false;
break;
}
for(uint i=0; i<bp.GetCount(); ++i)
{
if(bp[i] == m_offset + PC)
{
Emu.Pause();
break;
}
}
}
}
catch(const wxString& e)
{
ConLog.Error("Exception: %s", e);
}
catch(const char* e)
{
ConLog.Error("Exception: %s", e);
}
//ConLog.Write("%s leave", CPUThread::GetFName());
if(m_free_data)
free(this);
}

183
rpcs3/Emu/CPU/CPUThread.h Normal file
View File

@ -0,0 +1,183 @@
#pragma once
#include "Emu/Memory/MemoryBlock.h"
#include "Emu/Cell/PPCDecoder.h"
enum CPUThreadType
{
CPU_THREAD_PPU,
CPU_THREAD_SPU,
CPU_THREAD_RAW_SPU,
CPU_THREAD_ARM9,
};
enum CPUThreadStatus
{
CPUThread_Ready,
CPUThread_Running,
CPUThread_Paused,
CPUThread_Stopped,
CPUThread_Sleeping,
CPUThread_Break,
CPUThread_Step,
};
class CPUThread : public ThreadBase
{
protected:
u32 m_status;
u32 m_error;
u32 m_id;
u64 m_prio;
u64 m_offset;
CPUThreadType m_type;
bool m_joinable;
bool m_joining;
bool m_free_data;
bool m_is_step;
u64 m_stack_addr;
u64 m_stack_size;
u64 m_stack_point;
u32 m_exit_status;
public:
virtual void InitRegs()=0;
virtual void InitStack()=0;
virtual void CloseStack();
u64 GetStackAddr() const { return m_stack_addr; }
u64 GetStackSize() const { return m_stack_size; }
virtual u64 GetFreeStackSize() const=0;
void SetStackAddr(u64 stack_addr) { m_stack_addr = stack_addr; }
void SetStackSize(u64 stack_size) { m_stack_size = stack_size; }
virtual void SetArg(const uint pos, const u64 arg) = 0;
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 CPUThreadTypeToString(CPUThreadType type)
{
switch(type)
{
case CPU_THREAD_PPU: return "PPU";
case CPU_THREAD_SPU: return "SPU";
case CPU_THREAD_RAW_SPU: return "RawSPU";
case CPU_THREAD_ARM9: return "ARM9";
}
return "Unknown";
}
wxString GetTypeString() const { return CPUThreadTypeToString(m_type); }
virtual wxString GetThreadName() const
{
return GetFName() + wxString::Format("[0x%08llx]", PC);
}
public:
u64 entry;
u64 PC;
u64 nPC;
u64 cycle;
protected:
CPUThread(CPUThreadType type);
public:
~CPUThread();
u32 m_wait_thread_id;
wxCriticalSection m_cs_sync;
bool m_sync_wait;
void Wait(bool wait);
void Wait(const CPUThread& thr);
bool Sync();
template<typename T>
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();

View File

@ -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<std::mutex> 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<std::mutex> lock(m_mtx_thread);
for(u32 i=0; i<m_threads.GetCount(); ++i)
{
if(m_threads[i].m_wait_thread_id == id)
{
m_threads[i].Wait(false);
m_threads[i].m_wait_thread_id = -1;
}
if(m_threads[i].GetId() != id) continue;
CPUThread* thr = &m_threads[i];
wxGetApp().SendDbgCommand(DID_REMOVE_THREAD, thr);
if(thr->IsAlive())
{
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.GetCount(); ++i)
{
if(m_threads[i].GetId() == id) return num;
if(m_threads[i].GetType() == type) num++;
}
return -1;
}
CPUThread* CPUThreadManager::GetThread(u32 id)
{
for(u32 i=0; i<m_threads.GetCount(); ++i)
{
if(m_threads[i].GetId() == id) return &m_threads[i];
}
return nullptr;
}
void CPUThreadManager::Exec()
{
for(u32 i=0; i<m_threads.GetCount(); ++i)
{
m_threads[i].Exec();
}
}

View File

@ -0,0 +1,27 @@
#pragma once
#include "CPUThread.h"
class CPUThreadManager
{
ArrayF<CPUThread> m_threads;
std::mutex m_mtx_thread;
wxSemaphore m_sem_task;
Stack<u32> m_delete_threads;
u32 m_raw_spu_num;
public:
CPUThreadManager();
~CPUThreadManager();
void Close();
CPUThread& AddThread(CPUThreadType type);
void RemoveThread(const u32 id);
ArrayF<CPUThread>& GetThreads() { return m_threads; }
s32 GetThreadNumById(CPUThreadType type, u32 id);
CPUThread* GetThread(u32 id);
void Exec();
void Task();
};

View File

@ -1,24 +1,8 @@
#pragma once
#include "Emu/CPU/CPUDecoder.h"
#include "PPCInstrTable.h"
#pragma warning( disable : 4800 )
template<typename TO>
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<typename TO>
class InstrBinder_0 : public InstrCaller<TO>
{
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<typename TO, typename T1>
class InstrBinder_1 : public InstrCaller<TO>
{
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<typename TO, typename T1, typename T2>
class InstrBinder_2 : public InstrCaller<TO>
{
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<typename TO, typename T1, typename T2, typename T3>
class InstrBinder_3 : public InstrCaller<TO>
{
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<typename TO, typename T1, typename T2, typename T3, typename T4>
class InstrBinder_4 : public InstrCaller<TO>
{
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<typename TO, typename T1, typename T2, typename T3, typename T4, typename T5>
class InstrBinder_5 : public InstrCaller<TO>
{
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<typename TO, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
class InstrBinder_6 : public InstrCaller<TO>
{
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<typename TO>
InstrCaller<TO>* instr_bind(void (TO::*func)())
{
return new InstrBinder_0<TO>(func);
}
template<typename TO, typename T1>
InstrCaller<TO>* instr_bind(void (TO::*func)(T1), const CodeFieldBase& arg_func_1)
{
return new InstrBinder_1<TO, T1>(func, arg_func_1);
}
template<typename TO, typename T1, typename T2>
InstrCaller<TO>* instr_bind(void (TO::*func)(T1, T2),
const CodeFieldBase& arg_func_1,
const CodeFieldBase& arg_func_2)
{
return new InstrBinder_2<TO, T1, T2>(func, arg_func_1, arg_func_2);
}
template<typename TO, typename T1, typename T2, typename T3>
InstrCaller<TO>* 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<TO, T1, T2, T3>(func, arg_func_1, arg_func_2, arg_func_3);
}
template<typename TO, typename T1, typename T2, typename T3, typename T4>
InstrCaller<TO>* 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<TO, T1, T2, T3, T4>(func, arg_func_1, arg_func_2, arg_func_3, arg_func_4);
}
template<typename TO, typename T1, typename T2, typename T3, typename T4, typename T5>
InstrCaller<TO>* 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<TO, T1, T2, T3, T4, T5>(func, arg_func_1, arg_func_2, arg_func_3, arg_func_4, arg_func_5);
}
template<typename TO, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
InstrCaller<TO>* 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<TO, T1, T2, T3, T4, T5, T6>(func, arg_func_1, arg_func_2, arg_func_3, arg_func_4, arg_func_5, arg_func_6);
}
template<typename TO>
class InstrBase : public InstrCaller<TO>
{
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<TO>()
, 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<u32>& args) const
{
return encode(args);
}
virtual void decode(TO* op, u32 code) const=0;
virtual u32 encode(const Array<u32>& args) const=0;
};
template<int _count, typename TO>
class InstrList : public InstrCaller<TO>
{
public:
static const int count = _count;
protected:
const CodeFieldBase& m_func;
InstrCaller<TO>* m_instrs[count];
InstrBase<TO>* m_instrs_info[count];
InstrCaller<TO>* m_error_func;
InstrCaller<TO>* m_parent;
int m_opcode;
public:
InstrList(const CodeFieldBase& func, InstrCaller<TO>* error_func)
: InstrCaller<TO>()
, m_func(func)
, m_error_func(error_func)
, m_parent(nullptr)
, m_opcode(-1)
{
for(int i=0; i<count; ++i)
{
m_instrs[i] = error_func;
}
memset(m_instrs_info, 0, sizeof(InstrBase<TO>*) * count);
}
virtual ~InstrList()
{
for(int i=0; i<count; ++i)
{
delete m_instrs[i];
}
delete m_error_func;
}
void set_parent(InstrCaller<TO>* parent, int opcode)
{
m_opcode = opcode;
m_parent = parent;
}
InstrCaller<TO>* get_parent() const
{
return m_parent;
}
u32 get_opcode() const
{
return m_opcode;
}
void set_error_func(InstrCaller<TO>* error_func)
{
for(int i=0; i<count; ++i)
{
if(m_instrs[i] == m_error_func || !m_instrs[i])
{
m_instrs[i] = error_func;
}
}
m_error_func = error_func;
}
void set_instr(uint pos, InstrCaller<TO>* func, InstrBase<TO>* info = nullptr)
{
assert(pos < count);
m_instrs[pos] = func;
m_instrs_info[pos] = info;
}
InstrCaller<TO>* get_instr(int pos) const
{
assert(pos < count);
return m_instrs[pos];
}
InstrBase<TO>* 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<int count1, int count2, typename TO>
static InstrList<count2, TO>* connect_list(InstrList<count1, TO>* parent, InstrList<count2, TO>* child, int opcode)
{
parent->set_instr(opcode, child);
child->set_parent(parent, opcode);
return child;
}
template<int count1, int count2, typename TO>
static InstrList<count2, TO>* connect_list(InstrList<count1, TO>* parent, InstrList<count2, TO>* child)
{
parent->set_error_func(child);
child->set_parent(parent->get_parent(), parent->get_opcode());
return child;
}
template<typename TO, uint from, uint to>
static InstrList<1 << CodeField<from, to>::size, TO>* new_list(const CodeField<from, to>& func, InstrCaller<TO>* error_func = nullptr)
@ -500,403 +30,4 @@ template<int count, typename TO, uint from, uint to>
static InstrList<1 << CodeField<from, to>::size, TO>* new_list(InstrList<count, TO>* parent, const CodeField<from, to>& func, InstrCaller<TO>* error_func = nullptr)
{
return connect_list(parent, new InstrList<1 << CodeField<from, to>::size, TO>(func, error_func));
}
template<typename TO, int opcode, int count>
class Instr0 : public InstrBase<TO>
{
InstrList<count, TO>& m_list;
public:
Instr0(InstrList<count, TO>* 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<u32>& 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<typename TO, int opcode, int count, typename T1>
class Instr1 : public InstrBase<TO>
{
InstrList<count, TO>& m_list;
public:
Instr1(InstrList<count, TO>* 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<u32>& 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<typename TO, int opcode, int count, typename T1, typename T2>
class Instr2 : public InstrBase<TO>
{
InstrList<count, TO>& m_list;
public:
Instr2(InstrList<count, TO>* 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<u32>& 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<typename TO, int opcode, int count, typename T1, typename T2, typename T3>
class Instr3 : public InstrBase<TO>
{
InstrList<count, TO>& m_list;
public:
Instr3(InstrList<count, TO>* 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<u32>& 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<typename TO, int opcode, int count, typename T1, typename T2, typename T3, typename T4>
class Instr4 : public InstrBase<TO>
{
InstrList<count, TO>& m_list;
public:
Instr4(InstrList<count, TO>* 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<u32>& 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<typename TO, int opcode, int count, typename T1, typename T2, typename T3, typename T4, typename T5>
class Instr5 : public InstrBase<TO>
{
InstrList<count, TO>& m_list;
public:
Instr5(InstrList<count, TO>* 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<u32>& 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<typename TO, int opcode, int count, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
class Instr6 : public InstrBase<TO>
{
InstrList<count, TO>& m_list;
public:
Instr6(InstrList<count, TO>* 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<u32>& 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<int opcode, typename TO, int count>
static Instr0<TO, opcode, count>& make_instr(InstrList<count, TO>* list, const wxString& name, void (TO::*func)())
{
return *new Instr0<TO, opcode, count>(list, name, func);
}
template<int opcode, typename TO, int count, typename T1>
static Instr1<TO, opcode, count, T1>& make_instr(InstrList<count, TO>* list, const wxString& name,
void (TO::*func)(T1),
CodeFieldBase& arg_1)
{
return *new Instr1<TO, opcode, count, T1>(list, name, func, arg_1);
}
template<int opcode, typename TO, int count, typename T1, typename T2>
static Instr2<TO, opcode, count, T1, T2>& make_instr(InstrList<count, TO>* list, const wxString& name,
void (TO::*func)(T1, T2),
CodeFieldBase& arg_1,
CodeFieldBase& arg_2)
{
return *new Instr2<TO, opcode, count, T1, T2>(list, name, func, arg_1, arg_2);
}
template<int opcode, typename TO, int count, typename T1, typename T2, typename T3>
static Instr3<TO, opcode, count, T1, T2, T3>& make_instr(InstrList<count, TO>* list, const wxString& name,
void (TO::*func)(T1, T2, T3),
CodeFieldBase& arg_1,
CodeFieldBase& arg_2,
CodeFieldBase& arg_3)
{
return *new Instr3<TO, opcode, count, T1, T2, T3>(list, name, func, arg_1, arg_2, arg_3);
}
template<int opcode, typename TO, int count, typename T1, typename T2, typename T3, typename T4>
static Instr4<TO, opcode, count, T1, T2, T3, T4>& make_instr(InstrList<count, TO>* 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<TO, opcode, count, T1, T2, T3, T4>(list, name, func, arg_1, arg_2, arg_3, arg_4);
}
template<int opcode, typename TO, int count, typename T1, typename T2, typename T3, typename T4, typename T5>
static Instr5<TO, opcode, count, T1, T2, T3, T4, T5>& make_instr(InstrList<count, TO>* 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<TO, opcode, count, T1, T2, T3, T4, T5>(list, name, func, arg_1, arg_2, arg_3, arg_4, arg_5);
}
template<int opcode, typename TO, int count, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
static Instr6<TO, opcode, count, T1, T2, T3, T4, T5, T6>& make_instr(InstrList<count, TO>* 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<TO, opcode, count, T1, T2, T3, T4, T5, T6>(list, name, func, arg_1, arg_2, arg_3, arg_4, arg_5, arg_6);
}

View File

@ -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<int>(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;

View File

@ -1,16 +1,5 @@
#pragma once
template<uint size, typename T> __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<uint from, uint to=from>
class CodeField : public CodeFieldBase
{

View File

@ -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<u64>& bp = Emu.GetBreakPoints();
try
{
for(uint i=0; i<bp.GetCount(); ++i)
{
if(bp[i] == m_offset + PC)
{
Emu.Pause();
break;
}
}
while(true)
{
int status = ThreadStatus();
if(status == PPCThread_Stopped || status == PPCThread_Break)
{
break;
}
if(status == PPCThread_Sleeping)
{
Sleep(1);
continue;
}
DoCode(Memory.Read32(m_offset + PC));
NextPc();
if(status == PPCThread_Step)
{
m_is_step = false;
break;
}
for(uint i=0; i<bp.GetCount(); ++i)
{
if(bp[i] == m_offset + PC)
{
Emu.Pause();
break;
}
}
}
}
catch(const wxString& e)
{
ConLog.Error("Exception: %s", e);
}
catch(const char* e)
{
ConLog.Error("Exception: %s", e);
}
//ConLog.Write("%s leave", PPCThread::GetFName());
if(m_free_data)
free(this);
}

View File

@ -1,186 +1,38 @@
#pragma once
#include "Emu/Memory/MemoryBlock.h"
#include "Emu/CPU/CPUThread.h"
#include "Emu/Cell/PPCDecoder.h"
enum PPCThreadType
{
PPC_THREAD_PPU,
PPC_THREAD_SPU,
PPC_THREAD_RAW_SPU,
};
enum PPCThreadStatus
{
PPCThread_Ready,
PPCThread_Running,
PPCThread_Paused,
PPCThread_Stopped,
PPCThread_Sleeping,
PPCThread_Break,
PPCThread_Step,
};
class PPCThread : public ThreadBase
class PPCThread : public CPUThread
{
protected:
u32 m_status;
u32 m_error;
PPC_Decoder* m_dec;
wxWindow* DisAsmFrame;
u32 m_id;
PPCThreadType m_type;
PPCDecoder* m_dec;
u64 m_args[4];
u64 m_prio;
bool m_joinable;
bool m_joining;
Array<u64> argv_addr;
u64 m_offset;
u32 m_exit_status;
bool m_free_data;
bool m_is_step;
Array<u64> 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<typename T>
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();

View File

@ -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;
}

View File

@ -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;

View File

@ -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<PPU_opcodes::name>(list, #name, &PPU_Opcodes::name, ##__VA_ARGS__)
static const auto& name = make_instr<PPU_opcodes::name>(list, #name, &PPUOpcodes::name, ##__VA_ARGS__)
bind_instr(main_list, TDI, TO, RA, simm16);
bind_instr(main_list, TWI, TO, RA, simm16);

View File

@ -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);

View File

@ -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);

View File

@ -362,7 +362,7 @@ void CompilePPUProgram::DetectArgInfo(Arg& arg)
return;
}
if(GetInstruction<PPU_Opcodes>(str))
if(GetInstruction<PPUOpcodes>(str))
{
arg.type = ARG_INSTR;
return;
@ -1397,17 +1397,9 @@ void CompilePPUProgram::Compile()
LoadArgs();
auto instr = GetInstruction<PPU_Opcodes>(op);
auto instr = GetInstruction<PPUOpcodes>(op);
if(instr)
{
/*
FIELD_IMM,
FIELD_R_GPR,
FIELD_R_FPR,
FIELD_R_VPR,
FIELD_R_CR,
FIELD_BRANCH,
*/
uint type[] =
{
ARG_IMM,

View File

@ -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<argc; ++i) argv_list += argv_addr[i];
for(int i=0; i<argc; ++i) argv_list += m_argv_addr[i];
GPR[3] = argc;
GPR[4] = argv;
@ -149,12 +149,12 @@ void PPUThread::DoRun()
switch(Ini.CPUDecoderMode.GetValue())
{
case 0:
m_dec = new PPU_Decoder(*new PPU_DisAsm(*this));
//m_dec = new PPUDecoder(*new PPUDisAsm());
break;
case 1:
case 2:
m_dec = new PPU_Decoder(*new PPU_Interpreter(*this));
m_dec = new PPUDecoder(*new PPUInterpreter(*this));
break;
}
}
@ -178,8 +178,10 @@ void PPUThread::DoStop()
bool dump_enable = false;
void PPUThread::DoCode(const s32 code)
void PPUThread::DoCode()
{
const u32 code = Memory.Read32(m_offset + PC);
#ifdef _DEBUG
static bool is_last_enabled = false;

View File

@ -511,9 +511,7 @@ union VPR_reg
static const s32 MAX_INT_VALUE = 0x7fffffff;
class PPUThread
: public PPCThread
, public SysCalls
class PPUThread : public PPCThread
{
public:
PPCdouble FPR[32]; //Floating Point Register
@ -727,7 +725,7 @@ public:
virtual wxString RegsToString()
{
wxString ret = PPCThread::RegsToString();
wxString ret;
for(uint i=0; i<32; ++i) ret += wxString::Format("GPR[%d] = 0x%llx\n", i, GPR[i]);
for(uint i=0; i<32; ++i) ret += wxString::Format("FPR[%d] = %.6G\n", i, FPR[i]);
@ -768,6 +766,7 @@ public:
if (reg == "CTR") return wxString::Format("%016llx", CTR);
if (reg == "XER") return wxString::Format("%016llx", XER);
if (reg == "FPSCR") return wxString::Format("%08x", FPSCR);
return wxEmptyString;
}
@ -829,8 +828,7 @@ protected:
virtual void DoResume();
virtual void DoStop();
public:
virtual void DoCode(const s32 code);
virtual void DoCode();
};
PPUThread& GetCurrentPPUThread();

View File

@ -1,51 +1,259 @@
#include "stdafx.h"
#include "Emu/Cell/RawSPUThread.h"
RawSPUThread::RawSPUThread(PPCThreadType type) : SPUThread(type)
RawSPUThread::RawSPUThread(u32 index, CPUThreadType type)
: SPUThread(type)
, m_index(index)
{
Memory.MemoryBlocks.Add(MemoryBlock::SetRange(RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * index, RAW_SPU_OFFSET));
Reset();
}
RawSPUThread::~RawSPUThread()
{
MemoryBlock::Delete();
}
bool RawSPUThread::Read8(const u64 addr, u8* value)
{
if(addr < GetStartAddr() + RAW_SPU_PROB_OFFSET)
{
return MemoryBlock::Read8(addr, value);
}
u32 offset = addr - GetStartAddr() - RAW_SPU_PROB_OFFSET;
ConLog.Error("RawSPUThread[%d]: Read8(0x%x)", m_index, offset);
Emu.Pause();
return false;
}
bool RawSPUThread::Read16(const u64 addr, u16* value)
{
if(addr < GetStartAddr() + RAW_SPU_PROB_OFFSET)
{
return MemoryBlock::Read16(addr, value);
}
u32 offset = addr - GetStartAddr() - RAW_SPU_PROB_OFFSET;
ConLog.Error("RawSPUThread[%d]: Read16(0x%x)", m_index, offset);
Emu.Pause();
return false;
}
bool RawSPUThread::Read32(const u64 addr, u32* value)
{
if(addr < GetStartAddr() + RAW_SPU_PROB_OFFSET)
{
return MemoryBlock::Read32(addr, value);
}
u32 offset = addr - GetStartAddr() - RAW_SPU_PROB_OFFSET;
switch(offset)
{
case MFC_LSA_offs: ConLog.Warning("RawSPUThread[%d]: Read32(MFC_LSA)", m_index); *value = MFC.LSA.GetValue(); break;
case MFC_EAH_offs: ConLog.Warning("RawSPUThread[%d]: Read32(MFC_EAH)", m_index); *value = MFC.EAH.GetValue(); break;
case MFC_EAL_offs: ConLog.Warning("RawSPUThread[%d]: Read32(MFC_EAL)", m_index); *value = MFC.EAL.GetValue(); break;
case MFC_Size_Tag_offs: ConLog.Warning("RawSPUThread[%d]: Read32(MFC_Size_Tag)", m_index); *value = MFC.Size_Tag.GetValue(); break;
case MFC_CMDStatus_offs: ConLog.Warning("RawSPUThread[%d]: Read32(MFC_CMDStatus)", m_index); *value = MFC.CMDStatus.GetValue(); break;
case MFC_QStatus_offs: ConLog.Warning("RawSPUThread[%d]: Read32(MFC_QStatus)", m_index); *value = MFC.QStatus.GetValue(); break;
case Prxy_QueryType_offs: ConLog.Warning("RawSPUThread[%d]: Read32(Prxy_QueryType)", m_index); *value = Prxy.QueryType.GetValue(); break;
case Prxy_QueryMask_offs: ConLog.Warning("RawSPUThread[%d]: Read32(Prxy_QueryMask)", m_index); *value = Prxy.QueryMask.GetValue(); break;
case Prxy_TagStatus_offs: ConLog.Warning("RawSPUThread[%d]: Read32(Prxy_TagStatus)", m_index); *value = Prxy.TagStatus.GetValue(); break;
case SPU_Out_MBox_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_Out_MBox)", m_index); *value = SPU.Out_MBox.GetValue(); break;
case SPU_In_MBox_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_In_MBox)", m_index); *value = SPU.In_MBox.GetValue(); break;
case SPU_MBox_Status_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_MBox_Status)", m_index); *value = SPU.MBox_Status.GetValue(); break;
case SPU_RunCntl_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_RunCntl)", m_index); *value = SPU.RunCntl.GetValue(); break;
case SPU_Status_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_Status)", m_index); *value = SPU.Status.GetValue(); break;
case SPU_NPC_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_NPC)", m_index); *value = SPU.NPC.GetValue(); break;
case SPU_RdSigNotify1_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_RdSigNotify1)", m_index); *value = SPU.RdSigNotify1.GetValue(); break;
case SPU_RdSigNotify2_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_RdSigNotify2)", m_index); *value = SPU.RdSigNotify2.GetValue(); break;
default:
ConLog.Error("RawSPUThread[%d]: Read32(0x%x)", m_index, offset);
Emu.Pause();
break;
}
return true;
}
bool RawSPUThread::Read64(const u64 addr, u64* value)
{
if(addr < GetStartAddr() + RAW_SPU_PROB_OFFSET)
{
return MemoryBlock::Read64(addr, value);
}
u32 offset = addr - GetStartAddr() - RAW_SPU_PROB_OFFSET;
ConLog.Error("RawSPUThread[%d]: Read64(0x%x)", m_index, offset);
Emu.Pause();
return false;
}
bool RawSPUThread::Read128(const u64 addr, u128* value)
{
if(addr < GetStartAddr() + RAW_SPU_PROB_OFFSET)
{
return MemoryBlock::Read128(addr, value);
}
u32 offset = addr - GetStartAddr() - RAW_SPU_PROB_OFFSET;
ConLog.Error("RawSPUThread[%d]: Read128(0x%x)", m_index, offset);
Emu.Pause();
return false;
}
bool RawSPUThread::Write8(const u64 addr, const u8 value)
{
if(addr < GetStartAddr() + RAW_SPU_PROB_OFFSET)
{
return MemoryBlock::Write8(addr, value);
}
u32 offset = addr - GetStartAddr() - RAW_SPU_PROB_OFFSET;
ConLog.Error("RawSPUThread[%d]: Write8(0x%x, 0x%x)", m_index, offset, value);
Emu.Pause();
return false;
}
bool RawSPUThread::Write16(const u64 addr, const u16 value)
{
if(addr < GetStartAddr() + RAW_SPU_PROB_OFFSET)
{
return MemoryBlock::Write16(addr, value);
}
u32 offset = addr - GetStartAddr() - RAW_SPU_PROB_OFFSET;
ConLog.Error("RawSPUThread[%d]: Write16(0x%x, 0x%x)", m_index, offset, value);
Emu.Pause();
return false;
}
bool RawSPUThread::Write32(const u64 addr, const u32 value)
{
if(addr < GetStartAddr() + RAW_SPU_PROB_OFFSET)
{
return MemoryBlock::Write32(addr, value);
}
u32 offset = addr - GetStartAddr() - RAW_SPU_PROB_OFFSET;
switch(offset)
{
case MFC_LSA_offs: ConLog.Warning("RawSPUThread[%d]: Write32(MFC_LSA, 0x%x)", m_index, value); MFC.LSA.SetValue(value); break;
case MFC_EAH_offs: ConLog.Warning("RawSPUThread[%d]: Write32(MFC_EAH, 0x%x)", m_index, value); MFC.EAH.SetValue(value); break;
case MFC_EAL_offs: ConLog.Warning("RawSPUThread[%d]: Write32(MFC_EAL, 0x%x)", m_index, value); MFC.EAL.SetValue(value); break;
case MFC_Size_Tag_offs: ConLog.Warning("RawSPUThread[%d]: Write32(MFC_Size_Tag, 0x%x)", m_index, value); MFC.Size_Tag.SetValue(value); break;
case MFC_CMDStatus_offs:
{
ConLog.Warning("RawSPUThread[%d]: Write32(MFC_CMDStatus, 0x%x)", m_index, value);
MFC.CMDStatus.SetValue(value);
u16 op = value & MFC_MASK_CMD;
switch(op)
{
case MFC_PUT_CMD:
case MFC_GET_CMD:
{
u32 lsa = MFC.LSA.GetValue();
u64 ea = (u64)MFC.EAL.GetValue() | ((u64)MFC.EAH.GetValue() << 32);
u32 size_tag = MFC.Size_Tag.GetValue();
u16 tag = (u16)size_tag;
u16 size = size_tag >> 16;
ConLog.Warning("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; i<bp.GetCount(); ++i)
@ -128,4 +334,4 @@ void RawSPUThread::Task()
}
ConLog.Write("%s leave", PPCThread::GetFName());
}
}

View File

@ -39,30 +39,34 @@ __forceinline static u32 GetRawSPURegAddrByNum(int num, int offset)
__forceinline static u32 GetRawSPURegAddrById(int id, int offset)
{
return GetRawSPURegAddrByNum(Emu.GetCPU().GetThreadNumById(PPC_THREAD_RAW_SPU, id), offset);
return GetRawSPURegAddrByNum(Emu.GetCPU().GetThreadNumById(CPU_THREAD_RAW_SPU, id), offset);
}
class RawSPUThread : public SPUThread
class RawSPUThread
: public SPUThread
, public MemoryBlock
{
u32 m_index;
public:
RawSPUThread(PPCThreadType type = PPC_THREAD_RAW_SPU);
RawSPUThread(u32 index, CPUThreadType type = CPU_THREAD_RAW_SPU);
~RawSPUThread();
virtual u8 ReadLS8 (const u32 lsa) const { return Memory.Read8 (lsa + (m_offset & 0x3fffc)); }
virtual u16 ReadLS16 (const u32 lsa) const { return Memory.Read16 (lsa + m_offset); }
virtual u32 ReadLS32 (const u32 lsa) const { return Memory.Read32 (lsa + m_offset); }
virtual u64 ReadLS64 (const u32 lsa) const { return Memory.Read64 (lsa + m_offset); }
virtual u128 ReadLS128(const u32 lsa) const { return Memory.Read128(lsa + m_offset); }
virtual bool Read8(const u64 addr, u8* value) override;
virtual bool Read16(const u64 addr, u16* value) override;
virtual bool Read32(const u64 addr, u32* value) override;
virtual bool Read64(const u64 addr, u64* value) override;
virtual bool Read128(const u64 addr, u128* value) override;
virtual void WriteLS8 (const u32 lsa, const u8& data) const { Memory.Write8 (lsa + m_offset, data); }
virtual void WriteLS16 (const u32 lsa, const u16& data) const { Memory.Write16 (lsa + m_offset, data); }
virtual void WriteLS32 (const u32 lsa, const u32& data) const { Memory.Write32 (lsa + m_offset, data); }
virtual void WriteLS64 (const u32 lsa, const u64& data) const { Memory.Write64 (lsa + m_offset, data); }
virtual void WriteLS128(const u32 lsa, const u128& data) const { Memory.Write128(lsa + m_offset, data); }
virtual bool Write8(const u64 addr, const u8 value) override;
virtual bool Write16(const u64 addr, const u16 value) override;
virtual bool Write32(const u64 addr, const u32 value) override;
virtual bool Write64(const u64 addr, const u64 value) override;
virtual bool Write128(const u64 addr, const u128 value) override;
public:
virtual void InitRegs();
u32 GetIndex() const;
private:
virtual void Task();

View File

@ -4,18 +4,17 @@
#include "Emu/Cell/PPCDecoder.h"
#include "Emu/Cell/SPUInstrtable.h"
class SPU_Decoder : public PPC_Decoder
class SPUDecoder : public PPCDecoder
{
SPU_Opcodes* m_op;
SPUOpcodes* m_op;
public:
SPU_Decoder(SPU_Opcodes& op) : m_op(&op)
SPUDecoder(SPUOpcodes& op) : m_op(&op)
{
}
~SPU_Decoder()
~SPUDecoder()
{
m_op->Exit();
delete m_op;
}

View File

@ -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:

View File

@ -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<SPU_Opcodes>(RRR);
static auto rrr_list = new_list<SPUOpcodes>(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<SPU_opcodes::name>(list, #name, &SPU_Opcodes::name, ##__VA_ARGS__)
static const auto& name = make_instr<SPU_opcodes::name>(list, #name, &SPUOpcodes::name, ##__VA_ARGS__)
bind_instr(ri7_list, STOP, L_18_31);
bind_instr(ri7_list, LNOP);

View File

@ -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()
{
}

View File

@ -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;

View File

@ -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));
}

View File

@ -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<u32, 1> SPU_OutIntr_Mbox;
template<size_t _max_count>
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();

View File

@ -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; i<m_parr.params.GetCount(); ++i)
{
p += m_parr.params[i].Format();
@ -233,16 +236,18 @@ void FragmentDecompilerThread::Task()
m_offset = 4 * 4;
switch(dst.opcode | (src1.opcode_is_branch << 6))
const u32 opcode = dst.opcode | (src1.opcode_is_branch << 6);
switch(opcode)
{
case 0x00: break; //NOP
case 0x01: AddCode(GetSRC(src0)); break; //MOV
case 0x02: AddCode("(" + GetSRC(src0) + " * " + GetSRC(src1) + ")"); break; //MUL
case 0x03: AddCode("(" + GetSRC(src0) + " + " + GetSRC(src1) + ")"); break; //ADD
case 0x04: AddCode("(" + GetSRC(src0) + " * " + GetSRC(src1) + " + " + GetSRC(src2) + ")"); break; //MAD
case 0x05: AddCode("vec4(dot(" + GetSRC(src0) + ".xyz, " + GetSRC(src1) + ".xyz)).xxxx"); break; // DP3
case 0x06: AddCode("vec4(dot(" + GetSRC(src0) + ", " + GetSRC(src1) + ")).xxxx"); break; // DP4
case 0x07: AddCode("vec4(distance(" + GetSRC(src0) + ", " + GetSRC(src1) + ")).xxxx"); break; // DST
case 0x05: AddCode("vec2(dot(" + GetSRC(src0) + ".xyz, " + GetSRC(src1) + ".xyz), 0).xxxx"); break; // DP3
case 0x06: AddCode("vec2(dot(" + GetSRC(src0) + ", " + GetSRC(src1) + "), 0).xxxx"); break; // DP4
case 0x07: AddCode("vec2(distance(" + GetSRC(src0) + ", " + GetSRC(src1) + "), 0).xxxx"); break; // DST
case 0x08: AddCode("min(" + GetSRC(src0) + ", " + GetSRC(src1) + ")"); break; // MIN
case 0x09: AddCode("max(" + GetSRC(src0) + ", " + GetSRC(src1) + ")"); break; // MAX
case 0x0a: AddCode("vec4(lessThan(" + GetSRC(src0) + ", " + GetSRC(src1) + "))"); break; // SLT
@ -292,7 +297,7 @@ void FragmentDecompilerThread::Task()
//case 0x35: break; // BEMLUM
//case 0x36: break; // REFL
//case 0x37: break; // TIMESWTEX
case 0x38: AddCode("vec4(dot(" + GetSRC(src0) + ".xy, " + GetSRC(src1) + ".xy)).xxxx"); break; // DP2
case 0x38: AddCode("vec2(dot(" + GetSRC(src0) + ".xy, " + GetSRC(src1) + ".xy)).xxxx"); break; // DP2
case 0x39: AddCode("normalize(" + GetSRC(src0) + ".xyz)"); break; // NRM
case 0x3a: AddCode("(" + GetSRC(src0) + " / " + GetSRC(src1) + ")"); break; // DIV
case 0x3b: AddCode("(" + GetSRC(src0) + " / sqrt(" + GetSRC(src1) + "))"); break; // DIVSQ
@ -301,7 +306,7 @@ void FragmentDecompilerThread::Task()
case 0x3e: break; // FENCB
default:
ConLog.Error("Unknown opcode 0x%x (inst %d)", dst.opcode, m_size / (4 * 4));
ConLog.Error("Unknown opcode 0x%x (inst %d)", opcode, m_size / (4 * 4));
Emu.Pause();
break;
}

View File

@ -104,6 +104,7 @@ struct FragmentDecompilerThread : public ThreadBase
u32& m_size;
u32 m_const_index;
u32 m_offset;
u32 m_location;
FragmentDecompilerThread(wxString& shader, ParamArray& parr, u32 addr, u32& size)
: ThreadBase(false, "Fragment Shader Decompiler Thread")
@ -112,6 +113,7 @@ struct FragmentDecompilerThread : public ThreadBase
, m_addr(addr)
, m_size(size)
, m_const_index(0)
, m_location(0)
{
m_size = 0;
}

View File

@ -135,11 +135,13 @@ GLrbo::~GLrbo()
void GLrbo::Create(u32 count)
{
if(m_id.GetCount())
if(m_id.GetCount() == count)
{
return;
}
Delete();
m_id.SetCount(count);
glGenRenderbuffers(count, m_id.GetPtr());
}
@ -163,6 +165,11 @@ void GLrbo::Unbind()
void GLrbo::Delete()
{
if(!IsCreated())
{
return;
}
glDeleteRenderbuffers(m_id.GetCount(), m_id.GetPtr());
m_id.Clear();
}
@ -198,11 +205,15 @@ void GLfbo::Create()
void GLfbo::Bind(u32 type, int id)
{
if(id != -1)
assert(m_id);
glBindFramebuffer(type, id);
}
void GLfbo::Bind(u32 type)
{
assert(IsCreated());
m_type = type;
glBindFramebuffer(m_type, id == -1 ? m_id : id);
Bind(type, m_id);
}
void GLfbo::Texture1D(u32 attachment, u32 texture, int level)
@ -242,6 +253,11 @@ void GLfbo::Unbind(u32 type)
void GLfbo::Delete()
{
if(!IsCreated())
{
return;
}
glDeleteFramebuffers(1, &m_id);
m_id = 0;
}

View File

@ -77,12 +77,13 @@ public:
~GLfbo();
void Create();
void Bind(u32 type = GL_FRAMEBUFFER, int id = -1);
static void Bind(u32 type, int id);
void Bind(u32 type = GL_FRAMEBUFFER);
void Texture1D(u32 attachment, u32 texture, int level = 0);
void Texture2D(u32 attachment, u32 texture, int level = 0);
void Texture3D(u32 attachment, u32 texture, int zoffset = 0, int level = 0);
void Renderbuffer(u32 attachment, u32 renderbuffer);
void Blit(int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0, int dstX1, int dstY1, u32 mask, u32 filter);
static void Blit(int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0, int dstX1, int dstY1, u32 mask, u32 filter);
void Unbind();
static void Unbind(u32 type);
void Delete();

View File

@ -559,17 +559,14 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u
if(m_fbo.IsCreated())
{
m_fbo.Bind(GL_READ_FRAMEBUFFER);
m_fbo.Bind(GL_DRAW_FRAMEBUFFER, 0);
m_fbo.Blit(
GLfbo::Bind(GL_DRAW_FRAMEBUFFER, 0);
GLfbo::Blit(
m_surface_clip_x, m_surface_clip_y, m_surface_clip_x + m_surface_clip_w, m_surface_clip_y + m_surface_clip_h,
m_surface_clip_x, m_surface_clip_y, m_surface_clip_x + m_surface_clip_w, m_surface_clip_y + m_surface_clip_h,
GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST);
m_fbo.Bind();
checkForGlError("m_fbo.Blit");
}
m_frame->Flip();
//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
{

View File

@ -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<TransformConstant> m_transform_constants;
Array<TransformConstant> m_fragment_constants;
ArrayF<PostDrawObj> 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);

View File

@ -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);
OPENGL_PROC(PFNGLBLITFRAMEBUFFERPROC, BlitFramebuffer);
OPENGL_PROC(PFNGLDRAWBUFFERSPROC, DrawBuffers);

View File

@ -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:

View File

@ -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;

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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));
}

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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();

View File

@ -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;
}
}
*/

View File

@ -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; //?

View File

@ -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<PPCThread>& threads = GetCPU().GetThreads();
ArrayF<CPUThread>& 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)
{

View File

@ -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<u64> m_break_points;
Array<u64> 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<vfsStream>(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; }

View File

@ -24,7 +24,7 @@ struct EventPort
u64 data2;
u64 data3;
bool has_data;
PPCThread* thread;
CPUThread* thread;
EventQueue* queue[127];
int pos;
};

View File

@ -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();

View File

@ -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)

View File

@ -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();

View File

@ -8,8 +8,8 @@
class InterpreterDisAsmFrame : public wxPanel
{
wxListView* m_list;
PPC_DisAsm* disasm;
PPC_Decoder* decoder;
PPCDisAsm* disasm;
PPCDecoder* decoder;
u64 PC;
Array<u32> remove_markedPC;
wxTextCtrl* m_regs;

View File

@ -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();

View File

@ -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<LoaderBase> 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))

View File

@ -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();

View File

@ -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);

View File

@ -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)

View File

@ -104,11 +104,13 @@
<Optimization>Disabled</Optimization>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<PrecompiledHeader>Use</PrecompiledHeader>
<BufferSecurityCheck>true</BufferSecurityCheck>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>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)</AdditionalDependencies>
<IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
<DataExecutionPrevention>false</DataExecutionPrevention>
</Link>
<PreBuildEvent>
<Command>
@ -126,6 +128,7 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>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)</AdditionalDependencies>
<IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
<DataExecutionPrevention>false</DataExecutionPrevention>
</Link>
<PreBuildEvent>
<Command>$(SolutionDir)\Utilities\git-version-gen.cmd</Command>
@ -156,6 +159,7 @@
<IgnoreAllDefaultLibraries>
</IgnoreAllDefaultLibraries>
<IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
<DataExecutionPrevention>false</DataExecutionPrevention>
</Link>
<PreBuildEvent>
<Command>
@ -187,6 +191,7 @@
<IgnoreAllDefaultLibraries>
</IgnoreAllDefaultLibraries>
<IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
<DataExecutionPrevention>false</DataExecutionPrevention>
</Link>
<PreBuildEvent>
<Command>
@ -196,13 +201,15 @@
<ItemGroup>
<ClCompile Include="..\Utilities\Thread.cpp" />
<ClCompile Include="AppConnector.cpp" />
<ClCompile Include="Emu\ARM9\ARM9Thread.cpp" />
<ClCompile Include="Emu\Cell\MFC.cpp" />
<ClCompile Include="Emu\Cell\PPCThread.cpp" />
<ClCompile Include="Emu\Cell\PPCThreadManager.cpp" />
<ClCompile Include="Emu\Cell\PPUProgramCompiler.cpp" />
<ClCompile Include="Emu\Cell\PPUThread.cpp" />
<ClCompile Include="Emu\Cell\RawSPUThread.cpp" />
<ClCompile Include="Emu\Cell\SPUThread.cpp" />
<ClCompile Include="Emu\CPU\CPUThread.cpp" />
<ClCompile Include="Emu\CPU\CPUThreadManager.cpp" />
<ClCompile Include="Emu\DbgConsole.cpp" />
<ClCompile Include="Emu\FS\VFS.cpp" />
<ClCompile Include="Emu\FS\vfsDevice.cpp" />

View File

@ -17,9 +17,6 @@
<UniqueIdentifier>{adfec460-d940-4482-9fdb-18cb0814c3d5}</UniqueIdentifier>
<ParseFiles>true</ParseFiles>
</Filter>
<Filter Include="Emu\CPU">
<UniqueIdentifier>{f66e37f9-5e58-443b-bcff-2e9e002ac89e}</UniqueIdentifier>
</Filter>
<Filter Include="Loader">
<UniqueIdentifier>{6c36f15e-07fd-45d6-a81c-1ab43ee1b58b}</UniqueIdentifier>
</Filter>
@ -47,6 +44,15 @@
<Filter Include="Emu\HDD">
<UniqueIdentifier>{718bc358-b7ef-4988-8547-2148d14bb08b}</UniqueIdentifier>
</Filter>
<Filter Include="Emu\Cell">
<UniqueIdentifier>{f66e37f9-5e58-443b-bcff-2e9e002ac89e}</UniqueIdentifier>
</Filter>
<Filter Include="Emu\CPU">
<UniqueIdentifier>{041a844e-9f8b-4b4b-a4c5-6c72ecbde475}</UniqueIdentifier>
</Filter>
<Filter Include="Emu\ARM9">
<UniqueIdentifier>{bee6a4b4-6371-4c1b-8558-fc7888b1574e}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="rpcs3.cpp">
@ -116,13 +122,10 @@
<Filter>Loader</Filter>
</ClCompile>
<ClCompile Include="Emu\Cell\PPCThread.cpp">
<Filter>Emu\CPU</Filter>
</ClCompile>
<ClCompile Include="Emu\Cell\PPCThreadManager.cpp">
<Filter>Emu\CPU</Filter>
<Filter>Emu\Cell</Filter>
</ClCompile>
<ClCompile Include="Emu\Cell\SPUThread.cpp">
<Filter>Emu\CPU</Filter>
<Filter>Emu\Cell</Filter>
</ClCompile>
<ClCompile Include="Emu\SysCalls\FuncList.cpp">
<Filter>Emu\SysCalls</Filter>
@ -188,7 +191,7 @@
<Filter>Emu\GS</Filter>
</ClCompile>
<ClCompile Include="Emu\Cell\PPUThread.cpp">
<Filter>Emu\CPU</Filter>
<Filter>Emu\Cell</Filter>
</ClCompile>
<ClCompile Include="Emu\SysCalls\lv2\SC_Time.cpp">
<Filter>Emu\SysCalls\lv2</Filter>
@ -251,7 +254,7 @@
<Filter>rpcs3</Filter>
</ClCompile>
<ClCompile Include="Emu\Cell\PPUProgramCompiler.cpp">
<Filter>Emu\CPU</Filter>
<Filter>Emu\Cell</Filter>
</ClCompile>
<ClCompile Include="Emu\SysCalls\lv2\SC_Event.cpp">
<Filter>Emu\SysCalls\lv2</Filter>
@ -263,10 +266,10 @@
<Filter>Emu\SysCalls\Modules</Filter>
</ClCompile>
<ClCompile Include="Emu\Cell\RawSPUThread.cpp">
<Filter>Emu\CPU</Filter>
<Filter>Emu\Cell</Filter>
</ClCompile>
<ClCompile Include="Emu\Cell\MFC.cpp">
<Filter>Emu\CPU</Filter>
<Filter>Emu\Cell</Filter>
</ClCompile>
<ClCompile Include="Emu\HDD\HDD.cpp">
<Filter>Emu\HDD</Filter>
@ -310,6 +313,15 @@
<ClCompile Include="Emu\FS\vfsFile.cpp">
<Filter>Emu\FS</Filter>
</ClCompile>
<ClCompile Include="Emu\CPU\CPUThread.cpp">
<Filter>Emu\CPU</Filter>
</ClCompile>
<ClCompile Include="Emu\CPU\CPUThreadManager.cpp">
<Filter>Emu\CPU</Filter>
</ClCompile>
<ClCompile Include="Emu\ARM9\ARM9Thread.cpp">
<Filter>Emu\ARM9</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="rpcs3.rc" />