mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-25 12:12:50 +01:00
- Improved PPCDecoder.
- Improved PPUDecoder. - Improved Debugger GUI. CompilerELF: - Added all PPU instructions. - Fixed analyzer crash.
This commit is contained in:
parent
8ba26db020
commit
b35dfdf29b
@ -1,342 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
class Decoder
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
class instr_caller
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual ~instr_caller()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void operator ()() = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
instr_caller* m_instr_decoder;
|
|
||||||
|
|
||||||
template<typename TO>
|
|
||||||
class instr_binder_0 : public instr_caller
|
|
||||||
{
|
|
||||||
typedef void (TO::*func_t)();
|
|
||||||
TO* m_op;
|
|
||||||
func_t m_func;
|
|
||||||
|
|
||||||
public:
|
|
||||||
instr_binder_0(TO* op, func_t func)
|
|
||||||
: instr_caller()
|
|
||||||
, m_op(op)
|
|
||||||
, m_func(func)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void operator ()()
|
|
||||||
{
|
|
||||||
(m_op->*m_func)();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename TO, typename TD, typename T1>
|
|
||||||
class instr_binder_1 : public instr_caller
|
|
||||||
{
|
|
||||||
typedef void (TO::*func_t)(T1);
|
|
||||||
typedef T1 (TD::*arg_1_t)();
|
|
||||||
TO* m_op;
|
|
||||||
TD* m_dec;
|
|
||||||
func_t m_func;
|
|
||||||
arg_1_t m_arg_func_1;
|
|
||||||
|
|
||||||
public:
|
|
||||||
instr_binder_1(TO* op, TD* dec, func_t func, arg_1_t arg_func_1)
|
|
||||||
: instr_caller()
|
|
||||||
, m_op(op)
|
|
||||||
, m_dec(dec)
|
|
||||||
, m_func(func)
|
|
||||||
, m_arg_func_1(arg_func_1)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void operator ()()
|
|
||||||
{
|
|
||||||
(m_op->*m_func)((m_dec->*m_arg_func_1)());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename TO, typename TD, typename T1, typename T2>
|
|
||||||
class instr_binder_2 : public instr_caller
|
|
||||||
{
|
|
||||||
typedef void (TO::*func_t)(T1, T2);
|
|
||||||
typedef T1 (TD::*arg_1_t)();
|
|
||||||
typedef T2 (TD::*arg_2_t)();
|
|
||||||
TO* m_op;
|
|
||||||
TD* m_dec;
|
|
||||||
func_t m_func;
|
|
||||||
arg_1_t m_arg_func_1;
|
|
||||||
arg_2_t m_arg_func_2;
|
|
||||||
|
|
||||||
public:
|
|
||||||
instr_binder_2(TO* op, TD* dec, func_t func, arg_1_t arg_func_1, arg_2_t arg_func_2)
|
|
||||||
: instr_caller()
|
|
||||||
, m_op(op)
|
|
||||||
, m_dec(dec)
|
|
||||||
, m_func(func)
|
|
||||||
, m_arg_func_1(arg_func_1)
|
|
||||||
, m_arg_func_2(arg_func_2)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void operator ()()
|
|
||||||
{
|
|
||||||
(m_op->*m_func)(
|
|
||||||
(m_dec->*m_arg_func_1)(),
|
|
||||||
(m_dec->*m_arg_func_2)()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename TO, typename TD, typename T1, typename T2, typename T3>
|
|
||||||
class instr_binder_3 : public instr_caller
|
|
||||||
{
|
|
||||||
typedef void (TO::*func_t)(T1, T2, T3);
|
|
||||||
typedef T1 (TD::*arg_1_t)();
|
|
||||||
typedef T2 (TD::*arg_2_t)();
|
|
||||||
typedef T3 (TD::*arg_3_t)();
|
|
||||||
TO* m_op;
|
|
||||||
TD* m_dec;
|
|
||||||
func_t m_func;
|
|
||||||
arg_1_t m_arg_func_1;
|
|
||||||
arg_2_t m_arg_func_2;
|
|
||||||
arg_3_t m_arg_func_3;
|
|
||||||
|
|
||||||
public:
|
|
||||||
instr_binder_3(TO* op, TD* dec, func_t func,
|
|
||||||
arg_1_t arg_func_1,
|
|
||||||
arg_2_t arg_func_2,
|
|
||||||
arg_3_t arg_func_3)
|
|
||||||
: instr_caller()
|
|
||||||
, m_op(op)
|
|
||||||
, m_dec(dec)
|
|
||||||
, 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 ()()
|
|
||||||
{
|
|
||||||
(m_op->*m_func)(
|
|
||||||
(m_dec->*m_arg_func_1)(),
|
|
||||||
(m_dec->*m_arg_func_2)(),
|
|
||||||
(m_dec->*m_arg_func_3)()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename TO, typename TD, typename T1, typename T2, typename T3, typename T4>
|
|
||||||
class instr_binder_4 : public instr_caller
|
|
||||||
{
|
|
||||||
typedef void (TO::*func_t)(T1, T2, T3, T4);
|
|
||||||
typedef T1 (TD::*arg_1_t)();
|
|
||||||
typedef T2 (TD::*arg_2_t)();
|
|
||||||
typedef T3 (TD::*arg_3_t)();
|
|
||||||
typedef T4 (TD::*arg_4_t)();
|
|
||||||
TO* m_op;
|
|
||||||
TD* m_dec;
|
|
||||||
func_t m_func;
|
|
||||||
arg_1_t m_arg_func_1;
|
|
||||||
arg_2_t m_arg_func_2;
|
|
||||||
arg_3_t m_arg_func_3;
|
|
||||||
arg_4_t m_arg_func_4;
|
|
||||||
|
|
||||||
public:
|
|
||||||
instr_binder_4(TO* op, TD* dec, func_t func,
|
|
||||||
arg_1_t arg_func_1,
|
|
||||||
arg_2_t arg_func_2,
|
|
||||||
arg_3_t arg_func_3,
|
|
||||||
arg_4_t arg_func_4)
|
|
||||||
: instr_caller()
|
|
||||||
, m_op(op)
|
|
||||||
, m_dec(dec)
|
|
||||||
, 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 ()()
|
|
||||||
{
|
|
||||||
(m_op->*m_func)(
|
|
||||||
(m_dec->*m_arg_func_1)(),
|
|
||||||
(m_dec->*m_arg_func_2)(),
|
|
||||||
(m_dec->*m_arg_func_3)(),
|
|
||||||
(m_dec->*m_arg_func_4)()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename TO, typename TD, typename T1, typename T2, typename T3, typename T4, typename T5>
|
|
||||||
class instr_binder_5 : public instr_caller
|
|
||||||
{
|
|
||||||
typedef void (TO::*func_t)(T1, T2, T3, T4, T5);
|
|
||||||
typedef T1 (TD::*arg_1_t)();
|
|
||||||
typedef T2 (TD::*arg_2_t)();
|
|
||||||
typedef T3 (TD::*arg_3_t)();
|
|
||||||
typedef T4 (TD::*arg_4_t)();
|
|
||||||
typedef T5 (TD::*arg_5_t)();
|
|
||||||
TO* m_op;
|
|
||||||
TD* m_dec;
|
|
||||||
func_t m_func;
|
|
||||||
arg_1_t m_arg_func_1;
|
|
||||||
arg_2_t m_arg_func_2;
|
|
||||||
arg_3_t m_arg_func_3;
|
|
||||||
arg_4_t m_arg_func_4;
|
|
||||||
arg_5_t m_arg_func_5;
|
|
||||||
|
|
||||||
public:
|
|
||||||
instr_binder_5(TO* op, TD* dec, func_t func,
|
|
||||||
arg_1_t arg_func_1,
|
|
||||||
arg_2_t arg_func_2,
|
|
||||||
arg_3_t arg_func_3,
|
|
||||||
arg_4_t arg_func_4,
|
|
||||||
arg_5_t arg_func_5)
|
|
||||||
: instr_caller()
|
|
||||||
, m_op(op)
|
|
||||||
, m_dec(dec)
|
|
||||||
, 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 ()()
|
|
||||||
{
|
|
||||||
(m_op->*m_func)(
|
|
||||||
(m_dec->*m_arg_func_1)(),
|
|
||||||
(m_dec->*m_arg_func_2)(),
|
|
||||||
(m_dec->*m_arg_func_3)(),
|
|
||||||
(m_dec->*m_arg_func_4)(),
|
|
||||||
(m_dec->*m_arg_func_5)()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename TO, typename TD, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
|
|
||||||
class instr_binder_6 : public instr_caller
|
|
||||||
{
|
|
||||||
typedef void (TO::*func_t)(T1, T2, T3, T4, T5, T6);
|
|
||||||
typedef T1 (TD::*arg_1_t)();
|
|
||||||
typedef T2 (TD::*arg_2_t)();
|
|
||||||
typedef T3 (TD::*arg_3_t)();
|
|
||||||
typedef T4 (TD::*arg_4_t)();
|
|
||||||
typedef T5 (TD::*arg_5_t)();
|
|
||||||
typedef T6 (TD::*arg_6_t)();
|
|
||||||
TO* m_op;
|
|
||||||
TD* m_dec;
|
|
||||||
func_t m_func;
|
|
||||||
arg_1_t m_arg_func_1;
|
|
||||||
arg_2_t m_arg_func_2;
|
|
||||||
arg_3_t m_arg_func_3;
|
|
||||||
arg_4_t m_arg_func_4;
|
|
||||||
arg_5_t m_arg_func_5;
|
|
||||||
arg_6_t m_arg_func_6;
|
|
||||||
|
|
||||||
public:
|
|
||||||
instr_binder_6(TO* op, TD* dec, func_t func,
|
|
||||||
arg_1_t arg_func_1,
|
|
||||||
arg_2_t arg_func_2,
|
|
||||||
arg_3_t arg_func_3,
|
|
||||||
arg_4_t arg_func_4,
|
|
||||||
arg_5_t arg_func_5,
|
|
||||||
arg_6_t arg_func_6)
|
|
||||||
: instr_caller()
|
|
||||||
, m_op(op)
|
|
||||||
, m_dec(dec)
|
|
||||||
, 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 ()()
|
|
||||||
{
|
|
||||||
(m_op->*m_func)(
|
|
||||||
(m_dec->*m_arg_func_1)(),
|
|
||||||
(m_dec->*m_arg_func_2)(),
|
|
||||||
(m_dec->*m_arg_func_3)(),
|
|
||||||
(m_dec->*m_arg_func_4)(),
|
|
||||||
(m_dec->*m_arg_func_5)(),
|
|
||||||
(m_dec->*m_arg_func_6)()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<int count, typename TD, typename T>
|
|
||||||
class instr_list : public instr_caller
|
|
||||||
{
|
|
||||||
typedef T (TD::*func_t)();
|
|
||||||
|
|
||||||
TD* m_parent;
|
|
||||||
func_t m_func;
|
|
||||||
instr_caller* m_instrs[count];
|
|
||||||
instr_caller* m_error_func;
|
|
||||||
|
|
||||||
public:
|
|
||||||
instr_list(TD* parent, func_t func, instr_caller* error_func)
|
|
||||||
: instr_caller()
|
|
||||||
, m_parent(parent)
|
|
||||||
, m_func(func)
|
|
||||||
, m_error_func(error_func)
|
|
||||||
{
|
|
||||||
memset(m_instrs, 0, sizeof(instr_caller*) * count);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~instr_list()
|
|
||||||
{
|
|
||||||
for(int i=0; i<count; ++i)
|
|
||||||
{
|
|
||||||
delete m_instrs[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
delete m_error_func;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_instr(uint pos, instr_caller* func)
|
|
||||||
{
|
|
||||||
assert(pos < count);
|
|
||||||
m_instrs[pos] = func;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void operator ()()
|
|
||||||
{
|
|
||||||
instr_caller* instr = m_instrs[(m_parent->*m_func)() & (count - 1)];
|
|
||||||
|
|
||||||
if(instr)
|
|
||||||
{
|
|
||||||
(*instr)();
|
|
||||||
}
|
|
||||||
else if(m_error_func)
|
|
||||||
{
|
|
||||||
(*m_error_func)();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<int count, typename TD, typename T>
|
|
||||||
instr_list<count, TD, T>* new_list(TD* parent, T (TD::*func)(), instr_caller* error_func)
|
|
||||||
{
|
|
||||||
return new instr_list<count, TD, T>(parent, func, error_func);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
virtual void Decode(const u32 code)=0;
|
|
||||||
};
|
|
899
rpcs3/Emu/Cell/PPCDecoder.h
Normal file
899
rpcs3/Emu/Cell/PPCDecoder.h
Normal file
@ -0,0 +1,899 @@
|
|||||||
|
#pragma once
|
||||||
|
#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
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
u32 m_code;
|
||||||
|
|
||||||
|
public:
|
||||||
|
u32 GetCode() const { return m_code; }
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
memset(m_instrs, 0, sizeof(InstrCaller<TO>*) * count);
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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
|
||||||
|
{
|
||||||
|
InstrCaller<TO>* instr = m_instrs[entry];
|
||||||
|
|
||||||
|
if(instr)
|
||||||
|
{
|
||||||
|
(*instr)(op, code);
|
||||||
|
}
|
||||||
|
else if(m_error_func)
|
||||||
|
{
|
||||||
|
(*m_error_func)(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<int count, typename TO>
|
||||||
|
static InstrList<count, TO>* new_list(const CodeFieldBase& func, InstrCaller<TO>* error_func = nullptr)
|
||||||
|
{
|
||||||
|
return new InstrList<count, TO>(func, error_func);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<int count1, int count2, typename TO>
|
||||||
|
static InstrList<count1, TO>* new_list(InstrList<count2, TO>* parent, int opcode, const CodeFieldBase& func, InstrCaller<TO>* error_func = nullptr)
|
||||||
|
{
|
||||||
|
return connect_list(parent, new InstrList<count1, TO>(func, error_func), opcode);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<int count1, int count2, typename TO>
|
||||||
|
static InstrList<count1, TO>* new_list(InstrList<count2, TO>* parent, const CodeFieldBase& func, InstrCaller<TO>* error_func = nullptr)
|
||||||
|
{
|
||||||
|
return connect_list(parent, new InstrList<count1, 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);
|
||||||
|
}
|
@ -11,7 +11,7 @@ enum DisAsmModes
|
|||||||
CompilerElfMode,
|
CompilerElfMode,
|
||||||
};
|
};
|
||||||
|
|
||||||
class DisAsm
|
class PPC_DisAsm
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
DisAsmFrame* disasm_frame;
|
DisAsmFrame* disasm_frame;
|
||||||
@ -58,7 +58,7 @@ public:
|
|||||||
uint dump_pc;
|
uint dump_pc;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
DisAsm(PPCThread& cpu, DisAsmModes mode = NormalMode)
|
PPC_DisAsm(PPCThread& cpu, DisAsmModes mode = NormalMode)
|
||||||
: m_mode(mode)
|
: m_mode(mode)
|
||||||
, disasm_frame(NULL)
|
, disasm_frame(NULL)
|
||||||
{
|
{
|
135
rpcs3/Emu/Cell/PPCInstrTable.h
Normal file
135
rpcs3/Emu/Cell/PPCInstrTable.h
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
template<int size, typename T> __forceinline static T sign(const T value)
|
||||||
|
{
|
||||||
|
if(value & (1 << (size - 1)))
|
||||||
|
{
|
||||||
|
return value - (1 << size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum CodeFieldType
|
||||||
|
{
|
||||||
|
FIELD_IMM,
|
||||||
|
FIELD_R_GPR,
|
||||||
|
FIELD_R_FPR,
|
||||||
|
FIELD_R_VPR,
|
||||||
|
FIELD_R_CR,
|
||||||
|
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
|
||||||
|
{
|
||||||
|
static_assert(from <= to, "too big 'from' value");
|
||||||
|
static_assert(to <= 31, "too big 'to' value");
|
||||||
|
|
||||||
|
public:
|
||||||
|
CodeField(CodeFieldType type = FIELD_IMM) : CodeFieldBase(type)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static const u32 shift = 31 - to;
|
||||||
|
static const u32 mask = ((1ULL << ((to - from) + 1)) - 1) << shift;
|
||||||
|
|
||||||
|
static __forceinline void encode(u32& data, u32 value)
|
||||||
|
{
|
||||||
|
data &= ~mask;
|
||||||
|
data |= (value << shift) & mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __forceinline u32 decode(u32 data)
|
||||||
|
{
|
||||||
|
return (data & mask) >> shift;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual u32 operator ()(u32 data) const
|
||||||
|
{
|
||||||
|
return decode(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void operator()(u32& data, u32 value) const
|
||||||
|
{
|
||||||
|
encode(data, value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<uint from1, uint to1, uint from2, uint to2 = from2, uint offset = 0>
|
||||||
|
class DoubleCodeField : public CodeField<from1, to1>
|
||||||
|
{
|
||||||
|
static_assert(from2 <= to2, "too big from2 value");
|
||||||
|
static_assert(to2 <= 31, "too big to2 value");
|
||||||
|
|
||||||
|
public:
|
||||||
|
DoubleCodeField(CodeFieldType type = FIELD_IMM) : CodeField(type)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static const u32 shift2 = 31 - to2;
|
||||||
|
static const u32 mask2 = ((1 << ((to2 - from2) + 1)) - 1) << shift2;
|
||||||
|
|
||||||
|
static __forceinline void encode(u32& data, u32 value)
|
||||||
|
{
|
||||||
|
data &= ~(mask | mask2);
|
||||||
|
data |= ((value << shift) & mask) | (((value >> offset) << shift2) & mask2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static __forceinline u32 decode(u32 data)
|
||||||
|
{
|
||||||
|
return ((data & mask) >> shift) | (((data & mask2) >> shift2) << offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual u32 operator ()(u32 data) const
|
||||||
|
{
|
||||||
|
return decode(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void operator()(u32& data, u32 value) const
|
||||||
|
{
|
||||||
|
encode(data, value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<uint from, uint to = from, uint _size = to - from + 1>
|
||||||
|
class CodeFieldSigned : public CodeField<from, to>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CodeFieldSigned(CodeFieldType type = FIELD_IMM) : CodeField(type)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static const int size = _size;
|
||||||
|
|
||||||
|
static __forceinline u32 decode(u32 data)
|
||||||
|
{
|
||||||
|
return sign<size>((data & mask) >> shift);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual u32 operator ()(u32 data) const
|
||||||
|
{
|
||||||
|
return decode(data);
|
||||||
|
}
|
||||||
|
};
|
@ -168,6 +168,8 @@ void PPCThread::Run()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wxGetApp().SendDbgCommand(DID_START_THREAD, this);
|
||||||
|
|
||||||
m_status = Runned;
|
m_status = Runned;
|
||||||
|
|
||||||
SetPc(entry);
|
SetPc(entry);
|
||||||
@ -176,49 +178,52 @@ void PPCThread::Run()
|
|||||||
DoRun();
|
DoRun();
|
||||||
Emu.CheckStatus();
|
Emu.CheckStatus();
|
||||||
|
|
||||||
wxGetApp().SendDbgCommand(DID_START_THREAD, this);
|
wxGetApp().SendDbgCommand(DID_STARTED_THREAD, this);
|
||||||
|
|
||||||
if(DisAsmFrame) (*(InterpreterDisAsmFrame*)DisAsmFrame).DoUpdate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PPCThread::Resume()
|
void PPCThread::Resume()
|
||||||
{
|
{
|
||||||
if(!IsPaused()) return;
|
if(!IsPaused()) return;
|
||||||
|
|
||||||
|
wxGetApp().SendDbgCommand(DID_RESUME_THREAD, this);
|
||||||
|
|
||||||
m_status = Runned;
|
m_status = Runned;
|
||||||
DoResume();
|
DoResume();
|
||||||
Emu.CheckStatus();
|
Emu.CheckStatus();
|
||||||
|
|
||||||
wxGetApp().SendDbgCommand(DID_RESUME_THREAD, this);
|
|
||||||
|
|
||||||
ThreadBase::Start();
|
ThreadBase::Start();
|
||||||
|
|
||||||
|
wxGetApp().SendDbgCommand(DID_RESUMED_THREAD, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PPCThread::Pause()
|
void PPCThread::Pause()
|
||||||
{
|
{
|
||||||
if(!IsRunned()) return;
|
if(!IsRunned()) return;
|
||||||
|
|
||||||
|
wxGetApp().SendDbgCommand(DID_PAUSE_THREAD, this);
|
||||||
|
|
||||||
m_status = Paused;
|
m_status = Paused;
|
||||||
DoPause();
|
DoPause();
|
||||||
Emu.CheckStatus();
|
Emu.CheckStatus();
|
||||||
|
|
||||||
wxGetApp().SendDbgCommand(DID_PAUSE_THREAD, this);
|
|
||||||
|
|
||||||
ThreadBase::Stop(false);
|
ThreadBase::Stop(false);
|
||||||
|
wxGetApp().SendDbgCommand(DID_PAUSED_THREAD, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PPCThread::Stop()
|
void PPCThread::Stop()
|
||||||
{
|
{
|
||||||
if(IsStopped()) return;
|
if(IsStopped()) return;
|
||||||
|
|
||||||
|
wxGetApp().SendDbgCommand(DID_STOP_THREAD, this);
|
||||||
|
|
||||||
m_status = Stopped;
|
m_status = Stopped;
|
||||||
Reset();
|
Reset();
|
||||||
DoStop();
|
DoStop();
|
||||||
Emu.CheckStatus();
|
Emu.CheckStatus();
|
||||||
|
|
||||||
wxGetApp().SendDbgCommand(DID_STOP_THREAD, this);
|
|
||||||
|
|
||||||
ThreadBase::Stop();
|
ThreadBase::Stop();
|
||||||
|
|
||||||
|
wxGetApp().SendDbgCommand(DID_STOPED_THREAD, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PPCThread::Exec()
|
void PPCThread::Exec()
|
||||||
@ -237,8 +242,19 @@ void PPCThread::Task()
|
|||||||
{
|
{
|
||||||
ConLog.Write("%s enter", PPCThread::GetFName());
|
ConLog.Write("%s enter", PPCThread::GetFName());
|
||||||
|
|
||||||
|
const Array<u64>& bp = Emu.GetBreakPoints();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
for(uint i=0; i<bp.GetCount(); ++i)
|
||||||
|
{
|
||||||
|
if(bp[i] == m_offset + PC)
|
||||||
|
{
|
||||||
|
Emu.Pause();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
while(!Emu.IsStopped() && !TestDestroy())
|
while(!Emu.IsStopped() && !TestDestroy())
|
||||||
{
|
{
|
||||||
if(Emu.IsPaused())
|
if(Emu.IsPaused())
|
||||||
@ -249,6 +265,15 @@ void PPCThread::Task()
|
|||||||
|
|
||||||
DoCode(Memory.Read32(m_offset + PC));
|
DoCode(Memory.Read32(m_offset + PC));
|
||||||
NextPc();
|
NextPc();
|
||||||
|
|
||||||
|
for(uint i=0; i<bp.GetCount(); ++i)
|
||||||
|
{
|
||||||
|
if(bp[i] == m_offset + PC)
|
||||||
|
{
|
||||||
|
Emu.Pause();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(const wxString& e)
|
catch(const wxString& e)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Emu/Memory/MemoryBlock.h"
|
#include "Emu/Memory/MemoryBlock.h"
|
||||||
#include "Emu/Cell/Decoder.h"
|
#include "Emu/Cell/PPCDecoder.h"
|
||||||
|
|
||||||
enum PPCThreadType
|
enum PPCThreadType
|
||||||
{
|
{
|
||||||
@ -13,7 +13,7 @@ class PPCThread : public ThreadBase
|
|||||||
protected:
|
protected:
|
||||||
u32 m_status;
|
u32 m_status;
|
||||||
u32 m_error;
|
u32 m_error;
|
||||||
Decoder* m_dec;
|
PPC_Decoder* m_dec;
|
||||||
wxWindow* DisAsmFrame;
|
wxWindow* DisAsmFrame;
|
||||||
u32 m_id;
|
u32 m_id;
|
||||||
PPCThreadType m_type;
|
PPCThreadType m_type;
|
||||||
|
@ -1,763 +1,26 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Emu/Cell/PPUOpcodes.h"
|
#include "Emu/Cell/PPUOpcodes.h"
|
||||||
#include "Emu/Cell/Decoder.h"
|
#include "Emu/Cell/PPCDecoder.h"
|
||||||
|
#include "PPUInstrTable.h"
|
||||||
|
|
||||||
|
class PPU_Decoder : public PPC_Decoder
|
||||||
#define START_OPCODES_GROUP(group, reg) \
|
|
||||||
case(##group##): \
|
|
||||||
temp=##reg##;\
|
|
||||||
switch(temp)\
|
|
||||||
{
|
|
||||||
|
|
||||||
#define START_OPCODES_SUB_GROUP(reg) \
|
|
||||||
default:\
|
|
||||||
temp=##reg##;\
|
|
||||||
switch(temp)\
|
|
||||||
{
|
|
||||||
|
|
||||||
#define END_OPCODES_GROUP(group) \
|
|
||||||
default:\
|
|
||||||
m_op.UNK(m_code, opcode, temp);\
|
|
||||||
break;\
|
|
||||||
}\
|
|
||||||
break
|
|
||||||
|
|
||||||
#define END_OPCODES_SUB_GROUP() \
|
|
||||||
default:\
|
|
||||||
m_op.UNK(m_code, opcode, temp);\
|
|
||||||
break;\
|
|
||||||
}
|
|
||||||
#define END_OPCODES_ND_GROUP(group) \
|
|
||||||
} \
|
|
||||||
break;
|
|
||||||
|
|
||||||
#define ADD_OPCODE(name, ...) case(##name##):m_op.##name##(__VA_ARGS__); break
|
|
||||||
|
|
||||||
class PPU_Decoder : public Decoder
|
|
||||||
{
|
{
|
||||||
u32 m_code;
|
PPU_Opcodes* m_op;
|
||||||
PPU_Opcodes& m_op;
|
|
||||||
|
|
||||||
//This field is used in rotate instructions to specify the first 1 bit of a 64-bit mask
|
|
||||||
OP_REG mb() { return GetField(21, 25) | (m_code & 0x20); }
|
|
||||||
|
|
||||||
//This field is used in rotate instructions to specify the last 1 bit of a 64-bit mask
|
|
||||||
OP_REG me() { return GetField(21, 25) | (m_code & 0x20); }
|
|
||||||
|
|
||||||
//This field is used to specify a shift amount
|
|
||||||
OP_REG sh() { return GetField(16, 20) | ((m_code & 0x2) << 4); }
|
|
||||||
|
|
||||||
//This field is used to specify a special-purpose register for the mtspr and mfspr instructions
|
|
||||||
OP_REG SPR() { return GetField(11, 20); }
|
|
||||||
|
|
||||||
//
|
|
||||||
OP_REG VS() { return GetField(6, 10); }
|
|
||||||
|
|
||||||
//
|
|
||||||
OP_REG VD() { return GetField(6, 10); }
|
|
||||||
|
|
||||||
//
|
|
||||||
OP_REG VA() { return GetField(11, 15); }
|
|
||||||
|
|
||||||
//
|
|
||||||
OP_REG VB() { return GetField(16, 20); }
|
|
||||||
|
|
||||||
//
|
|
||||||
OP_REG VC() { return GetField(21, 25); }
|
|
||||||
|
|
||||||
//
|
|
||||||
OP_uIMM VUIMM() { return GetField(11, 15); }
|
|
||||||
|
|
||||||
//
|
|
||||||
OP_sIMM VSIMM() { int i5 = GetField(11, 15);
|
|
||||||
if(i5 & 0x10) return i5 - 0x20;
|
|
||||||
return i5; }
|
|
||||||
|
|
||||||
//
|
|
||||||
OP_uIMM VSH() { return GetField(22, 25); }
|
|
||||||
|
|
||||||
//This field is used to specify a GPR to be used as a destination
|
|
||||||
OP_REG RD() { return GetField(6, 10); }
|
|
||||||
|
|
||||||
//This field is used to specify a GPR to be used as a source
|
|
||||||
OP_REG RS() { return GetField(6, 10); }
|
|
||||||
|
|
||||||
//This field is used to specify a GPR to be used as a source or destination
|
|
||||||
OP_REG RA() { return GetField(11, 15); }
|
|
||||||
|
|
||||||
//This field is used to specify a GPR to be used as a source
|
|
||||||
OP_REG RB() { return GetField(16, 20); }
|
|
||||||
|
|
||||||
//This field is used to specify the number of bytes to move in an immediate string load or store
|
|
||||||
OP_REG NB() { return GetField(16, 20); }
|
|
||||||
|
|
||||||
//This field is used to specify one of the CR fields, or one of the FPSCR fields, as a destination
|
|
||||||
OP_REG CRFD() { return GetField(6, 8); }
|
|
||||||
|
|
||||||
//This field is used to specify one of the CR fields, or one of the FPSCR fields, as a source
|
|
||||||
OP_REG CRFS() { return GetField(11, 13); }
|
|
||||||
|
|
||||||
//This field is used to specify a bit in the CR to be used as a source
|
|
||||||
OP_REG CRBA() { return GetField(11, 15); }
|
|
||||||
|
|
||||||
//This field is used to specify a bit in the CR to be used as a source
|
|
||||||
OP_REG CRBB() { return GetField(16, 20); }
|
|
||||||
|
|
||||||
//This field is used to specify a bit in the CR, or in the FPSCR, as the destination of the result of an instruction
|
|
||||||
OP_REG CRBD() { return GetField(6, 10); }
|
|
||||||
|
|
||||||
//
|
|
||||||
OP_REG BT() { return GetField(6, 10); }
|
|
||||||
|
|
||||||
//
|
|
||||||
OP_REG BA() { return GetField(11, 15); }
|
|
||||||
|
|
||||||
//
|
|
||||||
OP_REG BB() { return GetField(16, 20); }
|
|
||||||
|
|
||||||
//
|
|
||||||
OP_REG BF() { return GetField(6, 10); }
|
|
||||||
|
|
||||||
//This field is used to specify options for the branch conditional instructions
|
|
||||||
OP_REG BO() { return GetField(6, 10); }
|
|
||||||
|
|
||||||
//This field is used to specify a bit in the CR to be used as the condition of a branch conditional instruction
|
|
||||||
OP_REG BI() { return GetField(11, 15); }
|
|
||||||
|
|
||||||
//Immediate field specifying a 14-bit signed two's complement branch displacement that is concatenated on the
|
|
||||||
//right with ‘00’ and sign-extended to 64 bits.
|
|
||||||
OP_sIMM BD() { return (s32)(s16)GetField(16, 31); }
|
|
||||||
|
|
||||||
//
|
|
||||||
OP_REG BH() { return GetField(19, 20); }
|
|
||||||
|
|
||||||
//
|
|
||||||
OP_REG BFA() { return GetField(11, 13); }
|
|
||||||
|
|
||||||
//Field used by the optional data stream variant of the dcbt instruction.
|
|
||||||
OP_uIMM TH() { return GetField(9, 10); }
|
|
||||||
|
|
||||||
//This field is used to specify the conditions on which to trap
|
|
||||||
OP_uIMM TO() { return GetField(6, 10); }
|
|
||||||
|
|
||||||
//
|
|
||||||
OP_REG MB() { return GetField(21, 25); }
|
|
||||||
|
|
||||||
//
|
|
||||||
OP_REG ME() { return GetField(26, 30); }
|
|
||||||
|
|
||||||
//This field is used to specify a shift amount
|
|
||||||
OP_REG SH() { return GetField(16, 20); }
|
|
||||||
|
|
||||||
/*
|
|
||||||
Absolute address bit.
|
|
||||||
0 The immediate field represents an address relative to the current instruction address (CIA). (For more
|
|
||||||
information on the CIA, see Table 8-3.) The effective (logical) address of the branch is either the sum
|
|
||||||
of the LI field sign-extended to 64 bits and the address of the branch instruction or the sum of the BD
|
|
||||||
field sign-extended to 64 bits and the address of the branch instruction.
|
|
||||||
1 The immediate field represents an absolute address. The effective address (EA) of the branch is the
|
|
||||||
LI field sign-extended to 64 bits or the BD field sign-extended to 64 bits.
|
|
||||||
*/
|
|
||||||
OP_REG AA() { return GetField(30); }
|
|
||||||
|
|
||||||
//
|
|
||||||
OP_sIMM LL()
|
|
||||||
{
|
|
||||||
OP_sIMM ll = m_code & 0x03fffffc;
|
|
||||||
if (ll & 0x02000000) return ll - 0x04000000;
|
|
||||||
return ll;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
Link bit.
|
|
||||||
0 Does not update the link register (LR).
|
|
||||||
1 Updates the LR. If the instruction is a branch instruction, the address of the instruction following the
|
|
||||||
branch instruction is placed into the LR.
|
|
||||||
*/
|
|
||||||
OP_REG LK() { return GetField(31); }
|
|
||||||
|
|
||||||
//This field is used for extended arithmetic to enable setting OV and SO in the XER
|
|
||||||
OP_REG OE() { return GetField(21); }
|
|
||||||
|
|
||||||
//Field used to specify whether an integer compare instruction is to compare 64-bit numbers or 32-bit numbers
|
|
||||||
OP_REG L_10() { return GetField(10); }
|
|
||||||
OP_REG L_6() { return GetField(6); }
|
|
||||||
OP_REG L_9_10() { return GetField(9, 10); }
|
|
||||||
OP_REG L_11() { return GetField(11); }
|
|
||||||
//
|
|
||||||
OP_REG I() { return GetField(16, 19); }
|
|
||||||
|
|
||||||
//
|
|
||||||
OP_REG DQ() { return GetField(16, 27); }
|
|
||||||
|
|
||||||
//This field is used to specify an FPR as the destination
|
|
||||||
OP_REG FRD() { return GetField(6, 10); }
|
|
||||||
|
|
||||||
//This field is used to specify an FPR as a source
|
|
||||||
OP_REG FRS() { return GetField(6, 10); }
|
|
||||||
|
|
||||||
//
|
|
||||||
OP_REG FLM() { return GetField(7, 14); }
|
|
||||||
|
|
||||||
//This field is used to specify an FPR as a source
|
|
||||||
OP_REG FRA() { return GetField(11, 15); }
|
|
||||||
|
|
||||||
//This field is used to specify an FPR as a source
|
|
||||||
OP_REG FRB() { return GetField(16, 20); }
|
|
||||||
|
|
||||||
//This field is used to specify an FPR as a source
|
|
||||||
OP_REG FRC() { return GetField(21, 25); }
|
|
||||||
|
|
||||||
//This field mask is used to identify the CR fields that are to be updated by the mtcrf instruction.
|
|
||||||
OP_REG CRM() { return GetField(12, 19); }
|
|
||||||
|
|
||||||
//
|
|
||||||
OP_sIMM SYS() { return GetField(6, 31); }
|
|
||||||
|
|
||||||
//Immediate field specifying a 16-bit signed two's complement integer that is sign-extended to 64 bits
|
|
||||||
OP_sIMM D() { return (s32)(s16)GetField(16, 31); }
|
|
||||||
|
|
||||||
//
|
|
||||||
OP_sIMM DS()
|
|
||||||
{
|
|
||||||
OP_sIMM d = D();
|
|
||||||
if(d < 0) return d - 1;
|
|
||||||
return d;
|
|
||||||
}
|
|
||||||
|
|
||||||
//This immediate field is used to specify a 16-bit signed integer
|
|
||||||
OP_sIMM simm16() { return (s32)(s16)m_code; }
|
|
||||||
|
|
||||||
//This immediate field is used to specify a 16-bit unsigned integer
|
|
||||||
OP_uIMM uimm16() { return (u32)(u16)m_code; }
|
|
||||||
|
|
||||||
/*
|
|
||||||
Record bit.
|
|
||||||
0 Does not update the condition register (CR).
|
|
||||||
1 Updates the CR to reflect the result of the operation.
|
|
||||||
For integer instructions, CR bits [0–2] are set to reflect the result as a signed quantity and CR bit [3]
|
|
||||||
receives a copy of the summary overflow bit, XER[SO]. The result as an unsigned quantity or a bit
|
|
||||||
string can be deduced from the EQ bit. For floating-point instructions, CR bits [4–7] are set to reflect
|
|
||||||
floating-point exception, floating-point enabled exception, floating-point invalid operation exception,
|
|
||||||
and floating-point overflow exception.
|
|
||||||
*/
|
|
||||||
bool RC() { return m_code & 0x1; }
|
|
||||||
|
|
||||||
//Primary opcode field
|
|
||||||
OP_uIMM OPCD() { return GetField(0, 5); }
|
|
||||||
|
|
||||||
OP_uIMM GD_04() { return GetField(26, 31); } //0x3f
|
|
||||||
OP_uIMM GD_04_0() { return GetField(21, 31); } //0x7ff
|
|
||||||
OP_uIMM GD_13() { return GetField(21, 30); } //0x3ff
|
|
||||||
OP_uIMM GD_1e() { return GetField(28, 29); } //0x3
|
|
||||||
OP_uIMM GD_1f() { return GetField(21, 30); } //0x3ff
|
|
||||||
OP_uIMM GD_3a() { return GetField(30, 31); } //0x3
|
|
||||||
OP_uIMM GD_3b() { return GetField(26, 30); } //0x1f
|
|
||||||
OP_uIMM GD_3e() { return GetField(30, 31); } //0x3
|
|
||||||
OP_uIMM GD_3f() { return GetField(26, 30); } //0x1f
|
|
||||||
OP_uIMM GD_3f_0() { return GetField(21, 30); } //0x3ff
|
|
||||||
|
|
||||||
OP_uIMM STRM() { return GetField(9, 10); }
|
|
||||||
|
|
||||||
OP_uIMM GetCode() { return m_code; }
|
|
||||||
|
|
||||||
__forceinline u32 GetField(const u32 p)
|
|
||||||
{
|
|
||||||
return (m_code >> (31 - p)) & 0x1;
|
|
||||||
}
|
|
||||||
|
|
||||||
__forceinline u32 GetField(const u32 from, const u32 to)
|
|
||||||
{
|
|
||||||
return (m_code >> (31 - to)) & ((1 << ((to - from) + 1)) - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template<typename TD, typename TO>
|
PPU_Decoder(PPU_Opcodes& op) : m_op(&op)
|
||||||
instr_caller* instr_bind(TD* parent, void (TO::*func)())
|
|
||||||
{
|
{
|
||||||
return new instr_binder_0<TO>(parent, func);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename TO>
|
|
||||||
instr_caller* instr_bind(void (TO::*func)())
|
|
||||||
{
|
|
||||||
return instr_bind(&m_op, func);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename TO, typename TD, typename T1>
|
|
||||||
instr_caller* instr_bind(void (TO::*func)(T1), T1 (TD::*arg_func_1)())
|
|
||||||
{
|
|
||||||
return new instr_binder_1<TO, TD, T1>(&m_op, this, func, arg_func_1);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename TO, typename TD, typename T1, typename T2>
|
|
||||||
instr_caller* instr_bind(void (TO::*func)(T1, T2), T1 (TD::*arg_func_1)(), T2 (TD::*arg_func_2)())
|
|
||||||
{
|
|
||||||
return new instr_binder_2<TO, TD, T1, T2>(&m_op, this, func, arg_func_1, arg_func_2);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename TO, typename TD, typename T1, typename T2, typename T3>
|
|
||||||
instr_caller* instr_bind(void (TO::*func)(T1, T2, T3), T1 (TD::*arg_func_1)(), T2 (TD::*arg_func_2)(), T3 (TD::*arg_func_3)())
|
|
||||||
{
|
|
||||||
return new instr_binder_3<TO, TD, T1, T2, T3>(&m_op, this, func, arg_func_1, arg_func_2, arg_func_3);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename TO, typename TD, typename T1, typename T2, typename T3, typename T4>
|
|
||||||
instr_caller* instr_bind(void (TO::*func)(T1, T2, T3, T4), T1 (TD::*arg_func_1)(), T2 (TD::*arg_func_2)(), T3 (TD::*arg_func_3)(), T4 (TD::*arg_func_4)())
|
|
||||||
{
|
|
||||||
return new instr_binder_4<TO, TD, T1, T2, T3, T4>(&m_op, this, func, arg_func_1, arg_func_2, arg_func_3, arg_func_4);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename TO, typename TD, typename T1, typename T2, typename T3, typename T4, typename T5>
|
|
||||||
instr_caller* instr_bind(void (TO::*func)(T1, T2, T3, T4, T5), T1 (TD::*arg_func_1)(), T2 (TD::*arg_func_2)(), T3 (TD::*arg_func_3)(), T4 (TD::*arg_func_4)(), T5 (TD::*arg_func_5)())
|
|
||||||
{
|
|
||||||
return new instr_binder_5<TO, TD, T1, T2, T3, T4, T5>(&m_op, this, func, arg_func_1, arg_func_2, arg_func_3, arg_func_4, arg_func_5);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename TO, typename TD, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
|
|
||||||
instr_caller* instr_bind(void (TO::*func)(T1, T2, T3, T4, T5, T6), T1 (TD::*arg_func_1)(), T2 (TD::*arg_func_2)(), T3 (TD::*arg_func_3)(), T4 (TD::*arg_func_4)(), T5 (TD::*arg_func_5)(), T6 (TD::*arg_func_6)())
|
|
||||||
{
|
|
||||||
return new instr_binder_6<TO, TD, T1, T2, T3, T4, T5, T6>(&m_op, this, func, arg_func_1, arg_func_2, arg_func_3, arg_func_4, arg_func_5, arg_func_6);
|
|
||||||
}
|
|
||||||
|
|
||||||
void UNK_MAIN()
|
|
||||||
{
|
|
||||||
if(!m_code)
|
|
||||||
{
|
|
||||||
m_op.NULL_OP();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
u32 opcd = OPCD();
|
|
||||||
m_op.UNK(m_code, opcd, opcd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PPU_Decoder(PPU_Opcodes& op) : m_op(op)
|
|
||||||
{
|
|
||||||
#define bind_instr(list, instr, ...) list->set_instr(instr, instr_bind(&PPU_Opcodes::##instr, ##__VA_ARGS__))
|
|
||||||
|
|
||||||
using namespace PPU_opcodes;
|
|
||||||
auto main_list = new_list<0x40>(this, &PPU_Decoder::OPCD, instr_bind(this, &PPU_Decoder::UNK_MAIN));
|
|
||||||
auto g04_0_list = new_list<0x800>(this, &PPU_Decoder::GD_04_0, instr_bind(&PPU_Opcodes::UNK, &PPU_Decoder::GetCode, &PPU_Decoder::OPCD, &PPU_Decoder::GD_04_0));
|
|
||||||
auto g04_list = new_list<0x40>(this, &PPU_Decoder::GD_04, g04_0_list);
|
|
||||||
auto g13_list = new_list<0x400>(this, &PPU_Decoder::GD_13, instr_bind(&PPU_Opcodes::UNK, &PPU_Decoder::GetCode, &PPU_Decoder::OPCD, &PPU_Decoder::GD_13));
|
|
||||||
auto g1e_list = new_list<0x4>(this, &PPU_Decoder::GD_1e, instr_bind(&PPU_Opcodes::UNK, &PPU_Decoder::GetCode, &PPU_Decoder::OPCD, &PPU_Decoder::GD_1e));
|
|
||||||
auto g1f_list = new_list<0x400>(this, &PPU_Decoder::GD_1f, instr_bind(&PPU_Opcodes::UNK, &PPU_Decoder::GetCode, &PPU_Decoder::OPCD, &PPU_Decoder::GD_1f));
|
|
||||||
auto g3a_list = new_list<0x4>(this, &PPU_Decoder::GD_3a, instr_bind(&PPU_Opcodes::UNK, &PPU_Decoder::GetCode, &PPU_Decoder::OPCD, &PPU_Decoder::GD_3a));
|
|
||||||
auto g3b_list = new_list<0x20>(this, &PPU_Decoder::GD_3b, instr_bind(&PPU_Opcodes::UNK, &PPU_Decoder::GetCode, &PPU_Decoder::OPCD, &PPU_Decoder::GD_3b));
|
|
||||||
auto g3e_list = new_list<0x4>(this, &PPU_Decoder::GD_3e, instr_bind(&PPU_Opcodes::UNK, &PPU_Decoder::GetCode, &PPU_Decoder::OPCD, &PPU_Decoder::GD_3e));
|
|
||||||
auto g3f_0_list = new_list<0x400>(this, &PPU_Decoder::GD_3f_0, instr_bind(&PPU_Opcodes::UNK, &PPU_Decoder::GetCode, &PPU_Decoder::OPCD, &PPU_Decoder::GD_3f_0));
|
|
||||||
auto g3f_list = new_list<0x20>(this, &PPU_Decoder::GD_3f, g3f_0_list);
|
|
||||||
|
|
||||||
bind_instr(main_list, TDI, &PPU_Decoder::TO, &PPU_Decoder::RA, &PPU_Decoder::simm16);
|
|
||||||
bind_instr(main_list, TWI, &PPU_Decoder::TO, &PPU_Decoder::RA, &PPU_Decoder::simm16);
|
|
||||||
main_list->set_instr(G_04, g04_list);
|
|
||||||
bind_instr(main_list, MULLI, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::simm16);
|
|
||||||
bind_instr(main_list, SUBFIC, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::simm16);
|
|
||||||
bind_instr(main_list, CMPLI, &PPU_Decoder::CRFD, &PPU_Decoder::L_10, &PPU_Decoder::RA, &PPU_Decoder::uimm16);
|
|
||||||
bind_instr(main_list, CMPI, &PPU_Decoder::CRFD, &PPU_Decoder::L_10, &PPU_Decoder::RA, &PPU_Decoder::simm16);
|
|
||||||
bind_instr(main_list, ADDIC, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::simm16);
|
|
||||||
bind_instr(main_list, ADDIC_, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::simm16);
|
|
||||||
bind_instr(main_list, ADDI, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::simm16);
|
|
||||||
bind_instr(main_list, ADDIS, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::simm16);
|
|
||||||
bind_instr(main_list, BC, &PPU_Decoder::BO, &PPU_Decoder::BI, &PPU_Decoder::BD, &PPU_Decoder::AA, &PPU_Decoder::LK);
|
|
||||||
bind_instr(main_list, SC, &PPU_Decoder::SYS);
|
|
||||||
bind_instr(main_list, B, &PPU_Decoder::LL, &PPU_Decoder::AA, &PPU_Decoder::LK);
|
|
||||||
main_list->set_instr(G_13, g13_list);
|
|
||||||
bind_instr(main_list, RLWIMI, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::SH, &PPU_Decoder::MB, &PPU_Decoder::ME, &PPU_Decoder::RC);
|
|
||||||
bind_instr(main_list, RLWINM, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::SH, &PPU_Decoder::MB, &PPU_Decoder::ME, &PPU_Decoder::RC);
|
|
||||||
bind_instr(main_list, RLWNM, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::RB, &PPU_Decoder::MB, &PPU_Decoder::ME, &PPU_Decoder::RC);
|
|
||||||
bind_instr(main_list, ORI, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::uimm16);
|
|
||||||
bind_instr(main_list, ORIS, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::uimm16);
|
|
||||||
bind_instr(main_list, XORI, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::uimm16);
|
|
||||||
bind_instr(main_list, XORIS, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::uimm16);
|
|
||||||
bind_instr(main_list, ANDI_, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::uimm16);
|
|
||||||
bind_instr(main_list, ANDIS_, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::uimm16);
|
|
||||||
main_list->set_instr(G_1e, g1e_list);
|
|
||||||
main_list->set_instr(G_1f, g1f_list);
|
|
||||||
bind_instr(main_list, LWZ, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::D);
|
|
||||||
bind_instr(main_list, LWZU, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::D);
|
|
||||||
bind_instr(main_list, LBZ, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::D);
|
|
||||||
bind_instr(main_list, LBZU, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::D);
|
|
||||||
bind_instr(main_list, STW, &PPU_Decoder::RS, &PPU_Decoder::RA, &PPU_Decoder::D);
|
|
||||||
bind_instr(main_list, STWU, &PPU_Decoder::RS, &PPU_Decoder::RA, &PPU_Decoder::D);
|
|
||||||
bind_instr(main_list, STB, &PPU_Decoder::RS, &PPU_Decoder::RA, &PPU_Decoder::D);
|
|
||||||
bind_instr(main_list, STBU, &PPU_Decoder::RS, &PPU_Decoder::RA, &PPU_Decoder::D);
|
|
||||||
bind_instr(main_list, LHZ, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::D);
|
|
||||||
bind_instr(main_list, LHZU, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::D);
|
|
||||||
bind_instr(main_list, STH, &PPU_Decoder::RS, &PPU_Decoder::RA, &PPU_Decoder::D);
|
|
||||||
bind_instr(main_list, STHU, &PPU_Decoder::RS, &PPU_Decoder::RA, &PPU_Decoder::D);
|
|
||||||
bind_instr(main_list, LMW, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::D);
|
|
||||||
bind_instr(main_list, STMW, &PPU_Decoder::RS, &PPU_Decoder::RA, &PPU_Decoder::D);
|
|
||||||
bind_instr(main_list, LFS, &PPU_Decoder::FRD, &PPU_Decoder::RA, &PPU_Decoder::D);
|
|
||||||
bind_instr(main_list, LFSU, &PPU_Decoder::FRD, &PPU_Decoder::RA, &PPU_Decoder::D);
|
|
||||||
bind_instr(main_list, LFD, &PPU_Decoder::FRD, &PPU_Decoder::RA, &PPU_Decoder::D);
|
|
||||||
bind_instr(main_list, LFDU, &PPU_Decoder::FRD, &PPU_Decoder::RA, &PPU_Decoder::D);
|
|
||||||
bind_instr(main_list, STFS, &PPU_Decoder::FRS, &PPU_Decoder::RA, &PPU_Decoder::D);
|
|
||||||
bind_instr(main_list, STFSU, &PPU_Decoder::FRS, &PPU_Decoder::RA, &PPU_Decoder::D);
|
|
||||||
bind_instr(main_list, STFD, &PPU_Decoder::FRS, &PPU_Decoder::RA, &PPU_Decoder::D);
|
|
||||||
bind_instr(main_list, STFDU, &PPU_Decoder::FRS, &PPU_Decoder::RA, &PPU_Decoder::D);
|
|
||||||
main_list->set_instr(G_3a, g3a_list);
|
|
||||||
main_list->set_instr(G_3b, g3b_list);
|
|
||||||
main_list->set_instr(G_3e, g3e_list);
|
|
||||||
main_list->set_instr(G_3f, g3f_list);
|
|
||||||
|
|
||||||
bind_instr(g04_list, VMADDFP, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB, &PPU_Decoder::VC);
|
|
||||||
bind_instr(g04_list, VMHADDSHS, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB, &PPU_Decoder::VC);
|
|
||||||
bind_instr(g04_list, VMHRADDSHS, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB, &PPU_Decoder::VC);
|
|
||||||
bind_instr(g04_list, VMLADDUHM, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB, &PPU_Decoder::VC);
|
|
||||||
bind_instr(g04_list, VMSUMMBM, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB, &PPU_Decoder::VC);
|
|
||||||
bind_instr(g04_list, VMSUMSHM, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB, &PPU_Decoder::VC);
|
|
||||||
bind_instr(g04_list, VMSUMSHS, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB, &PPU_Decoder::VC);
|
|
||||||
bind_instr(g04_list, VMSUMUBM, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB, &PPU_Decoder::VC);
|
|
||||||
bind_instr(g04_list, VMSUMUHM, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB, &PPU_Decoder::VC);
|
|
||||||
bind_instr(g04_list, VMSUMUHS, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB, &PPU_Decoder::VC);
|
|
||||||
bind_instr(g04_list, VNMSUBFP, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB, &PPU_Decoder::VC);
|
|
||||||
bind_instr(g04_list, VPERM, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB, &PPU_Decoder::VC);
|
|
||||||
bind_instr(g04_list, VSEL, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB, &PPU_Decoder::VC);
|
|
||||||
bind_instr(g04_list, VSLDOI, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB, &PPU_Decoder::VSH);
|
|
||||||
|
|
||||||
bind_instr(g04_0_list, MFVSCR, &PPU_Decoder::VD);
|
|
||||||
bind_instr(g04_0_list, MTVSCR, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VADDCUW, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VADDFP, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VADDSBS, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VADDSHS, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VADDSWS, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VADDUBM, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VADDUBS, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VADDUHM, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VADDUHS, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VADDUWM, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VADDUWS, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VAND, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VANDC, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VAVGSB, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VAVGSH, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VAVGSW, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VAVGUB, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VAVGUH, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VAVGUW, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VCFSX, &PPU_Decoder::VD, &PPU_Decoder::VUIMM, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VCFUX, &PPU_Decoder::VD, &PPU_Decoder::VUIMM, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VCMPBFP, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VCMPBFP_, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VCMPEQFP, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VCMPEQFP_, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VCMPEQUB, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VCMPEQUB_, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VCMPEQUH, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VCMPEQUH_, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VCMPEQUW, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VCMPEQUW_, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VCMPGEFP, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VCMPGEFP_, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VCMPGTFP, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VCMPGTFP_, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VCMPGTSB, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VCMPGTSB_, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VCMPGTSH, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VCMPGTSH_, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VCMPGTSW, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VCMPGTSW_, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VCMPGTUB, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VCMPGTUB_, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VCMPGTUH, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VCMPGTUH_, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VCMPGTUW, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VCMPGTUW_, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VCTSXS, &PPU_Decoder::VD, &PPU_Decoder::VUIMM, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VCTUXS, &PPU_Decoder::VD, &PPU_Decoder::VUIMM, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VEXPTEFP, &PPU_Decoder::VD, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VLOGEFP, &PPU_Decoder::VD, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VMAXFP, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VMAXSB, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VMAXSH, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VMAXSW, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VMAXUB, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VMAXUH, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VMAXUW, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VMINFP, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VMINSB, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VMINSH, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VMINSW, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VMINUB, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VMINUH, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VMINUW, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VMRGHB, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VMRGHH, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VMRGHW, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VMRGLB, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VMRGLH, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VMRGLW, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VMULESB, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VMULESH, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VMULEUB, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VMULEUH, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VMULOSB, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VMULOSH, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VMULOUB, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VMULOUH, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VNOR, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VOR, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VPKPX, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VPKSHSS, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VPKSHUS, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VPKSWSS, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VPKSWUS, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VPKUHUM, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VPKUHUS, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VPKUWUM, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VPKUWUS, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VREFP, &PPU_Decoder::VD, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VRFIM, &PPU_Decoder::VD, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VRFIN, &PPU_Decoder::VD, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VRFIP, &PPU_Decoder::VD, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VRFIZ, &PPU_Decoder::VD, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VRLB, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VRLH, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VRLW, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VRSQRTEFP, &PPU_Decoder::VD, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VSL, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VSLB, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VSLH, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VSLO, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VSLW, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VSPLTB, &PPU_Decoder::VD, &PPU_Decoder::VUIMM, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VSPLTH, &PPU_Decoder::VD, &PPU_Decoder::VUIMM, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VSPLTISB, &PPU_Decoder::VD, &PPU_Decoder::VSIMM);
|
|
||||||
bind_instr(g04_0_list, VSPLTISH, &PPU_Decoder::VD, &PPU_Decoder::VSIMM);
|
|
||||||
bind_instr(g04_0_list, VSPLTISW, &PPU_Decoder::VD, &PPU_Decoder::VSIMM);
|
|
||||||
bind_instr(g04_0_list, VSPLTW, &PPU_Decoder::VD, &PPU_Decoder::VUIMM, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VSR, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VSRAB, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VSRAH, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VSRAW, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VSRB, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VSRH, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VSRO, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VSRW, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VSUBCUW, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VSUBFP, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VSUBSBS, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VSUBSHS, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VSUBSWS, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VSUBUBM, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VSUBUBS, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VSUBUHM, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VSUBUHS, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VSUBUWM, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VSUBUWS, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VSUMSWS, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VSUM2SWS, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VSUM4SBS, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VSUM4SHS, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VSUM4UBS, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VUPKHPX, &PPU_Decoder::VD, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VUPKHSB, &PPU_Decoder::VD, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VUPKHSH, &PPU_Decoder::VD, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VUPKLPX, &PPU_Decoder::VD, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VUPKLSB, &PPU_Decoder::VD, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VUPKLSH, &PPU_Decoder::VD, &PPU_Decoder::VB);
|
|
||||||
bind_instr(g04_0_list, VXOR, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB);
|
|
||||||
|
|
||||||
bind_instr(g13_list, MCRF, &PPU_Decoder::CRFD, &PPU_Decoder::CRFS);
|
|
||||||
bind_instr(g13_list, BCLR, &PPU_Decoder::BO, &PPU_Decoder::BI, &PPU_Decoder::BH, &PPU_Decoder::LK);
|
|
||||||
bind_instr(g13_list, CRNOR, &PPU_Decoder::CRBD, &PPU_Decoder::CRBA, &PPU_Decoder::CRBB);
|
|
||||||
bind_instr(g13_list, CRANDC, &PPU_Decoder::CRBD, &PPU_Decoder::CRBA, &PPU_Decoder::CRBB);
|
|
||||||
bind_instr(g13_list, ISYNC);
|
|
||||||
bind_instr(g13_list, CRXOR, &PPU_Decoder::CRBD, &PPU_Decoder::CRBA, &PPU_Decoder::CRBB);
|
|
||||||
bind_instr(g13_list, CRNAND, &PPU_Decoder::CRBD, &PPU_Decoder::CRBA, &PPU_Decoder::CRBB);
|
|
||||||
bind_instr(g13_list, CRAND, &PPU_Decoder::CRBD, &PPU_Decoder::CRBA, &PPU_Decoder::CRBB);
|
|
||||||
bind_instr(g13_list, CREQV, &PPU_Decoder::CRBD, &PPU_Decoder::CRBA, &PPU_Decoder::CRBB);
|
|
||||||
bind_instr(g13_list, CRORC, &PPU_Decoder::CRBD, &PPU_Decoder::CRBA, &PPU_Decoder::CRBB);
|
|
||||||
bind_instr(g13_list, CROR, &PPU_Decoder::CRBD, &PPU_Decoder::CRBA, &PPU_Decoder::CRBB);
|
|
||||||
bind_instr(g13_list, BCCTR, &PPU_Decoder::BO, &PPU_Decoder::BI, &PPU_Decoder::BH, &PPU_Decoder::LK);
|
|
||||||
|
|
||||||
bind_instr(g1e_list, RLDICL, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::sh, &PPU_Decoder::mb, &PPU_Decoder::RC);
|
|
||||||
bind_instr(g1e_list, RLDICR, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::sh, &PPU_Decoder::me, &PPU_Decoder::RC);
|
|
||||||
bind_instr(g1e_list, RLDIC, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::sh, &PPU_Decoder::mb, &PPU_Decoder::RC);
|
|
||||||
bind_instr(g1e_list, RLDIMI, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::sh, &PPU_Decoder::mb, &PPU_Decoder::RC);
|
|
||||||
|
|
||||||
/*0x000*/bind_instr(g1f_list, CMP, &PPU_Decoder::CRFD, &PPU_Decoder::L_10, &PPU_Decoder::RA, &PPU_Decoder::RB);
|
|
||||||
/*0x004*/bind_instr(g1f_list, TW, &PPU_Decoder::TO, &PPU_Decoder::RA, &PPU_Decoder::RB);
|
|
||||||
/*0x006*/bind_instr(g1f_list, LVSL, &PPU_Decoder::VD, &PPU_Decoder::RA, &PPU_Decoder::RB);
|
|
||||||
/*0x007*/bind_instr(g1f_list, LVEBX, &PPU_Decoder::VD, &PPU_Decoder::RA, &PPU_Decoder::RB);
|
|
||||||
/*0x008*/bind_instr(g1f_list, SUBFC, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB, &PPU_Decoder::OE, &PPU_Decoder::RC);
|
|
||||||
/*0x009*/bind_instr(g1f_list, MULHDU, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB, &PPU_Decoder::RC);
|
|
||||||
/*0x00a*/bind_instr(g1f_list, ADDC, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB, &PPU_Decoder::OE, &PPU_Decoder::RC);
|
|
||||||
/*0x00b*/bind_instr(g1f_list, MULHWU, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB, &PPU_Decoder::RC);
|
|
||||||
/*0x013*/bind_instr(g1f_list, MFOCRF, &PPU_Decoder::L_11, &PPU_Decoder::RD, &PPU_Decoder::CRM);
|
|
||||||
/*0x014*/bind_instr(g1f_list, LWARX, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB);
|
|
||||||
/*0x015*/bind_instr(g1f_list, LDX, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::RB);
|
|
||||||
/*0x017*/bind_instr(g1f_list, LWZX, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB);
|
|
||||||
/*0x018*/bind_instr(g1f_list, SLW, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::RB, &PPU_Decoder::RC);
|
|
||||||
/*0x01a*/bind_instr(g1f_list, CNTLZW, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::RC);
|
|
||||||
/*0x01b*/bind_instr(g1f_list, SLD, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::RB, &PPU_Decoder::RC);
|
|
||||||
/*0x01c*/bind_instr(g1f_list, AND, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::RB, &PPU_Decoder::RC);
|
|
||||||
/*0x020*/bind_instr(g1f_list, CMPL, &PPU_Decoder::CRFD, &PPU_Decoder::L_10, &PPU_Decoder::RA, &PPU_Decoder::RB);
|
|
||||||
/*0x026*/bind_instr(g1f_list, LVSR, &PPU_Decoder::VD, &PPU_Decoder::RA, &PPU_Decoder::RB);
|
|
||||||
/*0x027*/bind_instr(g1f_list, LVEHX, &PPU_Decoder::VD, &PPU_Decoder::RA, &PPU_Decoder::RB);
|
|
||||||
/*0x028*/bind_instr(g1f_list, SUBF, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB, &PPU_Decoder::OE, &PPU_Decoder::RC);
|
|
||||||
/*0x036*/bind_instr(g1f_list, DCBST, &PPU_Decoder::RA, &PPU_Decoder::RB);
|
|
||||||
/*0x03a*/bind_instr(g1f_list, CNTLZD, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::RC);
|
|
||||||
/*0x03c*/bind_instr(g1f_list, ANDC, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::RB, &PPU_Decoder::RC);
|
|
||||||
/*0x047*/bind_instr(g1f_list, LVEWX, &PPU_Decoder::VD, &PPU_Decoder::RA, &PPU_Decoder::RB);
|
|
||||||
/*0x049*/bind_instr(g1f_list, MULHD, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB, &PPU_Decoder::RC);
|
|
||||||
/*0x04b*/bind_instr(g1f_list, MULHW, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB, &PPU_Decoder::RC);
|
|
||||||
/*0x054*/bind_instr(g1f_list, LDARX, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB);
|
|
||||||
/*0x056*/bind_instr(g1f_list, DCBF, &PPU_Decoder::RA, &PPU_Decoder::RB);
|
|
||||||
/*0x057*/bind_instr(g1f_list, LBZX, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB);
|
|
||||||
/*0x067*/bind_instr(g1f_list, LVX, &PPU_Decoder::VD, &PPU_Decoder::RA, &PPU_Decoder::RB);
|
|
||||||
/*0x068*/bind_instr(g1f_list, NEG, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::OE, &PPU_Decoder::RC);
|
|
||||||
/*0x077*/bind_instr(g1f_list, LBZUX, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB);
|
|
||||||
/*0x07c*/bind_instr(g1f_list, NOR, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::RB, &PPU_Decoder::RC);
|
|
||||||
/*0x087*/bind_instr(g1f_list, STVEBX, &PPU_Decoder::VS, &PPU_Decoder::RA, &PPU_Decoder::RB);
|
|
||||||
/*0x088*/bind_instr(g1f_list, SUBFE, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB, &PPU_Decoder::OE, &PPU_Decoder::RC);
|
|
||||||
/*0x08a*/bind_instr(g1f_list, ADDE, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB, &PPU_Decoder::OE, &PPU_Decoder::RC);
|
|
||||||
/*0x090*/bind_instr(g1f_list, MTOCRF, &PPU_Decoder::CRM, &PPU_Decoder::RS);
|
|
||||||
/*0x095*/bind_instr(g1f_list, STDX, &PPU_Decoder::RS, &PPU_Decoder::RA, &PPU_Decoder::RB);
|
|
||||||
/*0x096*/bind_instr(g1f_list, STWCX_, &PPU_Decoder::RS, &PPU_Decoder::RA, &PPU_Decoder::RB);
|
|
||||||
/*0x097*/bind_instr(g1f_list, STWX, &PPU_Decoder::RS, &PPU_Decoder::RA, &PPU_Decoder::RB);
|
|
||||||
/*0x0a7*/bind_instr(g1f_list, STVEHX, &PPU_Decoder::VS, &PPU_Decoder::RA, &PPU_Decoder::RB);
|
|
||||||
/*0x0b5*/bind_instr(g1f_list, STDUX, &PPU_Decoder::RS, &PPU_Decoder::RA, &PPU_Decoder::RB);
|
|
||||||
/*0x0c7*/bind_instr(g1f_list, STVEWX, &PPU_Decoder::VS, &PPU_Decoder::RA, &PPU_Decoder::RB);
|
|
||||||
/*0x0ca*/bind_instr(g1f_list, ADDZE, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::OE, &PPU_Decoder::RC);
|
|
||||||
/*0x0d6*/bind_instr(g1f_list, STDCX_, &PPU_Decoder::RS, &PPU_Decoder::RA, &PPU_Decoder::RB);
|
|
||||||
/*0x0d7*/bind_instr(g1f_list, STBX, &PPU_Decoder::RS, &PPU_Decoder::RA, &PPU_Decoder::RB);
|
|
||||||
/*0x0e7*/bind_instr(g1f_list, STVX, &PPU_Decoder::VS, &PPU_Decoder::RA, &PPU_Decoder::RB);
|
|
||||||
/*0x0e9*/bind_instr(g1f_list, MULLD, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB, &PPU_Decoder::OE, &PPU_Decoder::RC);
|
|
||||||
/*0x0ea*/bind_instr(g1f_list, ADDME, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::OE, &PPU_Decoder::RC);
|
|
||||||
/*0x0eb*/bind_instr(g1f_list, MULLW, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB, &PPU_Decoder::OE, &PPU_Decoder::RC);
|
|
||||||
/*0x0f6*/bind_instr(g1f_list, DCBTST, &PPU_Decoder::TH, &PPU_Decoder::RA, &PPU_Decoder::RB);
|
|
||||||
/*0x10a*/bind_instr(g1f_list, ADD, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB, &PPU_Decoder::OE, &PPU_Decoder::RC);
|
|
||||||
/*0x116*/bind_instr(g1f_list, DCBT, &PPU_Decoder::RA, &PPU_Decoder::RB, &PPU_Decoder::TH);
|
|
||||||
/*0x117*/bind_instr(g1f_list, LHZX, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB);
|
|
||||||
/*0x11c*/bind_instr(g1f_list, EQV, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::RB, &PPU_Decoder::RC);
|
|
||||||
/*0x136*/bind_instr(g1f_list, ECIWX, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB);
|
|
||||||
/*0x137*/bind_instr(g1f_list, LHZUX, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB);
|
|
||||||
/*0x13c*/bind_instr(g1f_list, XOR, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::RB, &PPU_Decoder::RC);
|
|
||||||
/*0x153*/bind_instr(g1f_list, MFSPR, &PPU_Decoder::RD, &PPU_Decoder::SPR);
|
|
||||||
/*0x156*/bind_instr(g1f_list, DST, &PPU_Decoder::RA, &PPU_Decoder::RB, &PPU_Decoder::STRM, &PPU_Decoder::L_6);
|
|
||||||
/*0x157*/bind_instr(g1f_list, LHAX, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB);
|
|
||||||
/*0x167*/bind_instr(g1f_list, LVXL, &PPU_Decoder::VD, &PPU_Decoder::RA, &PPU_Decoder::RB);
|
|
||||||
/*0x168*/bind_instr(g1f_list, ABS, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::OE, &PPU_Decoder::RC);
|
|
||||||
/*0x173*/bind_instr(g1f_list, MFTB, &PPU_Decoder::RD, &PPU_Decoder::SPR);
|
|
||||||
/*0x176*/bind_instr(g1f_list, DSTST, &PPU_Decoder::RA, &PPU_Decoder::RB, &PPU_Decoder::STRM, &PPU_Decoder::L_6);
|
|
||||||
/*0x177*/bind_instr(g1f_list, LHAUX, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB);
|
|
||||||
/*0x197*/bind_instr(g1f_list, STHX, &PPU_Decoder::RS, &PPU_Decoder::RA, &PPU_Decoder::RB);
|
|
||||||
/*0x19c*/bind_instr(g1f_list, ORC, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::RB, &PPU_Decoder::RC);
|
|
||||||
/*0x1b6*/bind_instr(g1f_list, ECOWX, &PPU_Decoder::RS, &PPU_Decoder::RA, &PPU_Decoder::RB);
|
|
||||||
/*0x1bc*/bind_instr(g1f_list, OR, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::RB, &PPU_Decoder::RC);
|
|
||||||
/*0x1c9*/bind_instr(g1f_list, DIVDU, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB, &PPU_Decoder::OE, &PPU_Decoder::RC);
|
|
||||||
/*0x1cb*/bind_instr(g1f_list, DIVWU, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB, &PPU_Decoder::OE, &PPU_Decoder::RC);
|
|
||||||
/*0x1d3*/bind_instr(g1f_list, MTSPR, &PPU_Decoder::SPR, &PPU_Decoder::RS);
|
|
||||||
/*0x1d6*///DCBI
|
|
||||||
/*0x1dc*/bind_instr(g1f_list, NAND, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::RB, &PPU_Decoder::RC);
|
|
||||||
/*0x1e7*/bind_instr(g1f_list, STVXL, &PPU_Decoder::RS, &PPU_Decoder::RA, &PPU_Decoder::RB);
|
|
||||||
/*0x1e9*/bind_instr(g1f_list, DIVD, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB, &PPU_Decoder::OE, &PPU_Decoder::RC);
|
|
||||||
/*0x1eb*/bind_instr(g1f_list, DIVW, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB, &PPU_Decoder::OE, &PPU_Decoder::RC);
|
|
||||||
/*0x207*/bind_instr(g1f_list, LVLX, &PPU_Decoder::VD, &PPU_Decoder::RA, &PPU_Decoder::RB);
|
|
||||||
/*0x216*/bind_instr(g1f_list, LWBRX, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB);
|
|
||||||
/*0x217*/bind_instr(g1f_list, LFSX, &PPU_Decoder::FRD, &PPU_Decoder::RA, &PPU_Decoder::RB);
|
|
||||||
/*0x218*/bind_instr(g1f_list, SRW, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::RB, &PPU_Decoder::RC);
|
|
||||||
/*0x21b*/bind_instr(g1f_list, SRD, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::RB, &PPU_Decoder::RC);
|
|
||||||
/*0x227*/bind_instr(g1f_list, LVRX, &PPU_Decoder::VD, &PPU_Decoder::RA, &PPU_Decoder::RB);
|
|
||||||
/*0x237*/bind_instr(g1f_list, LFSUX, &PPU_Decoder::FRD, &PPU_Decoder::RA, &PPU_Decoder::RB);
|
|
||||||
/*0x256*/bind_instr(g1f_list, SYNC, &PPU_Decoder::L_9_10);
|
|
||||||
/*0x257*/bind_instr(g1f_list, LFDX, &PPU_Decoder::FRD, &PPU_Decoder::RA, &PPU_Decoder::RB);
|
|
||||||
/*0x277*/bind_instr(g1f_list, LFDUX, &PPU_Decoder::FRD, &PPU_Decoder::RA, &PPU_Decoder::RB);
|
|
||||||
/*0x287*/bind_instr(g1f_list, STVLX, &PPU_Decoder::VS, &PPU_Decoder::RA, &PPU_Decoder::RB);
|
|
||||||
/*0x297*/bind_instr(g1f_list, STFSX, &PPU_Decoder::RS, &PPU_Decoder::RA, &PPU_Decoder::RB);
|
|
||||||
/*0x2a7*/bind_instr(g1f_list, STVRX, &PPU_Decoder::VS, &PPU_Decoder::RA, &PPU_Decoder::RB);
|
|
||||||
/*0x2d7*/bind_instr(g1f_list, STFDX, &PPU_Decoder::RS, &PPU_Decoder::RA, &PPU_Decoder::RB);
|
|
||||||
/*0x307*/bind_instr(g1f_list, LVLXL, &PPU_Decoder::VD, &PPU_Decoder::RA, &PPU_Decoder::RB);
|
|
||||||
/*0x316*/bind_instr(g1f_list, LHBRX, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB);
|
|
||||||
/*0x318*/bind_instr(g1f_list, SRAW, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::RB, &PPU_Decoder::RC);
|
|
||||||
/*0x31a*/bind_instr(g1f_list, SRAD, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::RB, &PPU_Decoder::RC);
|
|
||||||
/*0x327*/bind_instr(g1f_list, LVRXL, &PPU_Decoder::VD, &PPU_Decoder::RA, &PPU_Decoder::RB);
|
|
||||||
/*0x336*/bind_instr(g1f_list, DSS, &PPU_Decoder::STRM, &PPU_Decoder::L_6);
|
|
||||||
/*0x338*/bind_instr(g1f_list, SRAWI, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::sh, &PPU_Decoder::RC);
|
|
||||||
/*0x33a*/bind_instr(g1f_list, SRADI1, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::sh, &PPU_Decoder::RC);
|
|
||||||
/*0x33b*/bind_instr(g1f_list, SRADI2, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::sh, &PPU_Decoder::RC);
|
|
||||||
/*0x356*/bind_instr(g1f_list, EIEIO);
|
|
||||||
/*0x39a*/bind_instr(g1f_list, EXTSH, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::RC);
|
|
||||||
/*0x3ba*/bind_instr(g1f_list, EXTSB, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::RC);
|
|
||||||
/*0x3d7*/bind_instr(g1f_list, STFIWX, &PPU_Decoder::FRS, &PPU_Decoder::RA, &PPU_Decoder::RB);
|
|
||||||
/*0x3da*/bind_instr(g1f_list, EXTSW, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::RC);
|
|
||||||
/*0x3d6*///ICBI
|
|
||||||
/*0x3f6*/bind_instr(g1f_list, DCBZ, &PPU_Decoder::RA, &PPU_Decoder::RB);
|
|
||||||
|
|
||||||
bind_instr(g3a_list, LD, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::D);
|
|
||||||
bind_instr(g3a_list, LDU, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::DS);
|
|
||||||
|
|
||||||
bind_instr(g3b_list, FDIVS, &PPU_Decoder::FRD, &PPU_Decoder::FRA, &PPU_Decoder::FRB, &PPU_Decoder::RC);
|
|
||||||
bind_instr(g3b_list, FSUBS, &PPU_Decoder::FRD, &PPU_Decoder::FRA, &PPU_Decoder::FRB, &PPU_Decoder::RC);
|
|
||||||
bind_instr(g3b_list, FADDS, &PPU_Decoder::FRD, &PPU_Decoder::FRA, &PPU_Decoder::FRB, &PPU_Decoder::RC);
|
|
||||||
bind_instr(g3b_list, FSQRTS, &PPU_Decoder::FRD, &PPU_Decoder::FRB, &PPU_Decoder::RC);
|
|
||||||
bind_instr(g3b_list, FRES, &PPU_Decoder::FRD, &PPU_Decoder::FRB, &PPU_Decoder::RC);
|
|
||||||
bind_instr(g3b_list, FMULS, &PPU_Decoder::FRD, &PPU_Decoder::FRA, &PPU_Decoder::FRC, &PPU_Decoder::RC);
|
|
||||||
bind_instr(g3b_list, FMADDS, &PPU_Decoder::FRD, &PPU_Decoder::FRA, &PPU_Decoder::FRC, &PPU_Decoder::FRB, &PPU_Decoder::RC);
|
|
||||||
bind_instr(g3b_list, FMSUBS, &PPU_Decoder::FRD, &PPU_Decoder::FRA, &PPU_Decoder::FRC, &PPU_Decoder::FRB, &PPU_Decoder::RC);
|
|
||||||
bind_instr(g3b_list, FNMSUBS, &PPU_Decoder::FRD, &PPU_Decoder::FRA, &PPU_Decoder::FRC, &PPU_Decoder::FRB, &PPU_Decoder::RC);
|
|
||||||
bind_instr(g3b_list, FNMADDS, &PPU_Decoder::FRD, &PPU_Decoder::FRA, &PPU_Decoder::FRC, &PPU_Decoder::FRB, &PPU_Decoder::RC);
|
|
||||||
|
|
||||||
bind_instr(g3e_list, STD, &PPU_Decoder::RS, &PPU_Decoder::RA, &PPU_Decoder::D);
|
|
||||||
bind_instr(g3e_list, STDU, &PPU_Decoder::RS, &PPU_Decoder::RA, &PPU_Decoder::DS);
|
|
||||||
|
|
||||||
bind_instr(g3f_list, FSEL, &PPU_Decoder::FRD, &PPU_Decoder::FRA, &PPU_Decoder::FRC, &PPU_Decoder::FRB, &PPU_Decoder::RC);
|
|
||||||
bind_instr(g3f_list, FMUL, &PPU_Decoder::FRD, &PPU_Decoder::FRA, &PPU_Decoder::FRC, &PPU_Decoder::RC);
|
|
||||||
bind_instr(g3f_list, FMSUB, &PPU_Decoder::FRD, &PPU_Decoder::FRA, &PPU_Decoder::FRC, &PPU_Decoder::FRB, &PPU_Decoder::RC);
|
|
||||||
bind_instr(g3f_list, FMADD, &PPU_Decoder::FRD, &PPU_Decoder::FRA, &PPU_Decoder::FRC, &PPU_Decoder::FRB, &PPU_Decoder::RC);
|
|
||||||
bind_instr(g3f_list, FNMSUB, &PPU_Decoder::FRD, &PPU_Decoder::FRA, &PPU_Decoder::FRC, &PPU_Decoder::FRB, &PPU_Decoder::RC);
|
|
||||||
bind_instr(g3f_list, FNMADD, &PPU_Decoder::FRD, &PPU_Decoder::FRA, &PPU_Decoder::FRC, &PPU_Decoder::FRB, &PPU_Decoder::RC);
|
|
||||||
|
|
||||||
bind_instr(g3f_0_list, FDIV, &PPU_Decoder::FRD, &PPU_Decoder::FRA, &PPU_Decoder::FRB, &PPU_Decoder::RC);
|
|
||||||
bind_instr(g3f_0_list, FSUB, &PPU_Decoder::FRD, &PPU_Decoder::FRA, &PPU_Decoder::FRB, &PPU_Decoder::RC);
|
|
||||||
bind_instr(g3f_0_list, FADD, &PPU_Decoder::FRD, &PPU_Decoder::FRA, &PPU_Decoder::FRB, &PPU_Decoder::RC);
|
|
||||||
bind_instr(g3f_0_list, FSQRT, &PPU_Decoder::FRD, &PPU_Decoder::FRB, &PPU_Decoder::RC);
|
|
||||||
bind_instr(g3f_0_list, FRSQRTE, &PPU_Decoder::FRD, &PPU_Decoder::FRB, &PPU_Decoder::RC);
|
|
||||||
bind_instr(g3f_0_list, FCMPU, &PPU_Decoder::CRFD, &PPU_Decoder::FRA, &PPU_Decoder::FRB);
|
|
||||||
bind_instr(g3f_0_list, FRSP, &PPU_Decoder::FRD, &PPU_Decoder::FRB, &PPU_Decoder::RC);
|
|
||||||
bind_instr(g3f_0_list, FCTIW, &PPU_Decoder::FRD, &PPU_Decoder::FRB, &PPU_Decoder::RC);
|
|
||||||
bind_instr(g3f_0_list, FCTIWZ, &PPU_Decoder::FRD, &PPU_Decoder::FRB, &PPU_Decoder::RC);
|
|
||||||
bind_instr(g3f_0_list, FCMPO, &PPU_Decoder::CRFD, &PPU_Decoder::FRA, &PPU_Decoder::FRB);
|
|
||||||
bind_instr(g3f_0_list, FNEG, &PPU_Decoder::FRD, &PPU_Decoder::FRB, &PPU_Decoder::RC);
|
|
||||||
bind_instr(g3f_0_list, FMR, &PPU_Decoder::FRD, &PPU_Decoder::FRB, &PPU_Decoder::RC);
|
|
||||||
bind_instr(g3f_0_list, FNABS, &PPU_Decoder::FRD, &PPU_Decoder::FRB, &PPU_Decoder::RC);
|
|
||||||
bind_instr(g3f_0_list, FABS, &PPU_Decoder::FRD, &PPU_Decoder::FRB, &PPU_Decoder::RC);
|
|
||||||
bind_instr(g3f_0_list, FCFID, &PPU_Decoder::FRD, &PPU_Decoder::FRB, &PPU_Decoder::RC);
|
|
||||||
bind_instr(g3f_0_list, FCTID, &PPU_Decoder::FRD, &PPU_Decoder::FRB, &PPU_Decoder::RC);
|
|
||||||
bind_instr(g3f_0_list, FCTIDZ, &PPU_Decoder::FRD, &PPU_Decoder::FRB, &PPU_Decoder::RC);
|
|
||||||
|
|
||||||
bind_instr(g3f_0_list, MTFSB1, &PPU_Decoder::BT, &PPU_Decoder::RC);
|
|
||||||
bind_instr(g3f_0_list, MCRFS, &PPU_Decoder::BF, &PPU_Decoder::BFA);
|
|
||||||
bind_instr(g3f_0_list, MTFSB0, &PPU_Decoder::BT, &PPU_Decoder::RC);
|
|
||||||
bind_instr(g3f_0_list, MTFSFI, &PPU_Decoder::CRFD, &PPU_Decoder::I, &PPU_Decoder::RC);
|
|
||||||
bind_instr(g3f_0_list, MFFS, &PPU_Decoder::FRD, &PPU_Decoder::RC);
|
|
||||||
bind_instr(g3f_0_list, MTFSF, &PPU_Decoder::FLM, &PPU_Decoder::FRB, &PPU_Decoder::RC);
|
|
||||||
|
|
||||||
m_instr_decoder = main_list;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~PPU_Decoder()
|
~PPU_Decoder()
|
||||||
{
|
{
|
||||||
m_op.Exit();
|
m_op->Exit();
|
||||||
delete m_instr_decoder;
|
delete m_op;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void Decode(const u32 code)
|
virtual void Decode(const u32 code)
|
||||||
{
|
{
|
||||||
m_code = code;
|
(*PPU_instr::main_list)(m_op, code);
|
||||||
(*m_instr_decoder)();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#undef START_OPCODES_GROUP
|
|
||||||
#undef START_OPCODES_SUB_GROUP
|
|
||||||
#undef ADD_OPCODE
|
|
||||||
#undef ADD_NULL_OPCODE
|
|
||||||
#undef END_OPCODES_GROUP
|
|
||||||
#undef END_OPCODES_ND_GROUP
|
|
||||||
#undef END_OPCODES_SUB_GROUP
|
|
@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Emu/Cell/PPUOpcodes.h"
|
#include "Emu/Cell/PPUOpcodes.h"
|
||||||
#include "Emu/Cell/DisAsm.h"
|
#include "Emu/Cell/PPCDisAsm.h"
|
||||||
#include "Emu/Cell/PPCThread.h"
|
#include "Emu/Cell/PPCThread.h"
|
||||||
#include "Gui/DisAsmFrame.h"
|
#include "Gui/DisAsmFrame.h"
|
||||||
#include "Emu/Memory/Memory.h"
|
#include "Emu/Memory/Memory.h"
|
||||||
@ -11,19 +11,19 @@
|
|||||||
|
|
||||||
class PPU_DisAsm
|
class PPU_DisAsm
|
||||||
: public PPU_Opcodes
|
: public PPU_Opcodes
|
||||||
, public DisAsm
|
, public PPC_DisAsm
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PPCThread& CPU;
|
PPCThread& CPU;
|
||||||
|
|
||||||
PPU_DisAsm()
|
PPU_DisAsm()
|
||||||
: DisAsm(*(PPCThread*)NULL, DumpMode)
|
: PPC_DisAsm(*(PPCThread*)NULL, DumpMode)
|
||||||
, CPU(*(PPCThread*)NULL)
|
, CPU(*(PPCThread*)NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
PPU_DisAsm(PPCThread& cpu, DisAsmModes mode = NormalMode)
|
PPU_DisAsm(PPCThread& cpu, DisAsmModes mode = NormalMode)
|
||||||
: DisAsm(cpu, mode)
|
: PPC_DisAsm(cpu, mode)
|
||||||
, CPU(cpu)
|
, CPU(cpu)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -937,14 +937,6 @@ private:
|
|||||||
case 1: DisAsm_INT3("bcctrl", bo, bi, bh); break;
|
case 1: DisAsm_INT3("bcctrl", bo, bi, bh); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void BCTR()
|
|
||||||
{
|
|
||||||
Write("bctr");
|
|
||||||
}
|
|
||||||
void BCTRL()
|
|
||||||
{
|
|
||||||
Write("bctrl");
|
|
||||||
}
|
|
||||||
END_OPCODES_GROUP(G_13);
|
END_OPCODES_GROUP(G_13);
|
||||||
|
|
||||||
|
|
||||||
|
640
rpcs3/Emu/Cell/PPUInstrTable.h
Normal file
640
rpcs3/Emu/Cell/PPUInstrTable.h
Normal file
@ -0,0 +1,640 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "PPCInstrTable.h"
|
||||||
|
#include "PPCDecoder.h"
|
||||||
|
#include "PPUOpcodes.h"
|
||||||
|
|
||||||
|
namespace PPU_instr
|
||||||
|
{
|
||||||
|
//This field is used in rotate instructions to specify the first 1 bit of a 64-bit mask
|
||||||
|
static DoubleCodeField<21, 25, 26, 26, 5> mb;
|
||||||
|
|
||||||
|
//This field is used in rotate instructions to specify the last 1 bit of a 64-bit mask
|
||||||
|
static DoubleCodeField<21, 25, 26, 26, 5> me;
|
||||||
|
|
||||||
|
//This field is used to specify a shift amount
|
||||||
|
static DoubleCodeField<16, 20, 30, 30, 5> sh;
|
||||||
|
|
||||||
|
//This field is used to specify a special-purpose register for the mtspr and mfspr instructions
|
||||||
|
static CodeField<11, 20> SPR;
|
||||||
|
|
||||||
|
//
|
||||||
|
static CodeField<6, 10> VS(FIELD_R_VPR);
|
||||||
|
|
||||||
|
//
|
||||||
|
static CodeField<6, 10> VD(FIELD_R_VPR);
|
||||||
|
|
||||||
|
//
|
||||||
|
static CodeField<11, 15> VA(FIELD_R_VPR);
|
||||||
|
|
||||||
|
//
|
||||||
|
static CodeField<16, 20> VB(FIELD_R_VPR);
|
||||||
|
|
||||||
|
//
|
||||||
|
static CodeField<21, 25> VC(FIELD_R_VPR);
|
||||||
|
|
||||||
|
//
|
||||||
|
static CodeField<11, 15> VUIMM;
|
||||||
|
|
||||||
|
//
|
||||||
|
static CodeFieldSigned<11, 15> VSIMM;
|
||||||
|
|
||||||
|
//
|
||||||
|
static CodeField<22, 25> VSH;
|
||||||
|
|
||||||
|
//This field is used to specify a GPR to be used as a destination
|
||||||
|
static CodeField<6, 10> RD(FIELD_R_GPR);
|
||||||
|
|
||||||
|
//This field is used to specify a GPR to be used as a source
|
||||||
|
static CodeField<6, 10> RS(FIELD_R_GPR);
|
||||||
|
|
||||||
|
//This field is used to specify a GPR to be used as a source or destination
|
||||||
|
static CodeField<11, 15> RA(FIELD_R_GPR);
|
||||||
|
|
||||||
|
//This field is used to specify a GPR to be used as a source
|
||||||
|
static CodeField<16, 20> RB(FIELD_R_GPR);
|
||||||
|
|
||||||
|
//This field is used to specify the number of bytes to move in an immediate string load or store
|
||||||
|
static CodeField<16, 20> NB;
|
||||||
|
|
||||||
|
//This field is used to specify one of the CR fields, or one of the FPSCR fields, as a destination
|
||||||
|
static CodeField<6, 8> CRFD(FIELD_R_CR);
|
||||||
|
|
||||||
|
//This field is used to specify one of the CR fields, or one of the FPSCR fields, as a source
|
||||||
|
static CodeField<11, 13> CRFS(FIELD_R_CR);
|
||||||
|
|
||||||
|
//This field is used to specify a bit in the CR to be used as a source
|
||||||
|
static CodeField<11, 15> CRBA(FIELD_R_CR);
|
||||||
|
|
||||||
|
//This field is used to specify a bit in the CR to be used as a source
|
||||||
|
static CodeField<16, 20> CRBB(FIELD_R_CR);
|
||||||
|
|
||||||
|
//This field is used to specify a bit in the CR, or in the FPSCR, as the destination of the result of an instruction
|
||||||
|
static CodeField<6, 10> CRBD(FIELD_R_CR);
|
||||||
|
|
||||||
|
//
|
||||||
|
static CodeField<6, 10> BT;
|
||||||
|
|
||||||
|
//
|
||||||
|
static CodeField<11, 15> BA;
|
||||||
|
|
||||||
|
//
|
||||||
|
static CodeField<16, 20> BB;
|
||||||
|
|
||||||
|
//
|
||||||
|
static CodeField<6, 10> BF;
|
||||||
|
|
||||||
|
//This field is used to specify options for the branch conditional instructions
|
||||||
|
static CodeField<6, 10> BO;
|
||||||
|
|
||||||
|
//This field is used to specify a bit in the CR to be used as the condition of a branch conditional instruction
|
||||||
|
static CodeField<11, 13> BI;
|
||||||
|
|
||||||
|
//Immediate field specifying a 14-bit signed two's complement branch displacement that is concatenated on the
|
||||||
|
//right with ‘00’ and sign-extended to 64 bits.
|
||||||
|
static CodeFieldSigned<16, 31> BD(FIELD_BRANCH);
|
||||||
|
|
||||||
|
//
|
||||||
|
static CodeField<19, 20> BH;
|
||||||
|
|
||||||
|
//
|
||||||
|
static CodeField<11, 13> BFA;
|
||||||
|
|
||||||
|
//Field used by the optional data stream variant of the dcbt instruction.
|
||||||
|
static CodeField<9, 10> TH;
|
||||||
|
|
||||||
|
//This field is used to specify the conditions on which to trap
|
||||||
|
static CodeField<6, 10> TO;
|
||||||
|
|
||||||
|
//
|
||||||
|
static CodeField<21, 25> MB;
|
||||||
|
|
||||||
|
//
|
||||||
|
static CodeField<26, 30> ME;
|
||||||
|
|
||||||
|
//This field is used to specify a shift amount
|
||||||
|
static CodeField<16, 20> SH;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Absolute address bit.
|
||||||
|
0 The immediate field represents an address relative to the current instruction address (CIA). (For more
|
||||||
|
information on the CIA, see Table 8-3.) The effective (logical) address of the branch is either the sum
|
||||||
|
of the LI field sign-extended to 64 bits and the address of the branch instruction or the sum of the BD
|
||||||
|
field sign-extended to 64 bits and the address of the branch instruction.
|
||||||
|
1 The immediate field represents an absolute address. The effective address (EA) of the branch is the
|
||||||
|
LI field sign-extended to 64 bits or the BD field sign-extended to 64 bits.
|
||||||
|
*/
|
||||||
|
static CodeField<30> AA;
|
||||||
|
|
||||||
|
//
|
||||||
|
static CodeFieldSigned<6, 31> LL(FIELD_BRANCH);
|
||||||
|
/*
|
||||||
|
Link bit.
|
||||||
|
0 Does not update the link register (LR).
|
||||||
|
1 Updates the LR. If the instruction is a branch instruction, the address of the instruction following the
|
||||||
|
branch instruction is placed into the LR.
|
||||||
|
*/
|
||||||
|
static CodeField<31> LK;
|
||||||
|
|
||||||
|
//This field is used for extended arithmetic to enable setting OV and SO in the XER
|
||||||
|
static CodeField<21> OE;
|
||||||
|
|
||||||
|
//Field used to specify whether an integer compare instruction is to compare 64-bit numbers or 32-bit numbers
|
||||||
|
static CodeField<10> L_10;
|
||||||
|
static CodeField<6> L_6;
|
||||||
|
static CodeField<9, 10> L_9_10;
|
||||||
|
static CodeField<11> L_11;
|
||||||
|
//
|
||||||
|
static CodeField<16, 19> I;
|
||||||
|
|
||||||
|
//
|
||||||
|
static CodeField<16, 27> DQ;
|
||||||
|
|
||||||
|
//This field is used to specify an FPR as the destination
|
||||||
|
static CodeField<6, 10> FRD;
|
||||||
|
|
||||||
|
//This field is used to specify an FPR as a source
|
||||||
|
static CodeField<6, 10> FRS;
|
||||||
|
|
||||||
|
//
|
||||||
|
static CodeField<7, 14> FLM;
|
||||||
|
|
||||||
|
//This field is used to specify an FPR as a source
|
||||||
|
static CodeField<11, 15> FRA(FIELD_R_FPR);
|
||||||
|
|
||||||
|
//This field is used to specify an FPR as a source
|
||||||
|
static CodeField<16, 20> FRB(FIELD_R_FPR);
|
||||||
|
|
||||||
|
//This field is used to specify an FPR as a source
|
||||||
|
static CodeField<21, 25> FRC(FIELD_R_FPR);
|
||||||
|
|
||||||
|
//This field mask is used to identify the CR fields that are to be updated by the mtcrf instruction.
|
||||||
|
static CodeField<12, 19> CRM;
|
||||||
|
|
||||||
|
//
|
||||||
|
static CodeField<6, 31> SYS;
|
||||||
|
|
||||||
|
//Immediate field specifying a 16-bit signed two's complement integer that is sign-extended to 64 bits
|
||||||
|
static CodeFieldSigned<16, 31> D;
|
||||||
|
|
||||||
|
//
|
||||||
|
struct : public CodeFieldSigned<16, 31>
|
||||||
|
{
|
||||||
|
static __forceinline u32 decode(u32 data)
|
||||||
|
{
|
||||||
|
int res = sign<size>((data & mask) >> shift);
|
||||||
|
if(res < 0) return res - 1;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __forceinline void encode(u32& data, u32 value)
|
||||||
|
{
|
||||||
|
if((s32)value < 0)
|
||||||
|
{
|
||||||
|
value++;
|
||||||
|
}
|
||||||
|
|
||||||
|
data &= ~mask;
|
||||||
|
data |= (value << shift) & mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual u32 operator ()(u32 data) const
|
||||||
|
{
|
||||||
|
return decode(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void operator ()(u32& data, u32 value) const
|
||||||
|
{
|
||||||
|
return encode(data, value);
|
||||||
|
}
|
||||||
|
} static DS;
|
||||||
|
|
||||||
|
//This immediate field is used to specify a 16-bit signed integer
|
||||||
|
static CodeFieldSigned<16, 31> simm16;
|
||||||
|
|
||||||
|
//This immediate field is used to specify a 16-bit unsigned integer
|
||||||
|
static CodeField<16, 31> uimm16;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Record bit.
|
||||||
|
0 Does not update the condition register (CR).
|
||||||
|
1 Updates the CR to reflect the result of the operation.
|
||||||
|
For integer instructions, CR bits [0–2] are set to reflect the result as a signed quantity and CR bit [3]
|
||||||
|
receives a copy of the summary overflow bit, XER[SO]. The result as an unsigned quantity or a bit
|
||||||
|
string can be deduced from the EQ bit. For floating-point instructions, CR bits [4–7] are set to reflect
|
||||||
|
floating-point exception, floating-point enabled exception, floating-point invalid operation exception,
|
||||||
|
and floating-point overflow exception.
|
||||||
|
*/
|
||||||
|
static CodeField<31> RC;
|
||||||
|
|
||||||
|
//Primary opcode field
|
||||||
|
static CodeField<0, 5> OPCD;
|
||||||
|
|
||||||
|
static CodeField<26, 31> GD_04; //0x3f
|
||||||
|
static CodeField<21, 31> GD_04_0;//0x7ff
|
||||||
|
static CodeField<21, 30> GD_13; //0x3ff
|
||||||
|
static CodeField<28, 29> GD_1e; //0x3
|
||||||
|
static CodeField<21, 30> GD_1f; //0x3ff
|
||||||
|
static CodeField<30, 31> GD_3a; //0x3
|
||||||
|
static CodeField<26, 30> GD_3b; //0x1f
|
||||||
|
static CodeField<30, 31> GD_3e; //0x3
|
||||||
|
static CodeField<26, 30> GD_3f;//0x1f
|
||||||
|
static CodeField<21, 30> GD_3f_0; //0x3ff
|
||||||
|
|
||||||
|
static CodeField<0, 31> GetCode;
|
||||||
|
static CodeField<9, 10> STRM;
|
||||||
|
|
||||||
|
static auto main_list = new_list<0x40>(OPCD, instr_bind(&PPU_Opcodes::UNK, GetCode, OPCD, OPCD));
|
||||||
|
static auto g04_list = new_list<0x40>(main_list, PPU_opcodes::G_04, GD_04);
|
||||||
|
static auto g04_0_list = new_list<0x800>(g04_list, GD_04_0, instr_bind(&PPU_Opcodes::UNK, GetCode, OPCD, GD_04_0));
|
||||||
|
static auto g13_list = new_list<0x400>(main_list, PPU_opcodes::G_13, GD_13, instr_bind(&PPU_Opcodes::UNK, GetCode, OPCD, GD_13));
|
||||||
|
static auto g1e_list = new_list<0x4>(main_list, PPU_opcodes::G_1e, GD_1e, instr_bind(&PPU_Opcodes::UNK, GetCode, OPCD, GD_1e));
|
||||||
|
static auto g1f_list = new_list<0x400>(main_list, PPU_opcodes::G_1f, GD_1f, instr_bind(&PPU_Opcodes::UNK, GetCode, OPCD, GD_1f));
|
||||||
|
static auto g3a_list = new_list<0x4>(main_list, PPU_opcodes::G_3a, GD_3a, instr_bind(&PPU_Opcodes::UNK, GetCode, OPCD, GD_3a));
|
||||||
|
static auto g3b_list = new_list<0x20>(main_list, PPU_opcodes::G_3b, GD_3b, instr_bind(&PPU_Opcodes::UNK, GetCode, OPCD, GD_3b));
|
||||||
|
static auto g3e_list = new_list<0x4>(main_list, PPU_opcodes::G_3e, GD_3e, instr_bind(&PPU_Opcodes::UNK, GetCode, OPCD, GD_3e));
|
||||||
|
static auto g3f_list = new_list<0x20>(main_list, PPU_opcodes::G_3f, GD_3f);
|
||||||
|
static auto g3f_0_list = new_list<0x400>(g3f_list, GD_3f_0, instr_bind(&PPU_Opcodes::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__)
|
||||||
|
|
||||||
|
bind_instr(main_list, TDI, TO, RA, simm16);
|
||||||
|
bind_instr(main_list, TWI, TO, RA, simm16);
|
||||||
|
bind_instr(main_list, MULLI, RD, RA, simm16);
|
||||||
|
bind_instr(main_list, SUBFIC, RD, RA, simm16);
|
||||||
|
bind_instr(main_list, CMPLI, CRFD, L_10, RA, uimm16);
|
||||||
|
bind_instr(main_list, CMPI, CRFD, L_10, RA, simm16);
|
||||||
|
bind_instr(main_list, ADDIC, RD, RA, simm16);
|
||||||
|
bind_instr(main_list, ADDIC_, RD, RA, simm16);
|
||||||
|
bind_instr(main_list, ADDI, RD, RA, simm16);
|
||||||
|
bind_instr(main_list, ADDIS, RD, RA, simm16);
|
||||||
|
bind_instr(main_list, BC, BO, BI, BD, AA, LK);
|
||||||
|
bind_instr(main_list, SC, SYS);
|
||||||
|
bind_instr(main_list, B, LL, AA, LK);
|
||||||
|
bind_instr(main_list, RLWIMI, RA, RS, SH, MB, ME, RC);
|
||||||
|
bind_instr(main_list, RLWINM, RA, RS, SH, MB, ME, RC);
|
||||||
|
bind_instr(main_list, RLWNM, RA, RS, RB, MB, ME, RC);
|
||||||
|
bind_instr(main_list, ORI, RA, RS, uimm16);
|
||||||
|
bind_instr(main_list, ORIS, RA, RS, uimm16);
|
||||||
|
bind_instr(main_list, XORI, RA, RS, uimm16);
|
||||||
|
bind_instr(main_list, XORIS, RA, RS, uimm16);
|
||||||
|
bind_instr(main_list, ANDI_, RA, RS, uimm16);
|
||||||
|
bind_instr(main_list, ANDIS_, RA, RS, uimm16);
|
||||||
|
bind_instr(main_list, LWZ, RD, RA, D);
|
||||||
|
bind_instr(main_list, LWZU, RD, RA, D);
|
||||||
|
bind_instr(main_list, LBZ, RD, RA, D);
|
||||||
|
bind_instr(main_list, LBZU, RD, RA, D);
|
||||||
|
bind_instr(main_list, STW, RS, RA, D);
|
||||||
|
bind_instr(main_list, STWU, RS, RA, D);
|
||||||
|
bind_instr(main_list, STB, RS, RA, D);
|
||||||
|
bind_instr(main_list, STBU, RS, RA, D);
|
||||||
|
bind_instr(main_list, LHZ, RD, RA, D);
|
||||||
|
bind_instr(main_list, LHZU, RD, RA, D);
|
||||||
|
bind_instr(main_list, STH, RS, RA, D);
|
||||||
|
bind_instr(main_list, STHU, RS, RA, D);
|
||||||
|
bind_instr(main_list, LMW, RD, RA, D);
|
||||||
|
bind_instr(main_list, STMW, RS, RA, D);
|
||||||
|
bind_instr(main_list, LFS, FRD, RA, D);
|
||||||
|
bind_instr(main_list, LFSU, FRD, RA, D);
|
||||||
|
bind_instr(main_list, LFD, FRD, RA, D);
|
||||||
|
bind_instr(main_list, LFDU, FRD, RA, D);
|
||||||
|
bind_instr(main_list, STFS, FRS, RA, D);
|
||||||
|
bind_instr(main_list, STFSU, FRS, RA, D);
|
||||||
|
bind_instr(main_list, STFD, FRS, RA, D);
|
||||||
|
bind_instr(main_list, STFDU, FRS, RA, D);
|
||||||
|
|
||||||
|
bind_instr(g04_list, VMADDFP, VD, VA, VB, VC);
|
||||||
|
bind_instr(g04_list, VMHADDSHS, VD, VA, VB, VC);
|
||||||
|
bind_instr(g04_list, VMHRADDSHS, VD, VA, VB, VC);
|
||||||
|
bind_instr(g04_list, VMLADDUHM, VD, VA, VB, VC);
|
||||||
|
bind_instr(g04_list, VMSUMMBM, VD, VA, VB, VC);
|
||||||
|
bind_instr(g04_list, VMSUMSHM, VD, VA, VB, VC);
|
||||||
|
bind_instr(g04_list, VMSUMSHS, VD, VA, VB, VC);
|
||||||
|
bind_instr(g04_list, VMSUMUBM, VD, VA, VB, VC);
|
||||||
|
bind_instr(g04_list, VMSUMUHM, VD, VA, VB, VC);
|
||||||
|
bind_instr(g04_list, VMSUMUHS, VD, VA, VB, VC);
|
||||||
|
bind_instr(g04_list, VNMSUBFP, VD, VA, VB, VC);
|
||||||
|
bind_instr(g04_list, VPERM, VD, VA, VB, VC);
|
||||||
|
bind_instr(g04_list, VSEL, VD, VA, VB, VC);
|
||||||
|
bind_instr(g04_list, VSLDOI, VD, VA, VB, VSH);
|
||||||
|
|
||||||
|
bind_instr(g04_0_list, MFVSCR, VD);
|
||||||
|
bind_instr(g04_0_list, MTVSCR, VB);
|
||||||
|
bind_instr(g04_0_list, VADDCUW, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VADDFP, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VADDSBS, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VADDSHS, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VADDSWS, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VADDUBM, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VADDUBS, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VADDUHM, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VADDUHS, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VADDUWM, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VADDUWS, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VAND, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VANDC, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VAVGSB, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VAVGSH, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VAVGSW, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VAVGUB, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VAVGUH, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VAVGUW, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VCFSX, VD, VUIMM, VB);
|
||||||
|
bind_instr(g04_0_list, VCFUX, VD, VUIMM, VB);
|
||||||
|
bind_instr(g04_0_list, VCMPBFP, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VCMPBFP_, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VCMPEQFP, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VCMPEQFP_, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VCMPEQUB, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VCMPEQUB_, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VCMPEQUH, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VCMPEQUH_, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VCMPEQUW, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VCMPEQUW_, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VCMPGEFP, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VCMPGEFP_, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VCMPGTFP, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VCMPGTFP_, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VCMPGTSB, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VCMPGTSB_, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VCMPGTSH, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VCMPGTSH_, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VCMPGTSW, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VCMPGTSW_, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VCMPGTUB, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VCMPGTUB_, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VCMPGTUH, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VCMPGTUH_, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VCMPGTUW, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VCMPGTUW_, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VCTSXS, VD, VUIMM, VB);
|
||||||
|
bind_instr(g04_0_list, VCTUXS, VD, VUIMM, VB);
|
||||||
|
bind_instr(g04_0_list, VEXPTEFP, VD, VB);
|
||||||
|
bind_instr(g04_0_list, VLOGEFP, VD, VB);
|
||||||
|
bind_instr(g04_0_list, VMAXFP, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VMAXSB, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VMAXSH, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VMAXSW, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VMAXUB, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VMAXUH, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VMAXUW, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VMINFP, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VMINSB, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VMINSH, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VMINSW, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VMINUB, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VMINUH, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VMINUW, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VMRGHB, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VMRGHH, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VMRGHW, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VMRGLB, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VMRGLH, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VMRGLW, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VMULESB, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VMULESH, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VMULEUB, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VMULEUH, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VMULOSB, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VMULOSH, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VMULOUB, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VMULOUH, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VNOR, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VOR, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VPKPX, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VPKSHSS, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VPKSHUS, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VPKSWSS, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VPKSWUS, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VPKUHUM, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VPKUHUS, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VPKUWUM, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VPKUWUS, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VREFP, VD, VB);
|
||||||
|
bind_instr(g04_0_list, VRFIM, VD, VB);
|
||||||
|
bind_instr(g04_0_list, VRFIN, VD, VB);
|
||||||
|
bind_instr(g04_0_list, VRFIP, VD, VB);
|
||||||
|
bind_instr(g04_0_list, VRFIZ, VD, VB);
|
||||||
|
bind_instr(g04_0_list, VRLB, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VRLH, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VRLW, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VRSQRTEFP, VD, VB);
|
||||||
|
bind_instr(g04_0_list, VSL, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VSLB, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VSLH, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VSLO, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VSLW, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VSPLTB, VD, VUIMM, VB);
|
||||||
|
bind_instr(g04_0_list, VSPLTH, VD, VUIMM, VB);
|
||||||
|
bind_instr(g04_0_list, VSPLTISB, VD, VSIMM);
|
||||||
|
bind_instr(g04_0_list, VSPLTISH, VD, VSIMM);
|
||||||
|
bind_instr(g04_0_list, VSPLTISW, VD, VSIMM);
|
||||||
|
bind_instr(g04_0_list, VSPLTW, VD, VUIMM, VB);
|
||||||
|
bind_instr(g04_0_list, VSR, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VSRAB, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VSRAH, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VSRAW, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VSRB, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VSRH, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VSRO, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VSRW, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VSUBCUW, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VSUBFP, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VSUBSBS, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VSUBSHS, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VSUBSWS, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VSUBUBM, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VSUBUBS, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VSUBUHM, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VSUBUHS, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VSUBUWM, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VSUBUWS, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VSUMSWS, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VSUM2SWS, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VSUM4SBS, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VSUM4SHS, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VSUM4UBS, VD, VA, VB);
|
||||||
|
bind_instr(g04_0_list, VUPKHPX, VD, VB);
|
||||||
|
bind_instr(g04_0_list, VUPKHSB, VD, VB);
|
||||||
|
bind_instr(g04_0_list, VUPKHSH, VD, VB);
|
||||||
|
bind_instr(g04_0_list, VUPKLPX, VD, VB);
|
||||||
|
bind_instr(g04_0_list, VUPKLSB, VD, VB);
|
||||||
|
bind_instr(g04_0_list, VUPKLSH, VD, VB);
|
||||||
|
bind_instr(g04_0_list, VXOR, VD, VA, VB);
|
||||||
|
|
||||||
|
bind_instr(g13_list, MCRF, CRFD, CRFS);
|
||||||
|
bind_instr(g13_list, BCLR, BO, BI, BH, LK);
|
||||||
|
bind_instr(g13_list, CRNOR, CRBD, CRBA, CRBB);
|
||||||
|
bind_instr(g13_list, CRANDC, CRBD, CRBA, CRBB);
|
||||||
|
bind_instr(g13_list, ISYNC);
|
||||||
|
bind_instr(g13_list, CRXOR, CRBD, CRBA, CRBB);
|
||||||
|
bind_instr(g13_list, CRNAND, CRBD, CRBA, CRBB);
|
||||||
|
bind_instr(g13_list, CRAND, CRBD, CRBA, CRBB);
|
||||||
|
bind_instr(g13_list, CREQV, CRBD, CRBA, CRBB);
|
||||||
|
bind_instr(g13_list, CRORC, CRBD, CRBA, CRBB);
|
||||||
|
bind_instr(g13_list, CROR, CRBD, CRBA, CRBB);
|
||||||
|
bind_instr(g13_list, BCCTR, BO, BI, BH, LK);
|
||||||
|
|
||||||
|
bind_instr(g1e_list, RLDICL, RA, RS, sh, mb, RC);
|
||||||
|
bind_instr(g1e_list, RLDICR, RA, RS, sh, me, RC);
|
||||||
|
bind_instr(g1e_list, RLDIC, RA, RS, sh, mb, RC);
|
||||||
|
bind_instr(g1e_list, RLDIMI, RA, RS, sh, mb, RC);
|
||||||
|
|
||||||
|
/*0x000*/bind_instr(g1f_list, CMP, CRFD, L_10, RA, RB);
|
||||||
|
/*0x004*/bind_instr(g1f_list, TW, TO, RA, RB);
|
||||||
|
/*0x006*/bind_instr(g1f_list, LVSL, VD, RA, RB);
|
||||||
|
/*0x007*/bind_instr(g1f_list, LVEBX, VD, RA, RB);
|
||||||
|
/*0x008*/bind_instr(g1f_list, SUBFC, RD, RA, RB, OE, RC);
|
||||||
|
/*0x009*/bind_instr(g1f_list, MULHDU, RD, RA, RB, RC);
|
||||||
|
/*0x00a*/bind_instr(g1f_list, ADDC, RD, RA, RB, OE, RC);
|
||||||
|
/*0x00b*/bind_instr(g1f_list, MULHWU, RD, RA, RB, RC);
|
||||||
|
/*0x013*/bind_instr(g1f_list, MFOCRF, L_11, RD, CRM);
|
||||||
|
/*0x014*/bind_instr(g1f_list, LWARX, RD, RA, RB);
|
||||||
|
/*0x015*/bind_instr(g1f_list, LDX, RA, RS, RB);
|
||||||
|
/*0x017*/bind_instr(g1f_list, LWZX, RD, RA, RB);
|
||||||
|
/*0x018*/bind_instr(g1f_list, SLW, RA, RS, RB, RC);
|
||||||
|
/*0x01a*/bind_instr(g1f_list, CNTLZW, RA, RS, RC);
|
||||||
|
/*0x01b*/bind_instr(g1f_list, SLD, RA, RS, RB, RC);
|
||||||
|
/*0x01c*/bind_instr(g1f_list, AND, RA, RS, RB, RC);
|
||||||
|
/*0x020*/bind_instr(g1f_list, CMPL, CRFD, L_10, RA, RB);
|
||||||
|
/*0x026*/bind_instr(g1f_list, LVSR, VD, RA, RB);
|
||||||
|
/*0x027*/bind_instr(g1f_list, LVEHX, VD, RA, RB);
|
||||||
|
/*0x028*/bind_instr(g1f_list, SUBF, RD, RA, RB, OE, RC);
|
||||||
|
/*0x036*/bind_instr(g1f_list, DCBST, RA, RB);
|
||||||
|
/*0x03a*/bind_instr(g1f_list, CNTLZD, RA, RS, RC);
|
||||||
|
/*0x03c*/bind_instr(g1f_list, ANDC, RA, RS, RB, RC);
|
||||||
|
/*0x047*/bind_instr(g1f_list, LVEWX, VD, RA, RB);
|
||||||
|
/*0x049*/bind_instr(g1f_list, MULHD, RD, RA, RB, RC);
|
||||||
|
/*0x04b*/bind_instr(g1f_list, MULHW, RD, RA, RB, RC);
|
||||||
|
/*0x054*/bind_instr(g1f_list, LDARX, RD, RA, RB);
|
||||||
|
/*0x056*/bind_instr(g1f_list, DCBF, RA, RB);
|
||||||
|
/*0x057*/bind_instr(g1f_list, LBZX, RD, RA, RB);
|
||||||
|
/*0x067*/bind_instr(g1f_list, LVX, VD, RA, RB);
|
||||||
|
/*0x068*/bind_instr(g1f_list, NEG, RD, RA, OE, RC);
|
||||||
|
/*0x077*/bind_instr(g1f_list, LBZUX, RD, RA, RB);
|
||||||
|
/*0x07c*/bind_instr(g1f_list, NOR, RA, RS, RB, RC);
|
||||||
|
/*0x087*/bind_instr(g1f_list, STVEBX, VS, RA, RB);
|
||||||
|
/*0x088*/bind_instr(g1f_list, SUBFE, RD, RA, RB, OE, RC);
|
||||||
|
/*0x08a*/bind_instr(g1f_list, ADDE, RD, RA, RB, OE, RC);
|
||||||
|
/*0x090*/bind_instr(g1f_list, MTOCRF, CRM, RS);
|
||||||
|
/*0x095*/bind_instr(g1f_list, STDX, RS, RA, RB);
|
||||||
|
/*0x096*/bind_instr(g1f_list, STWCX_, RS, RA, RB);
|
||||||
|
/*0x097*/bind_instr(g1f_list, STWX, RS, RA, RB);
|
||||||
|
/*0x0a7*/bind_instr(g1f_list, STVEHX, VS, RA, RB);
|
||||||
|
/*0x0b5*/bind_instr(g1f_list, STDUX, RS, RA, RB);
|
||||||
|
/*0x0c7*/bind_instr(g1f_list, STVEWX, VS, RA, RB);
|
||||||
|
/*0x0ca*/bind_instr(g1f_list, ADDZE, RD, RA, OE, RC);
|
||||||
|
/*0x0d6*/bind_instr(g1f_list, STDCX_, RS, RA, RB);
|
||||||
|
/*0x0d7*/bind_instr(g1f_list, STBX, RS, RA, RB);
|
||||||
|
/*0x0e7*/bind_instr(g1f_list, STVX, VS, RA, RB);
|
||||||
|
/*0x0e9*/bind_instr(g1f_list, MULLD, RD, RA, RB, OE, RC);
|
||||||
|
/*0x0ea*/bind_instr(g1f_list, ADDME, RD, RA, OE, RC);
|
||||||
|
/*0x0eb*/bind_instr(g1f_list, MULLW, RD, RA, RB, OE, RC);
|
||||||
|
/*0x0f6*/bind_instr(g1f_list, DCBTST, TH, RA, RB);
|
||||||
|
/*0x10a*/bind_instr(g1f_list, ADD, RD, RA, RB, OE, RC);
|
||||||
|
/*0x116*/bind_instr(g1f_list, DCBT, RA, RB, TH);
|
||||||
|
/*0x117*/bind_instr(g1f_list, LHZX, RD, RA, RB);
|
||||||
|
/*0x11c*/bind_instr(g1f_list, EQV, RA, RS, RB, RC);
|
||||||
|
/*0x136*/bind_instr(g1f_list, ECIWX, RD, RA, RB);
|
||||||
|
/*0x137*/bind_instr(g1f_list, LHZUX, RD, RA, RB);
|
||||||
|
/*0x13c*/bind_instr(g1f_list, XOR, RA, RS, RB, RC);
|
||||||
|
/*0x153*/bind_instr(g1f_list, MFSPR, RD, SPR);
|
||||||
|
/*0x156*/bind_instr(g1f_list, DST, RA, RB, STRM, L_6);
|
||||||
|
/*0x157*/bind_instr(g1f_list, LHAX, RD, RA, RB);
|
||||||
|
/*0x167*/bind_instr(g1f_list, LVXL, VD, RA, RB);
|
||||||
|
/*0x168*/bind_instr(g1f_list, ABS, RD, RA, OE, RC);
|
||||||
|
/*0x173*/bind_instr(g1f_list, MFTB, RD, SPR);
|
||||||
|
/*0x176*/bind_instr(g1f_list, DSTST, RA, RB, STRM, L_6);
|
||||||
|
/*0x177*/bind_instr(g1f_list, LHAUX, RD, RA, RB);
|
||||||
|
/*0x197*/bind_instr(g1f_list, STHX, RS, RA, RB);
|
||||||
|
/*0x19c*/bind_instr(g1f_list, ORC, RA, RS, RB, RC);
|
||||||
|
/*0x1b6*/bind_instr(g1f_list, ECOWX, RS, RA, RB);
|
||||||
|
/*0x1bc*/bind_instr(g1f_list, OR, RA, RS, RB, RC);
|
||||||
|
/*0x1c9*/bind_instr(g1f_list, DIVDU, RD, RA, RB, OE, RC);
|
||||||
|
/*0x1cb*/bind_instr(g1f_list, DIVWU, RD, RA, RB, OE, RC);
|
||||||
|
/*0x1d3*/bind_instr(g1f_list, MTSPR, SPR, RS);
|
||||||
|
/*0x1d6*///DCBI
|
||||||
|
/*0x1dc*/bind_instr(g1f_list, NAND, RA, RS, RB, RC);
|
||||||
|
/*0x1e7*/bind_instr(g1f_list, STVXL, RS, RA, RB);
|
||||||
|
/*0x1e9*/bind_instr(g1f_list, DIVD, RD, RA, RB, OE, RC);
|
||||||
|
/*0x1eb*/bind_instr(g1f_list, DIVW, RD, RA, RB, OE, RC);
|
||||||
|
/*0x207*/bind_instr(g1f_list, LVLX, VD, RA, RB);
|
||||||
|
/*0x216*/bind_instr(g1f_list, LWBRX, RD, RA, RB);
|
||||||
|
/*0x217*/bind_instr(g1f_list, LFSX, FRD, RA, RB);
|
||||||
|
/*0x218*/bind_instr(g1f_list, SRW, RA, RS, RB, RC);
|
||||||
|
/*0x21b*/bind_instr(g1f_list, SRD, RA, RS, RB, RC);
|
||||||
|
/*0x227*/bind_instr(g1f_list, LVRX, VD, RA, RB);
|
||||||
|
/*0x237*/bind_instr(g1f_list, LFSUX, FRD, RA, RB);
|
||||||
|
/*0x256*/bind_instr(g1f_list, SYNC, L_9_10);
|
||||||
|
/*0x257*/bind_instr(g1f_list, LFDX, FRD, RA, RB);
|
||||||
|
/*0x277*/bind_instr(g1f_list, LFDUX, FRD, RA, RB);
|
||||||
|
/*0x287*/bind_instr(g1f_list, STVLX, VS, RA, RB);
|
||||||
|
/*0x297*/bind_instr(g1f_list, STFSX, RS, RA, RB);
|
||||||
|
/*0x2a7*/bind_instr(g1f_list, STVRX, VS, RA, RB);
|
||||||
|
/*0x2d7*/bind_instr(g1f_list, STFDX, RS, RA, RB);
|
||||||
|
/*0x307*/bind_instr(g1f_list, LVLXL, VD, RA, RB);
|
||||||
|
/*0x316*/bind_instr(g1f_list, LHBRX, RD, RA, RB);
|
||||||
|
/*0x318*/bind_instr(g1f_list, SRAW, RA, RS, RB, RC);
|
||||||
|
/*0x31a*/bind_instr(g1f_list, SRAD, RA, RS, RB, RC);
|
||||||
|
/*0x327*/bind_instr(g1f_list, LVRXL, VD, RA, RB);
|
||||||
|
/*0x336*/bind_instr(g1f_list, DSS, STRM, L_6);
|
||||||
|
/*0x338*/bind_instr(g1f_list, SRAWI, RA, RS, sh, RC);
|
||||||
|
/*0x33a*/bind_instr(g1f_list, SRADI1, RA, RS, sh, RC);
|
||||||
|
/*0x33b*/bind_instr(g1f_list, SRADI2, RA, RS, sh, RC);
|
||||||
|
/*0x356*/bind_instr(g1f_list, EIEIO);
|
||||||
|
/*0x39a*/bind_instr(g1f_list, EXTSH, RA, RS, RC);
|
||||||
|
/*0x3ba*/bind_instr(g1f_list, EXTSB, RA, RS, RC);
|
||||||
|
/*0x3d7*/bind_instr(g1f_list, STFIWX, FRS, RA, RB);
|
||||||
|
/*0x3da*/bind_instr(g1f_list, EXTSW, RA, RS, RC);
|
||||||
|
/*0x3d6*///ICBI
|
||||||
|
/*0x3f6*/bind_instr(g1f_list, DCBZ, RA, RB);
|
||||||
|
|
||||||
|
bind_instr(g3a_list, LD, RD, RA, D);
|
||||||
|
bind_instr(g3a_list, LDU, RD, RA, DS);
|
||||||
|
|
||||||
|
bind_instr(g3b_list, FDIVS, FRD, FRA, FRB, RC);
|
||||||
|
bind_instr(g3b_list, FSUBS, FRD, FRA, FRB, RC);
|
||||||
|
bind_instr(g3b_list, FADDS, FRD, FRA, FRB, RC);
|
||||||
|
bind_instr(g3b_list, FSQRTS, FRD, FRB, RC);
|
||||||
|
bind_instr(g3b_list, FRES, FRD, FRB, RC);
|
||||||
|
bind_instr(g3b_list, FMULS, FRD, FRA, FRC, RC);
|
||||||
|
bind_instr(g3b_list, FMADDS, FRD, FRA, FRC, FRB, RC);
|
||||||
|
bind_instr(g3b_list, FMSUBS, FRD, FRA, FRC, FRB, RC);
|
||||||
|
bind_instr(g3b_list, FNMSUBS, FRD, FRA, FRC, FRB, RC);
|
||||||
|
bind_instr(g3b_list, FNMADDS, FRD, FRA, FRC, FRB, RC);
|
||||||
|
|
||||||
|
bind_instr(g3e_list, STD, RS, RA, D);
|
||||||
|
bind_instr(g3e_list, STDU, RS, RA, DS);
|
||||||
|
|
||||||
|
bind_instr(g3f_list, FSEL, FRD, FRA, FRC, FRB, RC);
|
||||||
|
bind_instr(g3f_list, FMUL, FRD, FRA, FRC, RC);
|
||||||
|
bind_instr(g3f_list, FMSUB, FRD, FRA, FRC, FRB, RC);
|
||||||
|
bind_instr(g3f_list, FMADD, FRD, FRA, FRC, FRB, RC);
|
||||||
|
bind_instr(g3f_list, FNMSUB, FRD, FRA, FRC, FRB, RC);
|
||||||
|
bind_instr(g3f_list, FNMADD, FRD, FRA, FRC, FRB, RC);
|
||||||
|
|
||||||
|
bind_instr(g3f_0_list, FDIV, FRD, FRA, FRB, RC);
|
||||||
|
bind_instr(g3f_0_list, FSUB, FRD, FRA, FRB, RC);
|
||||||
|
bind_instr(g3f_0_list, FADD, FRD, FRA, FRB, RC);
|
||||||
|
bind_instr(g3f_0_list, FSQRT, FRD, FRB, RC);
|
||||||
|
bind_instr(g3f_0_list, FRSQRTE, FRD, FRB, RC);
|
||||||
|
bind_instr(g3f_0_list, FCMPU, CRFD, FRA, FRB);
|
||||||
|
bind_instr(g3f_0_list, FRSP, FRD, FRB, RC);
|
||||||
|
bind_instr(g3f_0_list, FCTIW, FRD, FRB, RC);
|
||||||
|
bind_instr(g3f_0_list, FCTIWZ, FRD, FRB, RC);
|
||||||
|
bind_instr(g3f_0_list, FCMPO, CRFD, FRA, FRB);
|
||||||
|
bind_instr(g3f_0_list, FNEG, FRD, FRB, RC);
|
||||||
|
bind_instr(g3f_0_list, FMR, FRD, FRB, RC);
|
||||||
|
bind_instr(g3f_0_list, FNABS, FRD, FRB, RC);
|
||||||
|
bind_instr(g3f_0_list, FABS, FRD, FRB, RC);
|
||||||
|
bind_instr(g3f_0_list, FCFID, FRD, FRB, RC);
|
||||||
|
bind_instr(g3f_0_list, FCTID, FRD, FRB, RC);
|
||||||
|
bind_instr(g3f_0_list, FCTIDZ, FRD, FRB, RC);
|
||||||
|
|
||||||
|
bind_instr(g3f_0_list, MTFSB1, BT, RC);
|
||||||
|
bind_instr(g3f_0_list, MCRFS, BF, BFA);
|
||||||
|
bind_instr(g3f_0_list, MTFSB0, BT, RC);
|
||||||
|
bind_instr(g3f_0_list, MTFSFI, CRFD, I, RC);
|
||||||
|
bind_instr(g3f_0_list, MFFS, FRD, RC);
|
||||||
|
bind_instr(g3f_0_list, MTFSF, FLM, FRB, RC);
|
||||||
|
};
|
1747
rpcs3/Emu/Cell/PPUProgramCompiler.cpp
Normal file
1747
rpcs3/Emu/Cell/PPUProgramCompiler.cpp
Normal file
File diff suppressed because it is too large
Load Diff
192
rpcs3/Emu/Cell/PPUProgramCompiler.h
Normal file
192
rpcs3/Emu/Cell/PPUProgramCompiler.h
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "PPUInstrTable.h"
|
||||||
|
#include "Loader/ELF64.h"
|
||||||
|
|
||||||
|
enum ArgType
|
||||||
|
{
|
||||||
|
ARG_ERR = 0,
|
||||||
|
ARG_NUM = 1 << 0,
|
||||||
|
ARG_NUM16 = 1 << 1,
|
||||||
|
ARG_TXT = 1 << 2,
|
||||||
|
ARG_REG_R = 1 << 3,
|
||||||
|
ARG_REG_F = 1 << 4,
|
||||||
|
ARG_REG_V = 1 << 5,
|
||||||
|
ARG_REG_CR = 1 << 6,
|
||||||
|
ARG_BRANCH = 1 << 7,
|
||||||
|
ARG_INSTR = 1 << 8,
|
||||||
|
ARG_IMM = ARG_NUM | ARG_NUM16 | ARG_BRANCH,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Arg
|
||||||
|
{
|
||||||
|
wxString string;
|
||||||
|
u32 value;
|
||||||
|
ArgType type;
|
||||||
|
|
||||||
|
Arg(const wxString& _string, const u32 _value = 0, const ArgType _type = ARG_ERR)
|
||||||
|
: string(_string)
|
||||||
|
, value(_value)
|
||||||
|
, type(_type)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SectionInfo
|
||||||
|
{
|
||||||
|
Elf64_Shdr shdr;
|
||||||
|
wxString name;
|
||||||
|
Array<u8> code;
|
||||||
|
u32 section_num;
|
||||||
|
|
||||||
|
SectionInfo(const wxString& name);
|
||||||
|
~SectionInfo();
|
||||||
|
|
||||||
|
void SetDataSize(u32 size, u32 align = 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ProgramInfo
|
||||||
|
{
|
||||||
|
Array<u8> code;
|
||||||
|
Elf64_Phdr phdr;
|
||||||
|
bool is_preload;
|
||||||
|
|
||||||
|
ProgramInfo()
|
||||||
|
{
|
||||||
|
is_preload = false;
|
||||||
|
code.Clear();
|
||||||
|
memset(&phdr, 0, sizeof(Elf64_Phdr));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CompilePPUProgram
|
||||||
|
{
|
||||||
|
struct Branch
|
||||||
|
{
|
||||||
|
wxString m_name;
|
||||||
|
s32 m_pos;
|
||||||
|
s32 m_id;
|
||||||
|
s32 m_addr;
|
||||||
|
|
||||||
|
Branch(const wxString& name, s32 pos)
|
||||||
|
: m_name(name)
|
||||||
|
, m_pos(pos)
|
||||||
|
, m_id(-1)
|
||||||
|
, m_addr(-1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Branch(const wxString& name, u32 id, u32 addr)
|
||||||
|
: m_name(name)
|
||||||
|
, m_pos(-1)
|
||||||
|
, m_id(id)
|
||||||
|
, m_addr(addr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
bool m_analyze;
|
||||||
|
s64 p;
|
||||||
|
u64 m_line;
|
||||||
|
const wxString& m_asm;
|
||||||
|
wxTextCtrl* m_asm_list;
|
||||||
|
wxTextCtrl* m_hex_list;
|
||||||
|
wxTextCtrl* m_err_list;
|
||||||
|
bool m_error;
|
||||||
|
Array<u32> m_code;
|
||||||
|
bool m_end_args;
|
||||||
|
Array<Branch> m_branches;
|
||||||
|
s32 m_branch_pos;
|
||||||
|
u32 m_text_addr;
|
||||||
|
wxString m_file_path;
|
||||||
|
|
||||||
|
struct SpData
|
||||||
|
{
|
||||||
|
wxString m_data;
|
||||||
|
u32 m_addr;
|
||||||
|
|
||||||
|
SpData(const wxString& data, u32 addr)
|
||||||
|
: m_data(data)
|
||||||
|
, m_addr(addr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Array<SpData> m_sp_string;
|
||||||
|
Array<Arg> m_args;
|
||||||
|
u32 m_cur_arg;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CompilePPUProgram(
|
||||||
|
const wxString& asm_,
|
||||||
|
const wxString& file_path = wxEmptyString,
|
||||||
|
wxTextCtrl* asm_list = nullptr,
|
||||||
|
wxTextCtrl* hex_list = nullptr,
|
||||||
|
wxTextCtrl* err_list = nullptr,
|
||||||
|
bool analyze = false);
|
||||||
|
|
||||||
|
static bool IsSkip(const char c);
|
||||||
|
static bool IsCommit(const char c);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool IsEnd() const;
|
||||||
|
bool IsEndLn(const char c) const;
|
||||||
|
|
||||||
|
void WriteHex(const wxString& text);
|
||||||
|
void WriteError(const wxString& error);
|
||||||
|
|
||||||
|
char NextChar();
|
||||||
|
void NextLn();
|
||||||
|
void EndLn();
|
||||||
|
|
||||||
|
void FirstChar();
|
||||||
|
void PrevArg();
|
||||||
|
|
||||||
|
bool GetOp(wxString& result);
|
||||||
|
int GetArg(wxString& result, bool func = false);
|
||||||
|
|
||||||
|
bool CheckEnd(bool show_err = true);
|
||||||
|
|
||||||
|
void DetectArgInfo(Arg& arg);
|
||||||
|
void LoadArgs();
|
||||||
|
u32 GetBranchValue(const wxString& branch);
|
||||||
|
|
||||||
|
bool SetNextArgType(u32 types, bool show_err = true);
|
||||||
|
bool SetNextArgBranch(u8 aa, bool show_err = true);
|
||||||
|
|
||||||
|
public:
|
||||||
|
static bool IsBranchOp(const wxString& op);
|
||||||
|
static bool IsFuncOp(const wxString& op);
|
||||||
|
|
||||||
|
enum SP_TYPE
|
||||||
|
{
|
||||||
|
SP_ERR,
|
||||||
|
SP_INT,
|
||||||
|
SP_STRING,
|
||||||
|
SP_STRLEN,
|
||||||
|
SP_BUF,
|
||||||
|
SP_SRL,
|
||||||
|
SP_SRR,
|
||||||
|
SP_MUL,
|
||||||
|
SP_DIV,
|
||||||
|
SP_ADD,
|
||||||
|
SP_SUB,
|
||||||
|
SP_AND,
|
||||||
|
SP_OR,
|
||||||
|
SP_XOR,
|
||||||
|
SP_NOT,
|
||||||
|
SP_NOR,
|
||||||
|
};
|
||||||
|
|
||||||
|
static SP_TYPE GetSpType(const wxString& op);
|
||||||
|
static wxString GetSpStyle(const SP_TYPE sp);
|
||||||
|
|
||||||
|
static bool IsSpOp(const wxString& op);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Branch& GetBranch(const wxString& name);
|
||||||
|
void SetSp(const wxString& name, u32 addr, bool create);
|
||||||
|
void LoadSp(const wxString& op, Elf64_Shdr& s_opd);
|
||||||
|
|
||||||
|
public:
|
||||||
|
void Compile();
|
||||||
|
};
|
@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Emu/Cell/SPUOpcodes.h"
|
#include "Emu/Cell/SPUOpcodes.h"
|
||||||
#include "Emu/Cell/Decoder.h"
|
#include "Emu/Cell/PPCDecoder.h"
|
||||||
|
|
||||||
#define START_OPCODES_GROUP_(group, reg) \
|
#define START_OPCODES_GROUP_(group, reg) \
|
||||||
case(##group##): \
|
case(##group##): \
|
||||||
@ -21,7 +21,7 @@
|
|||||||
#define ADD_OPCODE(name, regs) case(##name##):m_op.##name####regs##; return
|
#define ADD_OPCODE(name, regs) case(##name##):m_op.##name####regs##; return
|
||||||
#define ADD_NULL_OPCODE(name) ADD_OPCODE(##name##, ())
|
#define ADD_NULL_OPCODE(name) ADD_OPCODE(##name##, ())
|
||||||
|
|
||||||
class SPU_Decoder : public Decoder
|
class SPU_Decoder : public PPC_Decoder
|
||||||
{
|
{
|
||||||
u32 m_code;
|
u32 m_code;
|
||||||
SPU_Opcodes& m_op;
|
SPU_Opcodes& m_op;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Emu/Cell/SPUOpcodes.h"
|
#include "Emu/Cell/SPUOpcodes.h"
|
||||||
#include "Emu/Cell/DisAsm.h"
|
#include "Emu/Cell/PPCDisAsm.h"
|
||||||
#include "Emu/Cell/SPUThread.h"
|
#include "Emu/Cell/SPUThread.h"
|
||||||
#include "Gui/DisAsmFrame.h"
|
#include "Gui/DisAsmFrame.h"
|
||||||
#include "Emu/Memory/Memory.h"
|
#include "Emu/Memory/Memory.h"
|
||||||
@ -11,19 +11,19 @@
|
|||||||
|
|
||||||
class SPU_DisAsm
|
class SPU_DisAsm
|
||||||
: public SPU_Opcodes
|
: public SPU_Opcodes
|
||||||
, public DisAsm
|
, public PPC_DisAsm
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PPCThread& CPU;
|
PPCThread& CPU;
|
||||||
|
|
||||||
SPU_DisAsm()
|
SPU_DisAsm()
|
||||||
: DisAsm(*(PPCThread*)NULL, DumpMode)
|
: PPC_DisAsm(*(PPCThread*)NULL, DumpMode)
|
||||||
, CPU(*(PPCThread*)NULL)
|
, CPU(*(PPCThread*)NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
SPU_DisAsm(PPCThread& cpu, DisAsmModes mode = NormalMode)
|
SPU_DisAsm(PPCThread& cpu, DisAsmModes mode = NormalMode)
|
||||||
: DisAsm(cpu, mode)
|
: PPC_DisAsm(cpu, mode)
|
||||||
, CPU(cpu)
|
, CPU(cpu)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -1233,7 +1233,7 @@ void GLGSRender::ExecCMD()
|
|||||||
if(m_set_viewport_horizontal && m_set_viewport_vertical)
|
if(m_set_viewport_horizontal && m_set_viewport_vertical)
|
||||||
{
|
{
|
||||||
glViewport(m_viewport_x, m_viewport_y, m_viewport_w, m_viewport_h);
|
glViewport(m_viewport_x, m_viewport_y, m_viewport_w, m_viewport_h);
|
||||||
if(m_frame->GetSize() != wxSize(m_viewport_w, m_viewport_h))
|
if(m_frame->GetClientSize() != wxSize(m_viewport_w, m_viewport_h))
|
||||||
m_frame->SetClientSize(m_viewport_w, m_viewport_h);
|
m_frame->SetClientSize(m_viewport_w, m_viewport_h);
|
||||||
//m_frame->SetViewport(m_viewport_x, m_viewport_y, m_viewport_w, m_viewport_h);
|
//m_frame->SetViewport(m_viewport_x, m_viewport_y, m_viewport_w, m_viewport_h);
|
||||||
}
|
}
|
||||||
|
@ -188,7 +188,7 @@ int cellSysutilRegisterCallback(int slot, u64 func_addr, u64 userdata)
|
|||||||
sc_sysutil.Warning("cellSysutilRegisterCallback(slot=%d, func_addr=0x%llx, userdata=0x%llx)", slot, func_addr, userdata);
|
sc_sysutil.Warning("cellSysutilRegisterCallback(slot=%d, func_addr=0x%llx, userdata=0x%llx)", slot, func_addr, userdata);
|
||||||
Emu.GetCallbackManager().m_exit_callback.Register(slot, func_addr, userdata);
|
Emu.GetCallbackManager().m_exit_callback.Register(slot, func_addr, userdata);
|
||||||
|
|
||||||
wxGetApp().m_MainFrame->UpdateUI();
|
wxGetApp().SendDbgCommand(DID_REGISTRED_CALLBACK);
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
@ -198,7 +198,7 @@ int cellSysutilUnregisterCallback(int slot)
|
|||||||
sc_sysutil.Warning("cellSysutilUnregisterCallback(slot=%d)", slot);
|
sc_sysutil.Warning("cellSysutilUnregisterCallback(slot=%d)", slot);
|
||||||
Emu.GetCallbackManager().m_exit_callback.Unregister(slot);
|
Emu.GetCallbackManager().m_exit_callback.Unregister(slot);
|
||||||
|
|
||||||
wxGetApp().m_MainFrame->UpdateUI();
|
wxGetApp().SendDbgCommand(DID_UNREGISTRED_CALLBACK);
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
@ -6,9 +6,11 @@
|
|||||||
#include "Emu/Cell/PPCThreadManager.h"
|
#include "Emu/Cell/PPCThreadManager.h"
|
||||||
#include "Emu/Cell/PPUThread.h"
|
#include "Emu/Cell/PPUThread.h"
|
||||||
#include "Emu/Cell/SPUThread.h"
|
#include "Emu/Cell/SPUThread.h"
|
||||||
#include "Gui/CompilerELF.h"
|
#include "Emu/Cell/PPUInstrTable.h"
|
||||||
|
using namespace PPU_instr;
|
||||||
|
|
||||||
using namespace PPU_opcodes;
|
static const wxString& BreakPointsDBName = "BreakPoints.dat";
|
||||||
|
static const u16 bpdb_version = 0x1000;
|
||||||
|
|
||||||
//SysCalls SysCallsManager;
|
//SysCalls SysCallsManager;
|
||||||
|
|
||||||
@ -26,16 +28,9 @@ void Emulator::Init()
|
|||||||
//m_memory_viewer = new MemoryViewerPanel(wxGetApp().m_MainFrame);
|
//m_memory_viewer = new MemoryViewerPanel(wxGetApp().m_MainFrame);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Emulator::SetSelf(const wxString& path)
|
void Emulator::SetPath(const wxString& path)
|
||||||
{
|
{
|
||||||
m_path = path;
|
m_path = path;
|
||||||
IsSelf = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Emulator::SetElf(const wxString& path)
|
|
||||||
{
|
|
||||||
m_path = path;
|
|
||||||
IsSelf = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Emulator::CheckStatus()
|
void Emulator::CheckStatus()
|
||||||
@ -110,6 +105,7 @@ void Emulator::Load()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LoadPoints(BreakPointsDBName);
|
||||||
PPCThread& thread = GetCPU().AddThread(l.GetMachine() == MACHINE_PPC64);
|
PPCThread& thread = GetCPU().AddThread(l.GetMachine() == MACHINE_PPC64);
|
||||||
|
|
||||||
thread.SetEntry(l.GetEntry());
|
thread.SetEntry(l.GetEntry());
|
||||||
@ -123,22 +119,22 @@ void Emulator::Load()
|
|||||||
Memory.Write32(m_rsx_callback - 4, m_rsx_callback);
|
Memory.Write32(m_rsx_callback - 4, m_rsx_callback);
|
||||||
|
|
||||||
mem32_t callback_data(m_rsx_callback);
|
mem32_t callback_data(m_rsx_callback);
|
||||||
callback_data += ToOpcode(ADDI) | ToRD(11) | ToRA(0) | ToIMM16(0x3ff);
|
callback_data += ADDI(11, 0, 0x3ff);
|
||||||
callback_data += ToOpcode(SC) | ToSYS(2);
|
callback_data += SC(2);
|
||||||
callback_data += ToOpcode(G_13) | SetField(BCLR, 21, 30) | ToBO(0x10 | 0x04) | ToBI(0) | ToLK(0);
|
callback_data += BCLR(0x10 | 0x04, 0, 0, 0);
|
||||||
|
|
||||||
m_ppu_thr_exit = Memory.MainMem.Alloc(4 * 3);
|
m_ppu_thr_exit = Memory.MainMem.Alloc(4 * 3);
|
||||||
|
|
||||||
mem32_t ppu_thr_exit_data(m_ppu_thr_exit);
|
mem32_t ppu_thr_exit_data(m_ppu_thr_exit);
|
||||||
ppu_thr_exit_data += ToOpcode(ADDI) | ToRD(11) | ToRA(0) | ToIMM16(41);
|
ppu_thr_exit_data += ADDI(11, 0, 41);
|
||||||
ppu_thr_exit_data += ToOpcode(SC) | ToSYS(2);
|
ppu_thr_exit_data += SC(2);
|
||||||
ppu_thr_exit_data += ToOpcode(G_13) | SetField(BCLR, 21, 30) | ToBO(0x10 | 0x04) | ToBI(0) | ToLK(0);
|
ppu_thr_exit_data += BCLR(0x10 | 0x04, 0, 0, 0);
|
||||||
|
|
||||||
thread.Run();
|
thread.Run();
|
||||||
|
|
||||||
wxGetApp().m_MainFrame->UpdateUI();
|
|
||||||
wxCriticalSectionLocker lock(m_cs_status);
|
wxCriticalSectionLocker lock(m_cs_status);
|
||||||
m_status = Ready;
|
m_status = Ready;
|
||||||
|
wxGetApp().SendDbgCommand(DID_READY_EMU);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Emulator::Run()
|
void Emulator::Run()
|
||||||
@ -156,6 +152,8 @@ void Emulator::Run()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wxGetApp().SendDbgCommand(DID_START_EMU);
|
||||||
|
|
||||||
wxCriticalSectionLocker lock(m_cs_status);
|
wxCriticalSectionLocker lock(m_cs_status);
|
||||||
//ConLog.Write("run...");
|
//ConLog.Write("run...");
|
||||||
m_status = Runned;
|
m_status = Runned;
|
||||||
@ -165,7 +163,13 @@ void Emulator::Run()
|
|||||||
m_vfs.Mount("/app_home/", vfsDevice::GetRoot(m_path), new vfsLocalFile());
|
m_vfs.Mount("/app_home/", vfsDevice::GetRoot(m_path), new vfsLocalFile());
|
||||||
m_vfs.Mount(vfsDevice::GetRootPs3(m_path), vfsDevice::GetRoot(m_path), new vfsLocalFile());
|
m_vfs.Mount(vfsDevice::GetRootPs3(m_path), vfsDevice::GetRoot(m_path), new vfsLocalFile());
|
||||||
|
|
||||||
for(uint i=0; i<m_vfs.m_devices.GetCount(); ++i) ConLog.Write("%s -> %s", m_vfs.m_devices[i].GetPs3Path(), m_vfs.m_devices[i].GetLocalPath());
|
ConLog.SkipLn();
|
||||||
|
ConLog.Write("Mount info:");
|
||||||
|
for(uint i=0; i<m_vfs.m_devices.GetCount(); ++i)
|
||||||
|
{
|
||||||
|
ConLog.Write("%s -> %s", m_vfs.m_devices[i].GetPs3Path(), m_vfs.m_devices[i].GetLocalPath());
|
||||||
|
}
|
||||||
|
ConLog.SkipLn();
|
||||||
|
|
||||||
//if(m_memory_viewer && m_memory_viewer->exit) safe_delete(m_memory_viewer);
|
//if(m_memory_viewer && m_memory_viewer->exit) safe_delete(m_memory_viewer);
|
||||||
|
|
||||||
@ -173,54 +177,57 @@ void Emulator::Run()
|
|||||||
//m_memory_viewer->Show();
|
//m_memory_viewer->Show();
|
||||||
//m_memory_viewer->ShowPC();
|
//m_memory_viewer->ShowPC();
|
||||||
|
|
||||||
wxGetApp().SendDbgCommand(DID_START_EMU);
|
if(!m_dbg_console)
|
||||||
wxGetApp().m_MainFrame->UpdateUI();
|
m_dbg_console = new DbgConsole();
|
||||||
|
|
||||||
if(!m_dbg_console) m_dbg_console = new DbgConsole();
|
|
||||||
|
|
||||||
GetGSManager().Init();
|
GetGSManager().Init();
|
||||||
GetCallbackManager().Init();
|
GetCallbackManager().Init();
|
||||||
|
|
||||||
GetCPU().Exec();
|
GetCPU().Exec();
|
||||||
|
wxGetApp().SendDbgCommand(DID_STARTED_EMU);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Emulator::Pause()
|
void Emulator::Pause()
|
||||||
{
|
{
|
||||||
if(!IsRunned()) return;
|
if(!IsRunned()) return;
|
||||||
//ConLog.Write("pause...");
|
//ConLog.Write("pause...");
|
||||||
|
wxGetApp().SendDbgCommand(DID_PAUSE_EMU);
|
||||||
|
|
||||||
wxCriticalSectionLocker lock(m_cs_status);
|
wxCriticalSectionLocker lock(m_cs_status);
|
||||||
m_status = Paused;
|
m_status = Paused;
|
||||||
wxGetApp().SendDbgCommand(DID_PAUSE_EMU);
|
wxGetApp().SendDbgCommand(DID_PAUSED_EMU);
|
||||||
wxGetApp().m_MainFrame->UpdateUI();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Emulator::Resume()
|
void Emulator::Resume()
|
||||||
{
|
{
|
||||||
if(!IsPaused()) return;
|
if(!IsPaused()) return;
|
||||||
//ConLog.Write("resume...");
|
//ConLog.Write("resume...");
|
||||||
|
wxGetApp().SendDbgCommand(DID_RESUME_EMU);
|
||||||
|
|
||||||
wxCriticalSectionLocker lock(m_cs_status);
|
wxCriticalSectionLocker lock(m_cs_status);
|
||||||
m_status = Runned;
|
m_status = Runned;
|
||||||
wxGetApp().SendDbgCommand(DID_RESUME_EMU);
|
|
||||||
wxGetApp().m_MainFrame->UpdateUI();
|
|
||||||
|
|
||||||
CheckStatus();
|
CheckStatus();
|
||||||
if(IsRunned() && Ini.CPUDecoderMode.GetValue() != 1) GetCPU().Exec();
|
if(IsRunned() && Ini.CPUDecoderMode.GetValue() != 1) GetCPU().Exec();
|
||||||
|
wxGetApp().SendDbgCommand(DID_RESUMED_EMU);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Emulator::Stop()
|
void Emulator::Stop()
|
||||||
{
|
{
|
||||||
if(IsStopped()) return;
|
if(IsStopped()) return;
|
||||||
//ConLog.Write("shutdown...");
|
//ConLog.Write("shutdown...");
|
||||||
|
|
||||||
|
wxGetApp().SendDbgCommand(DID_STOP_EMU);
|
||||||
{
|
{
|
||||||
wxCriticalSectionLocker lock(m_cs_status);
|
wxCriticalSectionLocker lock(m_cs_status);
|
||||||
m_status = Stopped;
|
m_status = Stopped;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_rsx_callback = 0;
|
m_rsx_callback = 0;
|
||||||
wxGetApp().SendDbgCommand(DID_STOP_EMU);
|
|
||||||
wxGetApp().m_MainFrame->UpdateUI();
|
SavePoints(BreakPointsDBName);
|
||||||
|
m_break_points.Clear();
|
||||||
|
m_marked_points.Clear();
|
||||||
|
|
||||||
GetGSManager().Close();
|
GetGSManager().Close();
|
||||||
GetCPU().Close();
|
GetCPU().Close();
|
||||||
@ -238,7 +245,63 @@ void Emulator::Stop()
|
|||||||
GetDbgCon().Close();
|
GetDbgCon().Close();
|
||||||
GetDbgCon().Clear();
|
GetDbgCon().Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
//if(m_memory_viewer && m_memory_viewer->IsShown()) m_memory_viewer->Hide();
|
//if(m_memory_viewer && m_memory_viewer->IsShown()) m_memory_viewer->Hide();
|
||||||
|
wxGetApp().SendDbgCommand(DID_STOPED_EMU);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Emulator::SavePoints(const wxString& path)
|
||||||
|
{
|
||||||
|
wxFile f(path, wxFile::write);
|
||||||
|
|
||||||
|
u32 break_count = m_break_points.GetCount();
|
||||||
|
u32 marked_count = m_marked_points.GetCount();
|
||||||
|
|
||||||
|
f.Write(&bpdb_version, sizeof(u16));
|
||||||
|
f.Write(&break_count, sizeof(u32));
|
||||||
|
f.Write(&marked_count, sizeof(u32));
|
||||||
|
|
||||||
|
if(break_count)
|
||||||
|
{
|
||||||
|
f.Write(&m_break_points[0], sizeof(u64) * break_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(marked_count)
|
||||||
|
{
|
||||||
|
f.Write(&m_marked_points[0], sizeof(u64) * marked_count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Emulator::LoadPoints(const wxString& path)
|
||||||
|
{
|
||||||
|
if(!wxFileExists(path)) return;
|
||||||
|
|
||||||
|
wxFile f(path);
|
||||||
|
|
||||||
|
u32 break_count, marked_count;
|
||||||
|
u16 version;
|
||||||
|
f.Read(&version, sizeof(u16));
|
||||||
|
f.Read(&break_count, sizeof(u32));
|
||||||
|
f.Read(&marked_count, sizeof(u32));
|
||||||
|
|
||||||
|
if(version != bpdb_version ||
|
||||||
|
(sizeof(u16) + break_count * sizeof(u64) + sizeof(u32) + marked_count * sizeof(u64) + sizeof(u32)) != f.Length())
|
||||||
|
{
|
||||||
|
ConLog.Error("'%s' is borken", path);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(break_count > 0)
|
||||||
|
{
|
||||||
|
m_break_points.SetCount(break_count);
|
||||||
|
f.Read(&m_break_points[0], sizeof(u64) * break_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(marked_count > 0)
|
||||||
|
{
|
||||||
|
m_marked_points.SetCount(marked_count);
|
||||||
|
f.Read(&m_marked_points[0], sizeof(u64) * marked_count);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Emulator Emu;
|
Emulator Emu;
|
@ -63,6 +63,9 @@ class Emulator
|
|||||||
MemoryViewerPanel* m_memory_viewer;
|
MemoryViewerPanel* m_memory_viewer;
|
||||||
//ArrayF<CPUThread> m_cpu_threads;
|
//ArrayF<CPUThread> m_cpu_threads;
|
||||||
|
|
||||||
|
Array<u64> m_break_points;
|
||||||
|
Array<u64> m_marked_points;
|
||||||
|
|
||||||
PPCThreadManager m_thread_manager;
|
PPCThreadManager m_thread_manager;
|
||||||
PadManager m_pad_manager;
|
PadManager m_pad_manager;
|
||||||
IdManager m_id_manager;
|
IdManager m_id_manager;
|
||||||
@ -75,13 +78,11 @@ class Emulator
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
wxString m_path;
|
wxString m_path;
|
||||||
bool IsSelf;
|
|
||||||
|
|
||||||
Emulator();
|
Emulator();
|
||||||
|
|
||||||
void Init();
|
void Init();
|
||||||
void SetSelf(const wxString& path);
|
void SetPath(const wxString& path);
|
||||||
void SetElf(const wxString& path);
|
|
||||||
|
|
||||||
PPCThreadManager& GetCPU() { return m_thread_manager; }
|
PPCThreadManager& GetCPU() { return m_thread_manager; }
|
||||||
PadManager& GetPadManager() { return m_pad_manager; }
|
PadManager& GetPadManager() { return m_pad_manager; }
|
||||||
@ -90,6 +91,8 @@ public:
|
|||||||
GSManager& GetGSManager() { return m_gs_manager; }
|
GSManager& GetGSManager() { return m_gs_manager; }
|
||||||
CallbackManager& GetCallbackManager() { return m_callback_manager; }
|
CallbackManager& GetCallbackManager() { return m_callback_manager; }
|
||||||
VFS& GetVFS() { return m_vfs; }
|
VFS& GetVFS() { return m_vfs; }
|
||||||
|
Array<u64>& GetBreakPoints() { return m_break_points; }
|
||||||
|
Array<u64>& GetMarkedPoints() { return m_marked_points; }
|
||||||
|
|
||||||
void SetTLSData(const u64 addr, const u64 filesz, const u64 memsz)
|
void SetTLSData(const u64 addr, const u64 filesz, const u64 memsz)
|
||||||
{
|
{
|
||||||
@ -115,6 +118,9 @@ public:
|
|||||||
void Resume();
|
void Resume();
|
||||||
void Stop();
|
void Stop();
|
||||||
|
|
||||||
|
void SavePoints(const wxString& path);
|
||||||
|
void LoadPoints(const wxString& path);
|
||||||
|
|
||||||
__forceinline bool IsRunned() const { wxCriticalSectionLocker lock(m_cs_status); return m_status == Runned; }
|
__forceinline bool IsRunned() const { wxCriticalSectionLocker lock(m_cs_status); return m_status == Runned; }
|
||||||
__forceinline bool IsPaused() const { wxCriticalSectionLocker lock(m_cs_status); return m_status == Paused; }
|
__forceinline bool IsPaused() const { wxCriticalSectionLocker lock(m_cs_status); return m_status == Paused; }
|
||||||
__forceinline bool IsStopped() const { wxCriticalSectionLocker lock(m_cs_status); return m_status == Stopped; }
|
__forceinline bool IsStopped() const { wxCriticalSectionLocker lock(m_cs_status); return m_status == Stopped; }
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -5,38 +5,6 @@
|
|||||||
#include "Loader/ELF64.h"
|
#include "Loader/ELF64.h"
|
||||||
#include <wx/richtext/richtextctrl.h>
|
#include <wx/richtext/richtextctrl.h>
|
||||||
|
|
||||||
void Write8(wxFile& f, const u8 data);
|
|
||||||
void Write16(wxFile& f, const u16 data);
|
|
||||||
void Write32(wxFile& f, const u32 data);
|
|
||||||
void Write64(wxFile& f, const u64 data);
|
|
||||||
|
|
||||||
struct SectionInfo
|
|
||||||
{
|
|
||||||
Elf64_Shdr shdr;
|
|
||||||
wxString name;
|
|
||||||
Array<u8> code;
|
|
||||||
u32 section_num;
|
|
||||||
|
|
||||||
SectionInfo(const wxString& name);
|
|
||||||
~SectionInfo();
|
|
||||||
|
|
||||||
void SetDataSize(u32 size, u32 align = 0);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ProgramInfo
|
|
||||||
{
|
|
||||||
Array<u8> code;
|
|
||||||
Elf64_Phdr phdr;
|
|
||||||
bool is_preload;
|
|
||||||
|
|
||||||
ProgramInfo()
|
|
||||||
{
|
|
||||||
is_preload = false;
|
|
||||||
code.Clear();
|
|
||||||
memset(&phdr, 0, sizeof(Elf64_Phdr));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class CompilerELF : public FrameBase
|
class CompilerELF : public FrameBase
|
||||||
{
|
{
|
||||||
wxAuiManager m_aui_mgr;
|
wxAuiManager m_aui_mgr;
|
||||||
@ -78,42 +46,3 @@ public:
|
|||||||
|
|
||||||
void UpdateStatus(int offset=0);
|
void UpdateStatus(int offset=0);
|
||||||
};
|
};
|
||||||
|
|
||||||
static u32 SetField(u32 src, u32 from, u32 to)
|
|
||||||
{
|
|
||||||
return (src & ((1 << ((to - from) + 1)) - 1)) << (31 - to);
|
|
||||||
}
|
|
||||||
|
|
||||||
static u32 SetField(s32 src, u32 p)
|
|
||||||
{
|
|
||||||
return (src & 0x1) << (31 - p);
|
|
||||||
}
|
|
||||||
|
|
||||||
static u32 ToOpcode(u32 i) { return SetField(i, 0, 5); }
|
|
||||||
static u32 ToRS(u32 i) { return SetField(i, 6, 10); }
|
|
||||||
static u32 ToRD(u32 i) { return SetField(i, 6, 10); }
|
|
||||||
static u32 ToRA(u32 i) { return SetField(i, 11, 15); }
|
|
||||||
static u32 ToRB(u32 i) { return SetField(i, 16, 20); }
|
|
||||||
static u32 ToLL(u32 i) { return i & 0x03fffffc; }
|
|
||||||
static u32 ToAA(u32 i) { return SetField(i, 30); }
|
|
||||||
static u32 ToLK(u32 i) { return SetField(i, 31); }
|
|
||||||
static u32 ToIMM16(s32 i) { return SetField(i, 16, 31); }
|
|
||||||
static u32 ToD(s32 i) { return SetField(i, 16, 31); }
|
|
||||||
static u32 ToDS(s32 i)
|
|
||||||
{
|
|
||||||
if(i < 0) return ToD(i + 1);
|
|
||||||
return ToD(i);
|
|
||||||
}
|
|
||||||
static u32 ToSYS(u32 i) { return SetField(i, 6, 31); }
|
|
||||||
static u32 ToBF(u32 i) { return SetField(i, 6, 10); }
|
|
||||||
static u32 ToBO(u32 i) { return SetField(i, 6, 10); }
|
|
||||||
static u32 ToBI(u32 i) { return SetField(i, 11, 15); }
|
|
||||||
static u32 ToBD(u32 i) { return i & 0xfffc; }
|
|
||||||
static u32 ToMB(u32 i) { return SetField(i, 21, 25); }
|
|
||||||
static u32 ToME(u32 i) { return SetField(i, 26, 30); }
|
|
||||||
static u32 ToSH(u32 i) { return SetField(i, 16, 20); }
|
|
||||||
static u32 ToRC(u32 i) { return SetField(i, 31); }
|
|
||||||
static u32 ToOE(u32 i) { return SetField(i, 21); }
|
|
||||||
static u32 ToL(u32 i) { return SetField(i, 10); }
|
|
||||||
static u32 ToCRFD(u32 i) { return SetField(i, 6, 8); }
|
|
||||||
static u32 ToTO(u32 i) { return SetField(i, 6, 10); }
|
|
@ -113,8 +113,8 @@ bool ElfType64 = false;
|
|||||||
class DumperThread : public ThreadBase
|
class DumperThread : public ThreadBase
|
||||||
{
|
{
|
||||||
volatile uint id;
|
volatile uint id;
|
||||||
DisAsm* disasm;
|
PPC_DisAsm* disasm;
|
||||||
Decoder* decoder;
|
PPC_Decoder* decoder;
|
||||||
volatile bool* done;
|
volatile bool* done;
|
||||||
volatile u8 cores;
|
volatile u8 cores;
|
||||||
MTProgressDialog* prog_dial;
|
MTProgressDialog* prog_dial;
|
||||||
@ -338,8 +338,8 @@ void DisAsmFrame::Dump(wxCommandEvent& WXUNUSED(event))
|
|||||||
default: ConLog.Error("Corrupted ELF!"); return;
|
default: ConLog.Error("Corrupted ELF!"); return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DisAsm* disasm;
|
PPC_DisAsm* disasm;
|
||||||
Decoder* decoder;
|
PPC_Decoder* decoder;
|
||||||
|
|
||||||
if(Emu.GetCPU().GetThreads()[0].IsSPU())
|
if(Emu.GetCPU().GetThreads()[0].IsSPU())
|
||||||
{
|
{
|
||||||
|
@ -99,6 +99,6 @@ void GameViewer::DClick(wxListEvent& event)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Emu.Stop();
|
Emu.Stop();
|
||||||
Emu.SetElf(path);
|
Emu.SetPath(path);
|
||||||
Emu.Run();
|
Emu.Run();
|
||||||
}
|
}
|
@ -2,8 +2,6 @@
|
|||||||
#include "InterpreterDisAsm.h"
|
#include "InterpreterDisAsm.h"
|
||||||
|
|
||||||
static const int show_lines = 30;
|
static const int show_lines = 30;
|
||||||
static const wxString& BreakPointsDBName = "BreakPoints.dat";
|
|
||||||
static const u16 bpdb_version = 0x1000;
|
|
||||||
|
|
||||||
u32 FixPc(const u32 pc)
|
u32 FixPc(const u32 pc)
|
||||||
{
|
{
|
||||||
@ -85,73 +83,11 @@ InterpreterDisAsmFrame::InterpreterDisAsmFrame(wxWindow* parent, PPCThread* cpu)
|
|||||||
|
|
||||||
m_app_connector.Connect(wxEVT_DBG_COMMAND, wxCommandEventHandler(InterpreterDisAsmFrame::HandleCommand), (wxObject*)0, this);
|
m_app_connector.Connect(wxEVT_DBG_COMMAND, wxCommandEventHandler(InterpreterDisAsmFrame::HandleCommand), (wxObject*)0, this);
|
||||||
WriteRegs();
|
WriteRegs();
|
||||||
|
|
||||||
Load(BreakPointsDBName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
InterpreterDisAsmFrame::~InterpreterDisAsmFrame()
|
InterpreterDisAsmFrame::~InterpreterDisAsmFrame()
|
||||||
{
|
{
|
||||||
ThreadBase::Stop();
|
ThreadBase::Stop();
|
||||||
Save(BreakPointsDBName);
|
|
||||||
}
|
|
||||||
|
|
||||||
void InterpreterDisAsmFrame::Save(const wxString& path)
|
|
||||||
{
|
|
||||||
wxFile f(path, wxFile::write);
|
|
||||||
u32 break_count = m_break_points.GetCount();
|
|
||||||
u32 marked_count = markedPC.GetCount();
|
|
||||||
f.Write(&bpdb_version, sizeof(u16));
|
|
||||||
f.Write(&break_count, sizeof(u32));
|
|
||||||
f.Write(&marked_count, sizeof(u32));
|
|
||||||
|
|
||||||
for(u32 i=0; i<break_count; ++i)
|
|
||||||
{
|
|
||||||
f.Write(&m_break_points[i], sizeof(u64));
|
|
||||||
}
|
|
||||||
|
|
||||||
for(u32 i=0; i<marked_count; ++i)
|
|
||||||
{
|
|
||||||
f.Write(&markedPC[i], sizeof(u64));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void InterpreterDisAsmFrame::Load(const wxString& path)
|
|
||||||
{
|
|
||||||
if(!wxFileExists(path)) return;
|
|
||||||
|
|
||||||
wxFile f(path);
|
|
||||||
u32 break_count, marked_count;
|
|
||||||
u16 version;
|
|
||||||
f.Read(&version, sizeof(u16));
|
|
||||||
f.Read(&break_count, sizeof(u32));
|
|
||||||
f.Read(&marked_count, sizeof(u32));
|
|
||||||
|
|
||||||
if(version != bpdb_version ||
|
|
||||||
(sizeof(u16) + break_count * sizeof(u64) + sizeof(u32) + marked_count * sizeof(u64) + sizeof(u32)) != f.Length())
|
|
||||||
{
|
|
||||||
ConLog.Error("'%s' is borken", path);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(break_count > 0)
|
|
||||||
{
|
|
||||||
m_break_points.SetCount(break_count);
|
|
||||||
|
|
||||||
for(u32 i=0; i<break_count; ++i)
|
|
||||||
{
|
|
||||||
f.Read(&m_break_points[i], sizeof(u64));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(marked_count > 0)
|
|
||||||
{
|
|
||||||
markedPC.SetCount(marked_count);
|
|
||||||
|
|
||||||
for(u32 i=0; i<marked_count; ++i)
|
|
||||||
{
|
|
||||||
f.Read(&markedPC[i], sizeof(u64));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void InterpreterDisAsmFrame::OnKeyDown(wxKeyEvent& event)
|
void InterpreterDisAsmFrame::OnKeyDown(wxKeyEvent& event)
|
||||||
@ -224,9 +160,9 @@ void InterpreterDisAsmFrame::ShowAddr(const u64 addr)
|
|||||||
{
|
{
|
||||||
colour = wxColour("White");
|
colour = wxColour("White");
|
||||||
|
|
||||||
for(u32 i=0; i<markedPC.GetCount(); ++i)
|
for(u32 i=0; i<Emu.GetMarkedPoints().GetCount(); ++i)
|
||||||
{
|
{
|
||||||
if(markedPC[i] == PC)
|
if(Emu.GetMarkedPoints()[i] == PC)
|
||||||
{
|
{
|
||||||
colour = wxColour("Wheat");
|
colour = wxColour("Wheat");
|
||||||
break;
|
break;
|
||||||
@ -252,7 +188,7 @@ void InterpreterDisAsmFrame::ShowAddr(const u64 addr)
|
|||||||
if(remove_markedPC[i] > mpc) remove_markedPC[i]--;
|
if(remove_markedPC[i] > mpc) remove_markedPC[i]--;
|
||||||
}
|
}
|
||||||
|
|
||||||
markedPC.RemoveAt(mpc);
|
Emu.GetMarkedPoints().RemoveAt(mpc);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_list->SetColumnWidth(0, -1);
|
m_list->SetColumnWidth(0, -1);
|
||||||
@ -272,33 +208,50 @@ void InterpreterDisAsmFrame::HandleCommand(wxCommandEvent& event)
|
|||||||
PPCThread* thr = (PPCThread*)event.GetClientData();
|
PPCThread* thr = (PPCThread*)event.GetClientData();
|
||||||
event.Skip();
|
event.Skip();
|
||||||
|
|
||||||
if(!thr || thr->GetId() != CPU.GetId()) return;
|
if(!thr)
|
||||||
|
|
||||||
switch(event.GetId())
|
|
||||||
{
|
{
|
||||||
case DID_EXEC_THREAD:
|
switch(event.GetId())
|
||||||
case DID_REMOVE_THREAD:
|
{
|
||||||
case DID_RESUME_THREAD:
|
case DID_STOP_EMU:
|
||||||
m_btn_step->Disable();
|
case DID_PAUSE_EMU:
|
||||||
m_btn_run->Disable();
|
DoUpdate();
|
||||||
m_btn_pause->Enable();
|
break;
|
||||||
break;
|
}
|
||||||
|
}
|
||||||
|
else if(thr->GetId() == CPU.GetId())
|
||||||
|
{
|
||||||
|
switch(event.GetId())
|
||||||
|
{
|
||||||
|
case DID_PAUSE_THREAD:
|
||||||
|
m_btn_run->Enable();
|
||||||
|
m_btn_step->Enable();
|
||||||
|
m_btn_pause->Disable();
|
||||||
|
|
||||||
case DID_START_THREAD:
|
case DID_CREATE_THREAD:
|
||||||
case DID_CREATE_THREAD:
|
DoUpdate();
|
||||||
case DID_PAUSE_THREAD:
|
break;
|
||||||
case DID_STOP_THREAD:
|
|
||||||
m_btn_step->Enable(!Emu.IsReady());
|
|
||||||
m_btn_run->Enable(!Emu.IsReady());
|
|
||||||
m_btn_pause->Disable();
|
|
||||||
|
|
||||||
DoUpdate();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DID_STOP_EMU:
|
case DID_START_THREAD:
|
||||||
case DID_PAUSE_EMU:
|
case DID_EXEC_THREAD:
|
||||||
DoUpdate();
|
case DID_RESUME_THREAD:
|
||||||
break;
|
m_btn_run->Disable();
|
||||||
|
m_btn_step->Disable();
|
||||||
|
m_btn_pause->Enable();
|
||||||
|
|
||||||
|
if(event.GetId() == DID_START_THREAD)
|
||||||
|
{
|
||||||
|
DoUpdate();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DID_REMOVE_THREAD:
|
||||||
|
case DID_STOP_THREAD:
|
||||||
|
m_btn_run->Disable();
|
||||||
|
m_btn_step->Disable();
|
||||||
|
m_btn_pause->Disable();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -331,7 +284,7 @@ void InterpreterDisAsmFrame::Show_Val(wxCommandEvent& WXUNUSED(event))
|
|||||||
{
|
{
|
||||||
u64 pc = CPU.PC;
|
u64 pc = CPU.PC;
|
||||||
sscanf(p_pc->GetLabel(), "%llx", &pc);
|
sscanf(p_pc->GetLabel(), "%llx", &pc);
|
||||||
remove_markedPC.AddCpy(markedPC.AddCpy(pc));
|
remove_markedPC.AddCpy(Emu.GetMarkedPoints().AddCpy(pc));
|
||||||
ShowAddr(FixPc(pc));
|
ShowAddr(FixPc(pc));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -395,9 +348,9 @@ void InterpreterDisAsmFrame::MouseWheel(wxMouseEvent& event)
|
|||||||
|
|
||||||
bool InterpreterDisAsmFrame::IsBreakPoint(u64 pc)
|
bool InterpreterDisAsmFrame::IsBreakPoint(u64 pc)
|
||||||
{
|
{
|
||||||
for(u32 i=0; i<m_break_points.GetCount(); ++i)
|
for(u32 i=0; i<Emu.GetBreakPoints().GetCount(); ++i)
|
||||||
{
|
{
|
||||||
if(m_break_points[i] == pc) return true;
|
if(Emu.GetBreakPoints()[i] == pc) return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -405,20 +358,20 @@ bool InterpreterDisAsmFrame::IsBreakPoint(u64 pc)
|
|||||||
|
|
||||||
void InterpreterDisAsmFrame::AddBreakPoint(u64 pc)
|
void InterpreterDisAsmFrame::AddBreakPoint(u64 pc)
|
||||||
{
|
{
|
||||||
for(u32 i=0; i<m_break_points.GetCount(); ++i)
|
for(u32 i=0; i<Emu.GetBreakPoints().GetCount(); ++i)
|
||||||
{
|
{
|
||||||
if(m_break_points[i] == pc) return;
|
if(Emu.GetBreakPoints()[i] == pc) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_break_points.AddCpy(pc);
|
Emu.GetBreakPoints().AddCpy(pc);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InterpreterDisAsmFrame::RemoveBreakPoint(u64 pc)
|
bool InterpreterDisAsmFrame::RemoveBreakPoint(u64 pc)
|
||||||
{
|
{
|
||||||
for(u32 i=0; i<m_break_points.GetCount(); ++i)
|
for(u32 i=0; i<Emu.GetBreakPoints().GetCount(); ++i)
|
||||||
{
|
{
|
||||||
if(m_break_points[i] != pc) continue;
|
if(Emu.GetBreakPoints()[i] != pc) continue;
|
||||||
m_break_points.RemoveAt(i);
|
Emu.GetBreakPoints().RemoveAt(i);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,13 +10,11 @@ class InterpreterDisAsmFrame
|
|||||||
, public ThreadBase
|
, public ThreadBase
|
||||||
{
|
{
|
||||||
wxListView* m_list;
|
wxListView* m_list;
|
||||||
DisAsm* disasm;
|
PPC_DisAsm* disasm;
|
||||||
Decoder* decoder;
|
PPC_Decoder* decoder;
|
||||||
u64 PC;
|
u64 PC;
|
||||||
Array<u64> markedPC;
|
|
||||||
Array<u32> remove_markedPC;
|
Array<u32> remove_markedPC;
|
||||||
wxTextCtrl* m_regs;
|
wxTextCtrl* m_regs;
|
||||||
Array<u64> m_break_points;
|
|
||||||
wxButton* m_btn_step;
|
wxButton* m_btn_step;
|
||||||
wxButton* m_btn_run;
|
wxButton* m_btn_run;
|
||||||
wxButton* m_btn_pause;
|
wxButton* m_btn_pause;
|
||||||
@ -29,9 +27,6 @@ public:
|
|||||||
InterpreterDisAsmFrame(wxWindow* parent, PPCThread* cpu);
|
InterpreterDisAsmFrame(wxWindow* parent, PPCThread* cpu);
|
||||||
~InterpreterDisAsmFrame();
|
~InterpreterDisAsmFrame();
|
||||||
|
|
||||||
void Save(const wxString& path);
|
|
||||||
void Load(const wxString& path);
|
|
||||||
|
|
||||||
void OnKeyDown(wxKeyEvent& event);
|
void OnKeyDown(wxKeyEvent& event);
|
||||||
void DoUpdate();
|
void DoUpdate();
|
||||||
void ShowAddr(const u64 addr);
|
void ShowAddr(const u64 addr);
|
||||||
|
@ -50,10 +50,10 @@ MainFrame::MainFrame()
|
|||||||
menu_boot.Append(id_boot_elf, "Boot Elf");
|
menu_boot.Append(id_boot_elf, "Boot Elf");
|
||||||
//menu_boot.Append(id_boot_self, "Boot Self");
|
//menu_boot.Append(id_boot_self, "Boot Self");
|
||||||
|
|
||||||
menu_sys.Append(id_sys_pause, "Pause");
|
menu_sys.Append(id_sys_pause, "Pause")->Enable(false);
|
||||||
menu_sys.Append(id_sys_stop, "Stop\tCtrl + S");
|
menu_sys.Append(id_sys_stop, "Stop\tCtrl + S")->Enable(false);
|
||||||
menu_sys.AppendSeparator();
|
menu_sys.AppendSeparator();
|
||||||
menu_sys.Append(id_sys_send_exit, "Send exit cmd");
|
menu_sys.Append(id_sys_send_exit, "Send exit cmd")->Enable(false);
|
||||||
|
|
||||||
menu_conf.Append(id_config_emu, "Settings");
|
menu_conf.Append(id_config_emu, "Settings");
|
||||||
|
|
||||||
@ -73,8 +73,7 @@ MainFrame::MainFrame()
|
|||||||
|
|
||||||
Connect( id_config_emu, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::Config) );
|
Connect( id_config_emu, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::Config) );
|
||||||
m_app_connector.Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(MainFrame::OnKeyDown), (wxObject*)0, this);
|
m_app_connector.Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(MainFrame::OnKeyDown), (wxObject*)0, this);
|
||||||
|
m_app_connector.Connect(wxEVT_DBG_COMMAND, wxCommandEventHandler(MainFrame::UpdateUI), (wxObject*)0, this);
|
||||||
UpdateUI();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MainFrame::~MainFrame()
|
MainFrame::~MainFrame()
|
||||||
@ -131,35 +130,35 @@ void MainFrame::BootGame(wxCommandEvent& WXUNUSED(event))
|
|||||||
|
|
||||||
if(wxFile::Access(elf0, wxFile::read))
|
if(wxFile::Access(elf0, wxFile::read))
|
||||||
{
|
{
|
||||||
Emu.SetElf(elf0);
|
Emu.SetPath(elf0);
|
||||||
ConLog.Write("Elf: booting...");
|
ConLog.Write("Elf: booting...");
|
||||||
}
|
}
|
||||||
else if(wxFile::Access(elf1, wxFile::read))
|
else if(wxFile::Access(elf1, wxFile::read))
|
||||||
{
|
{
|
||||||
Emu.SetElf(elf1);
|
Emu.SetPath(elf1);
|
||||||
ConLog.Write("Elf: booting...");
|
ConLog.Write("Elf: booting...");
|
||||||
}
|
}
|
||||||
else if(wxFile::Access(elf2, wxFile::read))
|
else if(wxFile::Access(elf2, wxFile::read))
|
||||||
{
|
{
|
||||||
Emu.SetElf(elf2);
|
Emu.SetPath(elf2);
|
||||||
ConLog.Write("Elf: booting...");
|
ConLog.Write("Elf: booting...");
|
||||||
}
|
}
|
||||||
else if(wxFile::Access(self0, wxFile::read))
|
else if(wxFile::Access(self0, wxFile::read))
|
||||||
{
|
{
|
||||||
goto _ELF_NOT_FOUND_;
|
goto _ELF_NOT_FOUND_;
|
||||||
Emu.SetSelf(self0);
|
Emu.SetPath(self0);
|
||||||
ConLog.Warning("Self: booting...");
|
ConLog.Warning("Self: booting...");
|
||||||
}
|
}
|
||||||
else if(wxFile::Access(self1, wxFile::read))
|
else if(wxFile::Access(self1, wxFile::read))
|
||||||
{
|
{
|
||||||
goto _ELF_NOT_FOUND_;
|
goto _ELF_NOT_FOUND_;
|
||||||
Emu.SetSelf(self1);
|
Emu.SetPath(self1);
|
||||||
ConLog.Warning("Self: booting...");
|
ConLog.Warning("Self: booting...");
|
||||||
}
|
}
|
||||||
else if(wxFile::Access(self2, wxFile::read))
|
else if(wxFile::Access(self2, wxFile::read))
|
||||||
{
|
{
|
||||||
goto _ELF_NOT_FOUND_;
|
goto _ELF_NOT_FOUND_;
|
||||||
Emu.SetSelf(self2);
|
Emu.SetPath(self2);
|
||||||
ConLog.Warning("Self: booting...");
|
ConLog.Warning("Self: booting...");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -200,7 +199,7 @@ void MainFrame::BootElf(wxCommandEvent& WXUNUSED(event))
|
|||||||
|
|
||||||
Emu.Stop();
|
Emu.Stop();
|
||||||
|
|
||||||
Emu.SetElf(ctrl.GetPath());
|
Emu.SetPath(ctrl.GetPath());
|
||||||
Emu.Load();
|
Emu.Load();
|
||||||
|
|
||||||
ConLog.Write("Elf: boot done.");
|
ConLog.Write("Elf: boot done.");
|
||||||
@ -229,7 +228,7 @@ void MainFrame::BootSelf(wxCommandEvent& WXUNUSED(event))
|
|||||||
|
|
||||||
Emu.Stop();
|
Emu.Stop();
|
||||||
|
|
||||||
Emu.SetSelf(ctrl.GetPath());
|
Emu.SetPath(ctrl.GetPath());
|
||||||
Emu.Load();
|
Emu.Load();
|
||||||
|
|
||||||
ConLog.Write("SELF: boot done.");
|
ConLog.Write("SELF: boot done.");
|
||||||
@ -367,9 +366,79 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event))
|
|||||||
if(paused) Emu.Resume();
|
if(paused) Emu.Resume();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainFrame::UpdateUI(wxCommandEvent& WXUNUSED(event))
|
void MainFrame::UpdateUI(wxCommandEvent& event)
|
||||||
{
|
{
|
||||||
wxGetApp().m_debugger_frame->UpdateUI();
|
event.Skip();
|
||||||
|
|
||||||
|
bool is_runned, is_stopped, is_ready;
|
||||||
|
|
||||||
|
if(event.GetEventType() == wxEVT_DBG_COMMAND)
|
||||||
|
{
|
||||||
|
switch(event.GetId())
|
||||||
|
{
|
||||||
|
case DID_START_EMU:
|
||||||
|
case DID_STARTED_EMU:
|
||||||
|
is_runned = true;
|
||||||
|
is_stopped = false;
|
||||||
|
is_ready = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DID_STOP_EMU:
|
||||||
|
case DID_STOPED_EMU:
|
||||||
|
is_runned = false;
|
||||||
|
is_stopped = true;
|
||||||
|
is_ready = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DID_PAUSE_EMU:
|
||||||
|
case DID_PAUSED_EMU:
|
||||||
|
is_runned = false;
|
||||||
|
is_stopped = false;
|
||||||
|
is_ready = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DID_RESUME_EMU:
|
||||||
|
case DID_RESUMED_EMU:
|
||||||
|
is_runned = true;
|
||||||
|
is_stopped = false;
|
||||||
|
is_ready = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DID_READY_EMU:
|
||||||
|
is_runned = false;
|
||||||
|
is_stopped = false;
|
||||||
|
is_ready = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
is_runned = Emu.IsRunned();
|
||||||
|
is_stopped = Emu.IsStopped();
|
||||||
|
is_ready = Emu.IsReady();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
is_runned = Emu.IsRunned();
|
||||||
|
is_stopped = Emu.IsStopped();
|
||||||
|
is_ready = Emu.IsReady();
|
||||||
|
}
|
||||||
|
|
||||||
|
wxMenuBar& menubar( *GetMenuBar() );
|
||||||
|
wxMenuItem& pause = *menubar.FindItem( id_sys_pause );
|
||||||
|
wxMenuItem& stop = *menubar.FindItem( id_sys_stop );
|
||||||
|
wxMenuItem& send_exit = *menubar.FindItem( id_sys_send_exit );
|
||||||
|
|
||||||
|
pause.SetText(is_runned ? "Pause\tCtrl + P" : is_ready ? "Start\tCtrl + C" : "Resume\tCtrl + C");
|
||||||
|
pause.Enable(!is_stopped);
|
||||||
|
stop.Enable(!is_stopped);
|
||||||
|
//send_exit.Enable(false);
|
||||||
|
send_exit.Enable(!is_stopped && Emu.GetCallbackManager().m_exit_callback.m_callbacks.GetCount());
|
||||||
|
|
||||||
|
m_aui_mgr.Update();
|
||||||
|
|
||||||
|
//wxCommandEvent refit( wxEVT_COMMAND_MENU_SELECTED, id_update_dbg );
|
||||||
|
//GetEventHandler()->AddPendingEvent( refit );
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainFrame::OnQuit(wxCloseEvent& event)
|
void MainFrame::OnQuit(wxCloseEvent& event)
|
||||||
@ -434,22 +503,3 @@ void MainFrame::OnKeyDown(wxKeyEvent& event)
|
|||||||
|
|
||||||
event.Skip();
|
event.Skip();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainFrame::UpdateUI()
|
|
||||||
{
|
|
||||||
wxMenuBar& menubar( *GetMenuBar() );
|
|
||||||
wxMenuItem& pause = *menubar.FindItem( id_sys_pause );
|
|
||||||
wxMenuItem& stop = *menubar.FindItem( id_sys_stop );
|
|
||||||
wxMenuItem& send_exit = *menubar.FindItem( id_sys_send_exit );
|
|
||||||
|
|
||||||
pause.SetText(Emu.IsRunned() ? "Pause\tCtrl + P" : Emu.IsReady() ? "Start\tCtrl + C" : "Resume\tCtrl + C");
|
|
||||||
pause.Enable(!Emu.IsStopped());
|
|
||||||
stop.Enable(!Emu.IsStopped());
|
|
||||||
//send_exit.Enable(false);
|
|
||||||
send_exit.Enable(!Emu.IsStopped() && Emu.GetCallbackManager().m_exit_callback.m_callbacks.GetCount());
|
|
||||||
|
|
||||||
m_aui_mgr.Update();
|
|
||||||
|
|
||||||
wxCommandEvent refit( wxEVT_COMMAND_MENU_SELECTED, id_update_dbg );
|
|
||||||
GetEventHandler()->AddPendingEvent( refit );
|
|
||||||
}
|
|
@ -28,9 +28,6 @@ private:
|
|||||||
void UpdateUI(wxCommandEvent& event);
|
void UpdateUI(wxCommandEvent& event);
|
||||||
void OnKeyDown(wxKeyEvent& event);
|
void OnKeyDown(wxKeyEvent& event);
|
||||||
|
|
||||||
public:
|
|
||||||
void UpdateUI();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DECLARE_EVENT_TABLE()
|
DECLARE_EVENT_TABLE()
|
||||||
};
|
};
|
@ -1,7 +1,56 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "ELF64.h"
|
#include "ELF64.h"
|
||||||
#include "Gui/CompilerELF.h"
|
#include "Emu/Cell/PPUInstrTable.h"
|
||||||
using namespace PPU_opcodes;
|
using namespace PPU_instr;
|
||||||
|
|
||||||
|
void WriteEhdr(wxFile& f, Elf64_Ehdr& ehdr)
|
||||||
|
{
|
||||||
|
Write32(f, ehdr.e_magic);
|
||||||
|
Write8(f, ehdr.e_class);
|
||||||
|
Write8(f, ehdr.e_data);
|
||||||
|
Write8(f, ehdr.e_curver);
|
||||||
|
Write8(f, ehdr.e_os_abi);
|
||||||
|
Write64(f, ehdr.e_abi_ver);
|
||||||
|
Write16(f, ehdr.e_type);
|
||||||
|
Write16(f, ehdr.e_machine);
|
||||||
|
Write32(f, ehdr.e_version);
|
||||||
|
Write64(f, ehdr.e_entry);
|
||||||
|
Write64(f, ehdr.e_phoff);
|
||||||
|
Write64(f, ehdr.e_shoff);
|
||||||
|
Write32(f, ehdr.e_flags);
|
||||||
|
Write16(f, ehdr.e_ehsize);
|
||||||
|
Write16(f, ehdr.e_phentsize);
|
||||||
|
Write16(f, ehdr.e_phnum);
|
||||||
|
Write16(f, ehdr.e_shentsize);
|
||||||
|
Write16(f, ehdr.e_shnum);
|
||||||
|
Write16(f, ehdr.e_shstrndx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WritePhdr(wxFile& f, Elf64_Phdr& phdr)
|
||||||
|
{
|
||||||
|
Write32(f, phdr.p_type);
|
||||||
|
Write32(f, phdr.p_flags);
|
||||||
|
Write64(f, phdr.p_offset);
|
||||||
|
Write64(f, phdr.p_vaddr);
|
||||||
|
Write64(f, phdr.p_paddr);
|
||||||
|
Write64(f, phdr.p_filesz);
|
||||||
|
Write64(f, phdr.p_memsz);
|
||||||
|
Write64(f, phdr.p_align);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteShdr(wxFile& f, Elf64_Shdr& shdr)
|
||||||
|
{
|
||||||
|
Write32(f, shdr.sh_name);
|
||||||
|
Write32(f, shdr.sh_type);
|
||||||
|
Write64(f, shdr.sh_flags);
|
||||||
|
Write64(f, shdr.sh_addr);
|
||||||
|
Write64(f, shdr.sh_offset);
|
||||||
|
Write64(f, shdr.sh_size);
|
||||||
|
Write32(f, shdr.sh_link);
|
||||||
|
Write32(f, shdr.sh_info);
|
||||||
|
Write64(f, shdr.sh_addralign);
|
||||||
|
Write64(f, shdr.sh_entsize);
|
||||||
|
}
|
||||||
|
|
||||||
ELF64Loader::ELF64Loader(vfsStream& f)
|
ELF64Loader::ELF64Loader(vfsStream& f)
|
||||||
: elf64_f(f)
|
: elf64_f(f)
|
||||||
@ -326,9 +375,9 @@ bool ELF64Loader::LoadPhdrData(u64 offset)
|
|||||||
out_tbl += nid;
|
out_tbl += nid;
|
||||||
|
|
||||||
mem32_t out_dst(dst + i*section);
|
mem32_t out_dst(dst + i*section);
|
||||||
out_dst += ToOpcode(G_1f) | SetField(OR, 21, 30) | ToRA(11) | ToRS(2) | ToRB(2) | ToRC(0);
|
out_dst += OR(11, 2, 2, 0);
|
||||||
out_dst += ToOpcode(SC) | ToSYS(2);
|
out_dst += SC(2);
|
||||||
out_dst += ToOpcode(G_13) | SetField(BCLR, 21, 30) | ToBO(0x10 | 0x04) | ToBI(0) | ToLK(0);
|
out_dst += BCLR(0x10 | 0x04, 0, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef LOADER_DEBUG
|
#ifdef LOADER_DEBUG
|
||||||
|
@ -184,4 +184,8 @@ private:
|
|||||||
bool LoadShdrData(u64 offset);
|
bool LoadShdrData(u64 offset);
|
||||||
|
|
||||||
//bool LoadImports();
|
//bool LoadImports();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void WriteEhdr(wxFile& f, Elf64_Ehdr& ehdr);
|
||||||
|
void WritePhdr(wxFile& f, Elf64_Phdr& phdr);
|
||||||
|
void WriteShdr(wxFile& f, Elf64_Shdr& shdr);
|
@ -58,6 +58,30 @@ __forceinline static u64 Read64(vfsStream& f)
|
|||||||
return ((u64)Read32(f) << 32) | (u64)Read32(f);
|
return ((u64)Read32(f) << 32) | (u64)Read32(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__forceinline static void Write8(wxFile& f, const u8 data)
|
||||||
|
{
|
||||||
|
f.Write(&data, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
__forceinline static void Write16(wxFile& f, const u16 data)
|
||||||
|
{
|
||||||
|
Write8(f, data >> 8);
|
||||||
|
Write8(f, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
__forceinline static void Write32(wxFile& f, const u32 data)
|
||||||
|
{
|
||||||
|
Write16(f, data >> 16);
|
||||||
|
Write16(f, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
__forceinline static void Write64(wxFile& f, const u64 data)
|
||||||
|
{
|
||||||
|
Write32(f, data >> 32);
|
||||||
|
Write32(f, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const wxString Ehdr_DataToString(const u8 data);
|
const wxString Ehdr_DataToString(const u8 data);
|
||||||
const wxString Ehdr_TypeToString(const u16 type);
|
const wxString Ehdr_TypeToString(const u16 type);
|
||||||
const wxString Ehdr_OS_ABIToString(const u8 os_abi);
|
const wxString Ehdr_OS_ABIToString(const u8 os_abi);
|
||||||
|
@ -22,7 +22,15 @@ bool Rpcs3App::OnInit()
|
|||||||
SetTopWindow(m_MainFrame);
|
SetTopWindow(m_MainFrame);
|
||||||
Emu.Init();
|
Emu.Init();
|
||||||
|
|
||||||
(new CompilerELF(m_MainFrame))->Show();
|
try
|
||||||
|
{
|
||||||
|
(new CompilerELF(m_MainFrame))->Show();
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
ConLog.Warning("CompilerELF is broken.");
|
||||||
|
}
|
||||||
|
|
||||||
m_debugger_frame = new DebuggerPanel(m_MainFrame);
|
m_debugger_frame = new DebuggerPanel(m_MainFrame);
|
||||||
ConLogFrame = new LogFrame(m_MainFrame);
|
ConLogFrame = new LogFrame(m_MainFrame);
|
||||||
|
|
||||||
|
@ -22,17 +22,31 @@ enum DbgCommand
|
|||||||
DID_FIRST_COMMAND = 0x500,
|
DID_FIRST_COMMAND = 0x500,
|
||||||
|
|
||||||
DID_START_EMU,
|
DID_START_EMU,
|
||||||
|
DID_STARTED_EMU,
|
||||||
DID_STOP_EMU,
|
DID_STOP_EMU,
|
||||||
|
DID_STOPED_EMU,
|
||||||
DID_PAUSE_EMU,
|
DID_PAUSE_EMU,
|
||||||
|
DID_PAUSED_EMU,
|
||||||
DID_RESUME_EMU,
|
DID_RESUME_EMU,
|
||||||
|
DID_RESUMED_EMU,
|
||||||
|
DID_READY_EMU,
|
||||||
DID_CREATE_THREAD,
|
DID_CREATE_THREAD,
|
||||||
|
DID_CREATED_THREAD,
|
||||||
DID_REMOVE_THREAD,
|
DID_REMOVE_THREAD,
|
||||||
|
DID_REMOVED_THREAD,
|
||||||
DID_RENAME_THREAD,
|
DID_RENAME_THREAD,
|
||||||
|
DID_RENAMED_THREAD,
|
||||||
DID_START_THREAD,
|
DID_START_THREAD,
|
||||||
|
DID_STARTED_THREAD,
|
||||||
DID_STOP_THREAD,
|
DID_STOP_THREAD,
|
||||||
|
DID_STOPED_THREAD,
|
||||||
DID_PAUSE_THREAD,
|
DID_PAUSE_THREAD,
|
||||||
|
DID_PAUSED_THREAD,
|
||||||
DID_RESUME_THREAD,
|
DID_RESUME_THREAD,
|
||||||
|
DID_RESUMED_THREAD,
|
||||||
DID_EXEC_THREAD,
|
DID_EXEC_THREAD,
|
||||||
|
DID_REGISTRED_CALLBACK,
|
||||||
|
DID_UNREGISTRED_CALLBACK,
|
||||||
|
|
||||||
DID_LAST_COMMAND,
|
DID_LAST_COMMAND,
|
||||||
};
|
};
|
||||||
|
@ -197,6 +197,7 @@
|
|||||||
<ClCompile Include="AppConnector.cpp" />
|
<ClCompile Include="AppConnector.cpp" />
|
||||||
<ClCompile Include="Emu\Cell\PPCThread.cpp" />
|
<ClCompile Include="Emu\Cell\PPCThread.cpp" />
|
||||||
<ClCompile Include="Emu\Cell\PPCThreadManager.cpp" />
|
<ClCompile Include="Emu\Cell\PPCThreadManager.cpp" />
|
||||||
|
<ClCompile Include="Emu\Cell\PPUProgramCompiler.cpp" />
|
||||||
<ClCompile Include="Emu\Cell\PPUThread.cpp" />
|
<ClCompile Include="Emu\Cell\PPUThread.cpp" />
|
||||||
<ClCompile Include="Emu\Cell\SPUThread.cpp" />
|
<ClCompile Include="Emu\Cell\SPUThread.cpp" />
|
||||||
<ClCompile Include="Emu\DbgConsole.cpp" />
|
<ClCompile Include="Emu\DbgConsole.cpp" />
|
||||||
@ -275,13 +276,17 @@
|
|||||||
<ClInclude Include="..\Utilities\MTProgressDialog.h" />
|
<ClInclude Include="..\Utilities\MTProgressDialog.h" />
|
||||||
<ClInclude Include="..\Utilities\Thread.h" />
|
<ClInclude Include="..\Utilities\Thread.h" />
|
||||||
<ClInclude Include="..\Utilities\Timer.h" />
|
<ClInclude Include="..\Utilities\Timer.h" />
|
||||||
<ClInclude Include="Emu\Cell\DisAsm.h" />
|
<ClInclude Include="Emu\Cell\PPCDecoder.h" />
|
||||||
|
<ClInclude Include="Emu\Cell\PPCDisAsm.h" />
|
||||||
|
<ClInclude Include="Emu\Cell\PPCInstrTable.h" />
|
||||||
<ClInclude Include="Emu\Cell\PPCThread.h" />
|
<ClInclude Include="Emu\Cell\PPCThread.h" />
|
||||||
<ClInclude Include="Emu\Cell\PPCThreadManager.h" />
|
<ClInclude Include="Emu\Cell\PPCThreadManager.h" />
|
||||||
<ClInclude Include="Emu\Cell\PPUDecoder.h" />
|
<ClInclude Include="Emu\Cell\PPUDecoder.h" />
|
||||||
<ClInclude Include="Emu\Cell\PPUDisAsm.h" />
|
<ClInclude Include="Emu\Cell\PPUDisAsm.h" />
|
||||||
|
<ClInclude Include="Emu\Cell\PPUInstrTable.h" />
|
||||||
<ClInclude Include="Emu\Cell\PPUInterpreter.h" />
|
<ClInclude Include="Emu\Cell\PPUInterpreter.h" />
|
||||||
<ClInclude Include="Emu\Cell\PPUOpcodes.h" />
|
<ClInclude Include="Emu\Cell\PPUOpcodes.h" />
|
||||||
|
<ClInclude Include="Emu\Cell\PPUProgramCompiler.h" />
|
||||||
<ClInclude Include="Emu\Cell\PPUThread.h" />
|
<ClInclude Include="Emu\Cell\PPUThread.h" />
|
||||||
<ClInclude Include="Emu\Cell\SPUDecoder.h" />
|
<ClInclude Include="Emu\Cell\SPUDecoder.h" />
|
||||||
<ClInclude Include="Emu\Cell\SPUDisAsm.h" />
|
<ClInclude Include="Emu\Cell\SPUDisAsm.h" />
|
||||||
|
@ -247,6 +247,9 @@
|
|||||||
<ClCompile Include="AppConnector.cpp">
|
<ClCompile Include="AppConnector.cpp">
|
||||||
<Filter>rpcs3</Filter>
|
<Filter>rpcs3</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="Emu\Cell\PPUProgramCompiler.cpp">
|
||||||
|
<Filter>Emu\CPU</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="rpcs3.rc" />
|
<ResourceCompile Include="rpcs3.rc" />
|
||||||
@ -270,9 +273,6 @@
|
|||||||
<ClInclude Include="Emu\System.h">
|
<ClInclude Include="Emu\System.h">
|
||||||
<Filter>Include</Filter>
|
<Filter>Include</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="Emu\Cell\DisAsm.h">
|
|
||||||
<Filter>Include</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="Emu\Cell\PPCThread.h">
|
<ClInclude Include="Emu\Cell\PPCThread.h">
|
||||||
<Filter>Include</Filter>
|
<Filter>Include</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
@ -402,5 +402,20 @@
|
|||||||
<ClInclude Include="..\Utilities\Timer.h">
|
<ClInclude Include="..\Utilities\Timer.h">
|
||||||
<Filter>Utilities</Filter>
|
<Filter>Utilities</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="Emu\Cell\PPCDecoder.h">
|
||||||
|
<Filter>Include</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Emu\Cell\PPCDisAsm.h">
|
||||||
|
<Filter>Include</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Emu\Cell\PPCInstrTable.h">
|
||||||
|
<Filter>Include</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Emu\Cell\PPUInstrTable.h">
|
||||||
|
<Filter>Include</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Emu\Cell\PPUProgramCompiler.h">
|
||||||
|
<Filter>Include</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
Loading…
Reference in New Issue
Block a user