Last active
April 2, 2018 23:23
-
-
Save unknownbrackets/d01ac5cd2598e76a146e to your computer and use it in GitHub Desktop.
New, virtual function-less initial concept (untested)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "stdafx.h" | |
// Aren't these just PPC opcodes? | |
#include "Emu/Cell/PPUOpcodes.h" | |
// Design plan: | |
// Get to the interp/jit/etc. func as quick as possible. | |
// Individual interp/jit/disasm funcs should be short and direct as possible. | |
// Needs to take native byte order - too many args to win by using BE. | |
namespace PPC | |
{ | |
typedef u32 Opcode; | |
class Int { | |
public: | |
__forceinline void TDI(u32 to, u32 ra, s32 simm) | |
{ | |
// TODO | |
} | |
template <typename A0, typename A1, typename A2, void (Int::*Func)(typename A0::Type, typename A1::Type, typename A2::Type)> | |
void InstructionProxy(Opcode op) | |
{ | |
return (this->*Func)(A0::Decode(op), A1::Decode(op), A2::Decode(op)); | |
} | |
}; | |
class Comp { | |
public: | |
__forceinline void TDI(u32 to, u32 ra, s32 simm) | |
{ | |
// TODO | |
} | |
template <typename A0, typename A1, typename A2, void (Comp::*Func)(typename A0::Type, typename A1::Type, typename A2::Type)> | |
void InstructionProxy(Opcode op) | |
{ | |
return (this->*Func)(A0::Decode(op), A1::Decode(op), A2::Decode(op)); | |
} | |
}; | |
class Dis { | |
public: | |
__forceinline void TDI(u32 to, u32 ra, s32 simm) | |
{ | |
// TODO | |
} | |
template <typename A0, typename A1, typename A2, void (Dis::*Func)(typename A0::Type, typename A1::Type, typename A2::Type)> | |
void InstructionProxy(Opcode op) | |
{ | |
return (this->*Func)(A0::Decode(op), A1::Decode(op), A2::Decode(op)); | |
} | |
}; | |
// TODO: Change to class methods. | |
typedef void (Int::*InterpretFunc)(Opcode op); | |
typedef void (Comp::*CompileFunc)(Opcode op); | |
typedef void (Dis::*DisasmFunc)(Opcode op); | |
enum InstructionFlags | |
{ | |
// TODO | |
}; | |
struct Instruction; | |
inline static u8 FlipShift(u8 v) | |
{ | |
return 31 - v; | |
} | |
inline static u32 MakeMask(u8 from, u8 to) | |
{ | |
const u8 numBits = to - from + 1; | |
return (1 << numBits) - 1; | |
} | |
struct InstructionTable | |
{ | |
const u8 shift; | |
const u32 mask; | |
std::vector<Instruction> instructions; | |
// From / to in big endian order. | |
InstructionTable(u8 from, u8 to) | |
: shift(FlipShift(to)), mask(MakeMask(from, to)) | |
{ | |
// This will truncate/pad with invalid. | |
instructions.resize(mask); | |
} | |
void Add(u32 index, const Instruction &&instr); | |
const Instruction *Lookup(Opcode op) const | |
{ | |
return &instructions[(op >> shift) & mask]; | |
} | |
const Instruction *operator[](u32 index) const | |
{ | |
return &instructions[index]; | |
} | |
}; | |
struct Instruction | |
{ | |
const InstructionTable *subTable; | |
InterpretFunc interpret; | |
CompileFunc compile; | |
DisasmFunc disasm; | |
std::string name; | |
u32 flags; | |
Instruction() | |
: subTable(nullptr), interpret(nullptr), compile(nullptr), disasm(nullptr), name(), flags(0) | |
{ | |
} | |
Instruction(const Instruction &other) | |
: subTable(other.subTable), interpret(other.interpret), | |
compile(other.compile), disasm(other.disasm), name(other.name), flags(other.flags) | |
{ | |
} | |
explicit Instruction(InterpretFunc i, CompileFunc c, DisasmFunc d, const std::string &n, u32 f = 0) | |
: subTable(nullptr), interpret(i), compile(c), disasm(d), name(n), flags(f) | |
{ | |
} | |
explicit Instruction(const InstructionTable *t) | |
: subTable(t), interpret(nullptr), compile(nullptr), disasm(nullptr), name(), flags(0) | |
{ | |
} | |
}; | |
void InstructionTable::Add(u32 index, const Instruction &&instr) | |
{ | |
instructions[index] = instr; | |
} | |
inline static Instruction Invalid() | |
{ | |
return Instruction(); | |
} | |
template <typename A0, typename A1, typename A2, void (Int::*Interpret)(typename A0::Type, typename A1::Type, typename A2::Type), void (Comp::*Compile)(typename A0::Type, typename A1::Type, typename A2::Type), void (Dis::*Disasm)(typename A0::Type, typename A1::Type, typename A2::Type)> | |
inline static Instruction Instr(const std::string &n, u32 flags = 0) | |
{ | |
flags |= A0::flags | A1::flags | A2::flags; | |
const InterpretFunc interpret = &Int::InstructionProxy<A0, A1, A2, Interpret>; | |
// TODO: Hmm, this will be more complicated as a method... | |
const CompileFunc compile = &Comp::InstructionProxy<A0, A1, A2, Compile>; | |
const DisasmFunc disasm = &Dis::InstructionProxy<A0, A1, A2, Disasm>; | |
return Instruction(interpret, compile, disasm, n, flags); | |
} | |
template <u8 from, u8 to, u32 flags = 0> | |
struct CodeField | |
{ | |
static const u32 size = to - from + 1; | |
static const u32 shift = 31 - to; | |
static const u32 mask = (1 << (to - from + 1)) - 1; | |
static const u32 flags = flags; | |
typedef u32 Type; | |
static Type Decode(Opcode data) | |
{ | |
return (data >> shift) & mask; | |
} | |
}; | |
template <u8 from, u8 to, u32 flags = 0> | |
struct CodeFieldSigned : public CodeField<from, to, flags> | |
{ | |
typedef s32 Type; | |
static Type Decode(Opcode data) | |
{ | |
u32 uval = CodeField<from, to, flags>::Decode(data); | |
// If it's negative, fill all the sign bits. | |
if (uval & (1 << size)) | |
uval |= 0xFFFFFFFF << size; | |
return uval; | |
} | |
}; | |
typedef CodeField<6, 10> TO; | |
typedef CodeField<11, 15> RA; | |
typedef CodeField<16, 31> uimm16; | |
typedef CodeFieldSigned<16, 31> simm16; | |
struct MainInstructionTable : public InstructionTable | |
{ | |
MainInstructionTable(); | |
}; | |
static const MainInstructionTable mainTable; | |
#define INSTR(name, ...) Add(PPU_opcodes::name, Instr<##__VA_ARGS__, &Int::name, &Comp::name, &Dis::name>(#name)) | |
#define TABLE(index, list) Add(PPU_opcodes::index, Instruction(list)) | |
MainInstructionTable::MainInstructionTable() : InstructionTable(0, 5) | |
{ | |
INSTR(TDI, TO, RA, simm16); | |
} | |
#undef INSTR | |
#undef TABLE | |
Instruction GetInstruction(Opcode op) | |
{ | |
// Hardcoded the first shift for speed. See mainTable. | |
const Instruction *instr = mainTable[op >> (31 - 5)]; | |
while (instr->subTable) | |
instr = instr->subTable->Lookup(op); | |
return *instr; | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment