Remove global state from PPCAnalyst.cpp. Little bit of cleanup.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@1580 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
hrydgard 2008-12-18 10:44:03 +00:00
parent feb8dc7e6b
commit 50d72c1e59
9 changed files with 170 additions and 329 deletions

View File

@ -45,7 +45,6 @@ namespace HW
void Init()
{
CoreTiming::Init();
PPCAnalyst::Init();
Thunk_Init(); // not really hw, but this way we know it's inited early :P
State_Init();
@ -91,7 +90,6 @@ namespace HW
State_Shutdown();
Thunk_Shutdown();
CoreTiming::Shutdown();
PPCAnalyst::Shutdown();
}
void DoState(PointerWrap &p)

View File

@ -172,6 +172,7 @@ namespace Jit64
{
JitState js;
JitOptions jo;
PPCAnalyst::CodeBuffer code_buffer(32000);
void Init()
{
@ -319,7 +320,10 @@ namespace Jit64
//Analyze the block, collect all instructions it is made of (including inlining,
//if that is enabled), reorder instructions for optimal performance, and join joinable instructions.
PPCAnalyst::CodeOp *ops = PPCAnalyst::Flatten(emaddress, size, js.st, js.gpa, js.fpa);
PPCAnalyst::Flatten(emaddress, &size, &js.st, &js.gpa, &js.fpa, &code_buffer);
PPCAnalyst::CodeOp *ops = code_buffer.codebuffer;
const u8 *start = AlignCode4(); //TODO: Test if this or AlignCode16 make a difference from GetCodePtr
b.checkedEntry = start;
b.runCount = 0;

View File

@ -21,6 +21,7 @@
// dependency is a little inconvenient and this is possibly a slight
// performance hit, it's not enabled by default, but it's useful for
// locating performance issues.
//#define OPROFILE_REPORT
#include <map>
@ -71,10 +72,10 @@ namespace Jit64
TRAMPOLINE_SIZE = 1024*1024,
//MAX_NUM_BLOCKS = 65536,
};
int CODE_SIZE = 1024*1024*16; // nonconstant to be able to have an option for it
int CODE_SIZE = 1024*1024*16;
int MAX_NUM_BLOCKS = 65536*2;
static u8 **blockCodePointers; // cut these in half and force below 2GB?
static u8 **blockCodePointers;
static std::multimap<u32, int> links_to;
@ -133,8 +134,8 @@ namespace Jit64
#endif
}
/* This clears the JIT cache. It's called from JitCache.cpp when the JIT cache
is full and when saving and loading states */
// This clears the JIT cache. It's called from JitCache.cpp when the JIT cache
// is full and when saving and loading states.
void ClearCache()
{
Core::DisplayMessage("Cleared code cache.", 3000);
@ -348,13 +349,6 @@ namespace Jit64
}
}
/*
if ((b.exitAddress[0] == INVALID_EXIT || b.linkStatus[0]) &&
(b.exitAddress[1] == INVALID_EXIT || b.linkStatus[1])) {
unlinked.erase(iter);
if (unlinked.size() > 4000) PanicAlert("Removed from unlinked. Size = %i", unlinked.size());
}
*/
using namespace std;
void LinkBlock(int i)
{
@ -408,7 +402,6 @@ namespace Jit64
SetCodePtr(prev_code); // reset code pointer
}
#define BLR_OP 0x4e800020
void InvalidateCodeRange(u32 address, u32 length)
{
@ -418,7 +411,7 @@ namespace Jit64
//This is slow but should be safe (zelda needs it for block linking)
for (int i = 0; i < numBlocks; i++)
{
if (RangeIntersect(blocks[i].originalAddress, blocks[i].originalAddress+blocks[i].originalSize,
if (RangeIntersect(blocks[i].originalAddress, blocks[i].originalAddress + blocks[i].originalSize,
address, address + length))
{
DestroyBlock(i, true);

View File

@ -278,6 +278,10 @@ void stfs(UGeckoInstruction inst)
void stfsx(UGeckoInstruction inst)
{
#ifdef JIT_OFF_OPTIONS
if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITLoadStoreFloatingOff)
{Default(inst); return;} // turn off from debugger
#endif
// We can take a shortcut here - it's not likely that a hardware access would use this instruction.
INSTRUCTION_START;
#ifdef _M_X64

View File

@ -182,7 +182,7 @@ void psq_st(UGeckoInstruction inst)
{
if (gpr.R(a).IsImm() && !update && cpu_info.bSSSE3)
{
u32 addr = gpr.R(a).offset + offset;
u32 addr = (u32)(gpr.R(a).offset + offset);
if (addr == 0xCC008000) {
// Writing to FIFO. Let's do fast method.
CVTPD2PS(XMM0, fpr.R(s));

View File

@ -40,30 +40,24 @@ namespace PPCAnalyst {
using namespace std;
PPCAnalyst::CodeOp *codebuffer;
enum
{
CODEBUFFER_SIZE = 32000,
};
void Init()
CodeBuffer::CodeBuffer(int size)
{
codebuffer = new PPCAnalyst::CodeOp[CODEBUFFER_SIZE];
codebuffer = new PPCAnalyst::CodeOp[size];
}
void Shutdown()
CodeBuffer::~CodeBuffer()
{
delete [] codebuffer;
}
void AnalyzeFunction2(Symbol &func);
u32 EvaluateBranchTarget(UGeckoInstruction instr, u32 pc);
// void FixUpInternalBranches(CodeOp *code, int begin, int end);
#define INVALID_TARGET ((u32)-1)
u32 EvaluateBranchTarget(UGeckoInstruction instr, u32 pc)
@ -206,34 +200,14 @@ bool AnalyzeFunction(u32 startAddr, Symbol &func, int max_size)
// Second pass analysis, done after the first pass is done for all functions
// so we have more information to work with
void AnalyzeFunction2(Symbol &func)
void AnalyzeFunction2(Symbol *func)
{
// u32 addr = func.address;
u32 flags = func.flags;
/*
for (int i = 0; i < func.size; i++)
{
UGeckoInstruction instr = (UGeckoInstruction)Memory::ReadUnchecked_U32(addr);
GekkoOPInfo *info = GetOpInfo(instr);
if (!info)
{
LOG(HLE,"Seems function %s contains bad op %08x",func.name,instr);
}
else
{
if (info->flags & FL_TIMER)
{
flags |= FFLAG_TIMERINSTRUCTIONS;
}
}
addr+=4;
}*/
u32 flags = func->flags;
bool nonleafcall = false;
for (size_t i = 0; i < func.calls.size(); i++)
for (size_t i = 0; i < func->calls.size(); i++)
{
SCall c = func.calls[i];
SCall c = func->calls[i];
Symbol *called_func = g_symbolDB.GetSymbolFromAddr(c.function);
if (called_func && (called_func->flags & FFLAG_LEAF) == 0)
{
@ -245,44 +219,7 @@ void AnalyzeFunction2(Symbol &func)
if (nonleafcall && !(flags & FFLAG_EVIL) && !(flags & FFLAG_RFI))
flags |= FFLAG_ONLYCALLSNICELEAFS;
func.flags = flags;
}
// Currently not used
void FixUpInternalBranches(CodeOp *code, int begin, int end)
{
for (int i = begin; i < end; i++)
{
if (code[i].branchTo != INVALID_TARGET) //check if this branch already processed
{
if (code[i].inst.OPCD == 16)
{
u32 target = SignExt16(code[i].inst.BD<<2);
if (!code[i].inst.AA)
target += code[i].address;
//local branch
code[i].branchTo = target;
}
else
code[i].branchTo = INVALID_TARGET;
}
}
//brute force
for (int i = begin; i < end; i++)
{
if (code[i].branchTo != INVALID_TARGET)
{
bool found = false;
for (int j = begin; j < end; j++)
if (code[i].branchTo == code[j].address)
code[i].branchToIndex = j;
if (!found)
{
LOG(HLE, "ERROR: branch target missing");
}
}
}
func->flags = flags;
}
// IMPORTANT - CURRENTLY ASSUMES THAT A IS A COMPARE
@ -346,138 +283,92 @@ bool CanSwapAdjacentOps(const CodeOp &a, const CodeOp &b)
}
// Does not yet perform inlining - although there are plans for that.
CodeOp *Flatten(u32 address, int &realsize, BlockStats &st, BlockRegStats &gpa, BlockRegStats &fpa)
void Flatten(u32 address, int *realsize, BlockStats *st, BlockRegStats *gpa, BlockRegStats *fpa, CodeBuffer *buffer)
{
int numCycles = 0;
u32 blockstart = address;
memset(&st, 0, sizeof(st));
UGeckoInstruction previnst = Memory::Read_Instruction(address-4);
memset(st, 0, sizeof(st));
UGeckoInstruction previnst = Memory::Read_Instruction(address - 4);
if (previnst.hex == 0x4e800020)
{
st.isFirstBlockOfFunction = true;
st->isFirstBlockOfFunction = true;
}
gpa->any = true;
fpa->any = false;
gpa.any = true;
fpa.any = false;
enum Todo
{
JustCopy = 0, Flatten = 1, Nothing = 2
};
Todo todo = Nothing;
//Symbol *f = g_symbolDB.GetSymbolFromAddr(address);
int maxsize = CODEBUFFER_SIZE;
//for now, all will return JustCopy :P
/*
if (f)
int num_inst = 0;
int numFollows = 0;
CodeOp *code = buffer->codebuffer;
bool foundExit = false;
// Flatten! (Currently just copies, following branches is disabled)
for (int i = 0; i < maxsize; i++, num_inst++)
{
if (f->flags & FFLAG_LEAF)
memset(&code[i], 0, sizeof(CodeOp));
code[i].address = address;
UGeckoInstruction inst = Memory::Read_Instruction(code[i].address);
_assert_msg_(GEKKO, inst.hex != 0, "Zero Op - Error flattening %08x op %08x", address + i*4, inst);
code[i].inst = inst;
code[i].branchTo = -1;
code[i].branchToIndex = -1;
GekkoOPInfo *opinfo = GetOpInfo(inst);
if (opinfo)
numCycles += opinfo->numCyclesMinusOne + 1;
_assert_msg_(GEKKO, opinfo != 0, "Invalid Op - Error flattening %08x op %08x", address + i*4, inst);
bool follow = false;
u32 destination;
if (inst.OPCD == 18)
{
//no reason to flatten
todo = JustCopy;
//Is bx - should we inline? yes!
if (inst.AA)
destination = SignExt26(inst.LI << 2);
else
destination = address + SignExt26(inst.LI << 2);
if (destination != blockstart)
follow = true;
}
else if (f->flags & FFLAG_ONLYCALLSNICELEAFS)
if (follow)
numFollows++;
if (numFollows > 1)
follow = false;
follow = false;
if (!follow)
{
//inline calls if possible
//todo = Flatten;
todo = JustCopy;
if (opinfo->flags & FL_ENDBLOCK) //right now we stop early
{
foundExit = true;
break;
}
address += 4;
}
else
{
todo = JustCopy;
address = destination;
}
todo = JustCopy;
maxsize = f->size;
}
else*/
todo = JustCopy;
CodeOp *code = codebuffer; //new CodeOp[size];
if (todo == JustCopy)
{
realsize = 0;
bool foundExit = false;
int numFollows = 0;
for (int i = 0; i < maxsize; i++, realsize++)
{
memset(&code[i], 0, sizeof(CodeOp));
code[i].address = address;
UGeckoInstruction inst = Memory::Read_Instruction(code[i].address);
_assert_msg_(GEKKO, inst.hex != 0, "Zero Op - Error flattening %08x op %08x",address+i*4,inst);
code[i].inst = inst;
code[i].branchTo = -1;
code[i].branchToIndex = -1;
GekkoOPInfo *opinfo = GetOpInfo(inst);
if (opinfo)
numCycles += opinfo->numCyclesMinusOne + 1;
_assert_msg_(GEKKO, opinfo != 0, "Invalid Op - Error flattening %08x op %08x",address+i*4,inst);
int flags = opinfo->flags;
bool follow = false;
u32 destination;
if (inst.OPCD == 18)
{
//Is bx - should we inline? yes!
if (inst.AA)
destination = SignExt26(inst.LI << 2);
else
destination = address + SignExt26(inst.LI << 2);
if (destination != blockstart)
follow = true;
}
if (follow)
numFollows++;
if (numFollows > 1)
follow = false;
follow = false;
if (!follow)
{
if (flags & FL_ENDBLOCK) //right now we stop early
{
foundExit = true;
break;
}
address += 4;
}
else
{
address = destination;
}
}
_assert_msg_(GEKKO,foundExit,"Analyzer ERROR - Function %08x too big", blockstart);
realsize++;
st.numCycles = numCycles;
FixUpInternalBranches(code,0,realsize);
}
else if (todo == Flatten)
{
return 0;
}
else
{
return 0;
}
_assert_msg_(GEKKO, foundExit, "Analyzer ERROR - Function %08x too big", blockstart);
num_inst++; // why?
st->numCycles = numCycles;
// Do analysis of the code, look for dependencies etc
int numSystemInstructions = 0;
for (int i = 0; i < 32; i++)
{
gpa.firstRead[i] = -1;
gpa.firstWrite[i] = -1;
gpa.numReads[i] = 0;
gpa.numWrites[i] = 0;
gpa->firstRead[i] = -1;
gpa->firstWrite[i] = -1;
gpa->numReads[i] = 0;
gpa->numWrites[i] = 0;
}
gpa.any = true;
for (size_t i = 0; i < realsize; i++)
gpa->any = true;
for (size_t i = 0; i < num_inst; i++)
{
UGeckoInstruction inst = code[i].inst;
if (PPCTables::UsesFPU(inst))
fpa.any = true;
fpa->any = true;
code[i].wantsCR0 = false;
code[i].wantsCR1 = false;
@ -488,7 +379,7 @@ CodeOp *Flatten(u32 address, int &realsize, BlockStats &st, BlockRegStats &gpa,
int flags = opinfo->flags;
if (flags & FL_TIMER)
gpa.anyTimer = true;
gpa->anyTimer = true;
// Does the instruction output CR0?
if (flags & FL_RC_BIT)
@ -521,37 +412,37 @@ CodeOp *Flatten(u32 address, int &realsize, BlockStats &st, BlockRegStats &gpa,
if (flags & FL_OUT_A)
{
code[i].regsOut[numOut++] = inst.RA;
gpa.numWrites[inst.RA]++;
gpa->numWrites[inst.RA]++;
}
if (flags & FL_OUT_D)
{
code[i].regsOut[numOut++] = inst.RD;
gpa.numWrites[inst.RD]++;
gpa->numWrites[inst.RD]++;
}
if (flags & FL_OUT_S)
{
code[i].regsOut[numOut++] = inst.RS;
gpa.numWrites[inst.RS]++;
gpa->numWrites[inst.RS]++;
}
if ((flags & FL_IN_A) || ((flags & FL_IN_A0) && inst.RA != 0))
{
code[i].regsIn[numIn++] = inst.RA;
gpa.numReads[inst.RA]++;
gpa->numReads[inst.RA]++;
}
if (flags & FL_IN_B)
{
code[i].regsIn[numIn++] = inst.RB;
gpa.numReads[inst.RB]++;
gpa->numReads[inst.RB]++;
}
if (flags & FL_IN_C)
{
code[i].regsIn[numIn++] = inst.RC;
gpa.numReads[inst.RC]++;
gpa->numReads[inst.RC]++;
}
if (flags & FL_IN_S)
{
code[i].regsIn[numIn++] = inst.RS;
gpa.numReads[inst.RS]++;
gpa->numReads[inst.RS]++;
}
switch (opinfo->type)
@ -583,10 +474,10 @@ CodeOp *Flatten(u32 address, int &realsize, BlockStats &st, BlockRegStats &gpa,
int r = code[i].regsIn[j];
if (r < 0 || r > 31)
PanicAlert("wtf");
if (gpa.firstRead[r] == -1)
gpa.firstRead[r] = (short)(i);
gpa.lastRead[r] = (short)(i);
gpa.numReads[r]++;
if (gpa->firstRead[r] == -1)
gpa->firstRead[r] = (short)(i);
gpa->lastRead[r] = (short)(i);
gpa->numReads[r]++;
}
for (int j = 0; j < numOut; j++)
@ -594,18 +485,18 @@ CodeOp *Flatten(u32 address, int &realsize, BlockStats &st, BlockRegStats &gpa,
int r = code[i].regsOut[j];
if (r < 0 || r > 31)
PanicAlert("wtf");
if (gpa.firstWrite[r] == -1)
gpa.firstWrite[r] = (short)(i);
gpa.lastWrite[r] = (short)(i);
gpa.numWrites[r]++;
if (gpa->firstWrite[r] == -1)
gpa->firstWrite[r] = (short)(i);
gpa->lastWrite[r] = (short)(i);
gpa->numWrites[r]++;
}
}
// Instruction Reordering Pass
// Bubble down compares towards branches, so that they can be merged (merging not yet implemented).
// Bubble down compares towards branches, so that they can be merged.
// -2: -1 for the pair, -1 for not swapping with the final instruction which is probably the branch.
for (int i = 0; i < (realsize - 2); i++)
for (int i = 0; i < num_inst - 2; i++)
{
CodeOp &a = code[i];
CodeOp &b = code[i + 1];
@ -628,7 +519,7 @@ CodeOp *Flatten(u32 address, int &realsize, BlockStats &st, BlockRegStats &gpa,
bool wantsCR0 = true;
bool wantsCR1 = true;
bool wantsPS1 = true;
for (int i = realsize - 1; i; i--)
for (int i = num_inst - 1; i; i--)
{
if (code[i].outputCR0)
wantsCR0 = false;
@ -644,40 +535,11 @@ CodeOp *Flatten(u32 address, int &realsize, BlockStats &st, BlockRegStats &gpa,
code[i].wantsPS1 = wantsPS1;
}
// Time for code shuffling, taking into account the above dependency analysis.
bool successful_shuffle = false;
//Move compares
// Try to push compares as close as possible to the following branch
// this way we can do neat stuff like combining compare and branch
// and avoid emitting any cr flags at all
/*
*
pseudo:
if (op is cmp and sets CR0)
{
scan forward for branch
if we hit any instruction that sets CR0, bail
if we hit any instruction that writes to any of the cmp input variables, bail
shuffleup(code, cmpaddr, branchaddr-1)
}
how to merge:
if (op is cmp and nextop is condbranch)
{
check if nextnextop wants cr
if it does, bail (or merge and write cr)
else merge!
}
*/
if (successful_shuffle) {
// Disasm before and after, display side by side
}
// Decide what regs to potentially regcache
return code;
*realsize = num_inst;
// ...
}
// Most functions that are relevant to analyze should be
// called by another function. Therefore, let's scan the
// entire space for bl operations and find what functions
@ -759,9 +621,9 @@ void FindFunctions(u32 startAddr, u32 endAddr, SymbolDB *func_db)
LOG(HLE, "weird function");
continue;
}
AnalyzeFunction2(iter->second);
AnalyzeFunction2(&(iter->second));
Symbol &f = iter->second;
if (f.name.substr(0,3) == "zzz")
if (f.name.substr(0, 3) == "zzz")
{
if (f.flags & FFLAG_LEAF)
f.name += "_leaf";
@ -810,46 +672,4 @@ void FindFunctions(u32 startAddr, u32 endAddr, SymbolDB *func_db)
LOG(HLE, "Average size: %i (leaf), %i (nice), %i(unnice)", leafSize, niceSize, unniceSize);
}
/*
void AnalyzeBackwards()
{
#ifndef BWLINKS
return;
#else
for (int i=0; i<numEntries; i++)
{
u32 ptr = entries[i].vaddress;
if (ptr && entries[i].type == ST_FUNCTION)
{
for (int a = 0; a<entries[i].size/4; a++)
{
u32 inst = Memory::ReadUnchecked_U32(ptr);
switch (inst >> 26)
{
case 18:
if (LK) //LK
{
u32 addr;
if(AA)
addr = SignExt26(LI << 2);
else
addr = ptr + SignExt26(LI << 2);
int funNum = GetSymbolNum(addr);
if (funNum>=0)
entries[funNum].backwardLinks.push_back(ptr);
}
break;
default:
;
}
ptr+=4;
}
}
}
#endif
}
*/
} // namespace

View File

@ -76,13 +76,20 @@ struct BlockRegStats
min(firstRead[reg], firstWrite[reg]);}
};
void Init();
void Shutdown();
CodeOp *Flatten(u32 address, int &realsize, BlockStats &st, BlockRegStats &gpa, BlockRegStats &fpa);
class CodeBuffer
{
public:
CodeBuffer(int size);
~CodeBuffer();
PPCAnalyst::CodeOp *codebuffer;
int size_;
};
void Flatten(u32 address, int *realsize, BlockStats *st, BlockRegStats *gpa, BlockRegStats *fpa, CodeBuffer *buffer);
void LogFunctionCall(u32 addr);
void FindFunctions(u32 startAddr, u32 endAddr, SymbolDB *func_db);
bool AnalyzeFunction(u32 startAddr, Symbol &func, int max_size = 0);

View File

@ -122,8 +122,7 @@ Interpreter::_interpreterInstruction GetInterpreterOp(UGeckoInstruction _inst)
}
}
GekkoOPTemplate primarytable[] =
static GekkoOPTemplate primarytable[] =
{
{4, Interpreter::RunTable4, DynaRunTable4, {"RunTable4", OPTYPE_SUBTABLE | (4<<24), 0}},
{19, Interpreter::RunTable19, DynaRunTable19, {"RunTable19", OPTYPE_SUBTABLE | (19<<24), 0}},
@ -204,7 +203,7 @@ GekkoOPTemplate primarytable[] =
{58, Interpreter::unknown_instruction, Jit64::Default, {"unknown_instruction", OPTYPE_UNKNOWN, 0}},
};
GekkoOPTemplate table4[] =
static GekkoOPTemplate table4[] =
{ //SUBOP10
{0, Interpreter::ps_cmpu0, Jit64::Default, {"ps_cmpu0", OPTYPE_PS, FL_SET_CRn}},
{32, Interpreter::ps_cmpo0, Jit64::Default, {"ps_cmpo0", OPTYPE_PS, FL_SET_CRn}},
@ -222,7 +221,7 @@ GekkoOPTemplate table4[] =
{1014, Interpreter::dcbz_l, Jit64::Default, {"dcbz_l", OPTYPE_SYSTEM, 0}},
};
GekkoOPTemplate table4_2[] =
static GekkoOPTemplate table4_2[] =
{
{10, Interpreter::ps_sum0, Jit64::ps_sum, {"ps_sum0", OPTYPE_PS, 0}},
{11, Interpreter::ps_sum1, Jit64::ps_sum, {"ps_sum1", OPTYPE_PS, 0}},
@ -244,7 +243,7 @@ GekkoOPTemplate table4_2[] =
};
GekkoOPTemplate table4_3[] =
static GekkoOPTemplate table4_3[] =
{
{6, Interpreter::psq_lx, Jit64::Default, {"psq_lx", OPTYPE_PS, 0}},
{7, Interpreter::psq_stx, Jit64::Default, {"psq_stx", OPTYPE_PS, 0}},
@ -252,7 +251,7 @@ GekkoOPTemplate table4_3[] =
{39, Interpreter::psq_stux, Jit64::Default, {"psq_stux", OPTYPE_PS, 0}},
};
GekkoOPTemplate table19[] =
static GekkoOPTemplate table19[] =
{
{528, Interpreter::bcctrx, Jit64::bcctrx, {"bcctrx", OPTYPE_BRANCH, FL_ENDBLOCK}},
{16, Interpreter::bclrx, Jit64::bclrx, {"bclrx", OPTYPE_BRANCH, FL_ENDBLOCK}},
@ -273,7 +272,7 @@ GekkoOPTemplate table19[] =
};
GekkoOPTemplate table31[] =
static GekkoOPTemplate table31[] =
{
{28, Interpreter::andx, Jit64::andx, {"andx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
{60, Interpreter::andcx, Jit64::Default, {"andcx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
@ -386,7 +385,7 @@ GekkoOPTemplate table31[] =
{566, Interpreter::tlbsync, Jit64::Default, {"tlbsync", OPTYPE_SYSTEM, 0}},
};
GekkoOPTemplate table31_2[] =
static GekkoOPTemplate table31_2[] =
{
{266, Interpreter::addx, Jit64::addx, {"addx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT}},
{10, Interpreter::addcx, Jit64::Default, {"addcx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_SET_CA | FL_RC_BIT}},
@ -406,7 +405,7 @@ GekkoOPTemplate table31_2[] =
{200, Interpreter::subfzex, Jit64::Default, {"subfzex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}},
};
GekkoOPTemplate table59[] =
static GekkoOPTemplate table59[] =
{
{18, Interpreter::fdivsx, Jit64::fp_arith_s, {"fdivsx", OPTYPE_FPU, FL_RC_BIT_F, 16}},
{20, Interpreter::fsubsx, Jit64::fp_arith_s, {"fsubsx", OPTYPE_FPU, FL_RC_BIT_F}},
@ -420,7 +419,7 @@ GekkoOPTemplate table59[] =
{31, Interpreter::fnmaddsx, Jit64::fmaddXX, {"fnmaddsx", OPTYPE_FPU, FL_RC_BIT_F}},
};
GekkoOPTemplate table63[] =
static GekkoOPTemplate table63[] =
{
{264, Interpreter::fabsx, Jit64::Default, {"fabsx", OPTYPE_FPU, FL_RC_BIT_F}},
{32, Interpreter::fcmpo, Jit64::fcmpx, {"fcmpo", OPTYPE_FPU, FL_RC_BIT_F}},
@ -440,7 +439,7 @@ GekkoOPTemplate table63[] =
{711, Interpreter::mtfsfx, Jit64::Default, {"mtfsfx", OPTYPE_SYSTEMFP, 0, 2}},
};
GekkoOPTemplate table63_2[] =
static GekkoOPTemplate table63_2[] =
{
{18, Interpreter::fdivx, Jit64::Default, {"fdivx", OPTYPE_FPU, FL_RC_BIT_F, 30}},
{20, Interpreter::fsubx, Jit64::Default, {"fsubx", OPTYPE_FPU, FL_RC_BIT_F}},
@ -455,7 +454,10 @@ GekkoOPTemplate table63_2[] =
{31, Interpreter::fnmaddx, Jit64::fmaddXX, {"fnmaddx", OPTYPE_FPU, FL_RC_BIT_F}},
};
bool PPCTables::UsesFPU(UGeckoInstruction _inst)
namespace PPCTables
{
bool UsesFPU(UGeckoInstruction _inst)
{
switch (_inst.OPCD)
{
@ -500,7 +502,7 @@ bool PPCTables::UsesFPU(UGeckoInstruction _inst)
}
}
void PPCTables::InitTables()
void InitTables()
{
//clear
for (int i = 0; i < 32; i++)
@ -671,31 +673,30 @@ void PPCTables::CompileInstruction(UGeckoInstruction _inst)
}
}
bool PPCTables::IsValidInstruction(UGeckoInstruction _instCode)
bool IsValidInstruction(UGeckoInstruction _instCode)
{
const GekkoOPInfo *info = GetOpInfo(_instCode);
return info != 0;
}
void PPCTables::CountInstruction(UGeckoInstruction _inst)
void CountInstruction(UGeckoInstruction _inst)
{
GekkoOPInfo *info = GetOpInfo(_inst);
if (info)
info->runCount++;
}
struct inf
void PrintInstructionRunCounts()
{
const char *name;
int count;
bool operator < (const inf &o) const
struct inf
{
return count > o.count;
}
};
void PPCTables::PrintInstructionRunCounts()
{
const char *name;
int count;
bool operator < (const inf &o) const
{
return count > o.count;
}
};
std::vector<inf> temp;
for (int i = 0; i < m_numInstructions; i++)
{
@ -712,7 +713,7 @@ void PPCTables::PrintInstructionRunCounts()
}
//TODO move to LogManager
void PPCTables::LogCompiledInstructions()
void LogCompiledInstructions()
{
static int time = 0;
FILE *f = fopen(StringFromFormat(FULL_LOGS_DIR "inst_log%i.txt", time).c_str(), "w");
@ -740,3 +741,5 @@ void PPCTables::LogCompiledInstructions()
#endif
time++;
}
} // namespace

View File

@ -71,6 +71,18 @@ enum
OPTYPE_UNKNOWN ,
};
enum {
OPCD_HLEFUNCTION = 1,
OPCD_COMPILEDBLOCK = 2,
OPCD_BCx = 16,
OPCD_SC = 17,
OPCD_Bx = 18,
};
enum {
OP_BLR = 0x4e800020,
};
struct GekkoOPInfo
{
const char *opname;
@ -85,21 +97,21 @@ struct GekkoOPInfo
GekkoOPInfo *GetOpInfo(UGeckoInstruction _inst);
Interpreter::_interpreterInstruction GetInterpreterOp(UGeckoInstruction _inst);
class PPCTables
namespace PPCTables
{
public:
typedef void (*_recompilerInstruction) (UGeckoInstruction instCode);
typedef void (*_interpreterInstruction)(UGeckoInstruction instCode);
static void InitTables();
static bool IsValidInstruction(UGeckoInstruction _instCode);
static bool UsesFPU(UGeckoInstruction _inst);
typedef void (*_recompilerInstruction) (UGeckoInstruction instCode);
typedef void (*_interpreterInstruction)(UGeckoInstruction instCode);
static void CountInstruction(UGeckoInstruction _inst);
static void PrintInstructionRunCounts();
static void LogCompiledInstructions();
void InitTables();
bool IsValidInstruction(UGeckoInstruction _instCode);
bool UsesFPU(UGeckoInstruction _inst);
static void CompileInstruction(UGeckoInstruction _inst);
};
void CountInstruction(UGeckoInstruction _inst);
void PrintInstructionRunCounts();
void LogCompiledInstructions();
void CompileInstruction(UGeckoInstruction _inst);
} // namespace
#endif