2013-04-17 22:43:11 -04:00
|
|
|
// Copyright 2013 Dolphin Emulator Project
|
|
|
|
// Licensed under GPLv2
|
|
|
|
// Refer to the license.txt file included.
|
2008-12-08 04:46:09 +00:00
|
|
|
|
2014-02-10 13:54:46 -05:00
|
|
|
#pragma once
|
2008-12-08 04:46:09 +00:00
|
|
|
|
2013-10-26 18:04:00 -07:00
|
|
|
#include <algorithm>
|
2013-10-17 00:32:18 -04:00
|
|
|
#include <cstdlib>
|
2014-02-17 05:18:15 -05:00
|
|
|
#include <map>
|
2008-12-08 04:46:09 +00:00
|
|
|
#include <string>
|
2014-02-17 05:18:15 -05:00
|
|
|
#include <vector>
|
2008-12-08 04:46:09 +00:00
|
|
|
|
2014-02-17 05:18:15 -05:00
|
|
|
#include "Common/Common.h"
|
|
|
|
#include "Core/PowerPC/PPCTables.h"
|
2008-12-08 04:46:09 +00:00
|
|
|
|
2009-06-21 08:39:21 +00:00
|
|
|
class PPCSymbolDB;
|
2008-12-08 04:46:09 +00:00
|
|
|
struct Symbol;
|
|
|
|
|
|
|
|
namespace PPCAnalyst
|
|
|
|
{
|
|
|
|
|
|
|
|
struct CodeOp //16B
|
|
|
|
{
|
|
|
|
UGeckoInstruction inst;
|
2010-07-23 19:30:00 +00:00
|
|
|
GekkoOPInfo * opinfo;
|
2008-12-08 04:46:09 +00:00
|
|
|
u32 address;
|
|
|
|
u32 branchTo; //if 0, not a branch
|
|
|
|
int branchToIndex; //index of target block
|
|
|
|
s8 regsOut[2];
|
|
|
|
s8 regsIn[3];
|
|
|
|
s8 fregOut;
|
|
|
|
s8 fregsIn[3];
|
|
|
|
bool isBranchTarget;
|
|
|
|
bool wantsCR0;
|
|
|
|
bool wantsCR1;
|
|
|
|
bool wantsPS1;
|
|
|
|
bool outputCR0;
|
|
|
|
bool outputCR1;
|
|
|
|
bool outputPS1;
|
2008-12-20 11:20:47 +00:00
|
|
|
bool skip; // followed BL-s for example
|
2008-12-08 04:46:09 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct BlockStats
|
|
|
|
{
|
|
|
|
bool isFirstBlockOfFunction;
|
|
|
|
bool isLastBlockOfFunction;
|
|
|
|
int numCycles;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct BlockRegStats
|
|
|
|
{
|
|
|
|
short firstRead[32];
|
|
|
|
short firstWrite[32];
|
|
|
|
short lastRead[32];
|
|
|
|
short lastWrite[32];
|
|
|
|
short numReads[32];
|
|
|
|
short numWrites[32];
|
|
|
|
|
|
|
|
bool any;
|
|
|
|
bool anyTimer;
|
|
|
|
|
|
|
|
int GetTotalNumAccesses(int reg) {return numReads[reg] + numWrites[reg];}
|
|
|
|
int GetUseRange(int reg) {
|
2013-10-29 01:23:17 -04:00
|
|
|
return std::max(lastRead[reg], lastWrite[reg]) -
|
2013-10-17 00:32:18 -04:00
|
|
|
std::min(firstRead[reg], firstWrite[reg]);}
|
2010-07-25 19:01:32 +00:00
|
|
|
|
|
|
|
inline void SetInputRegister(int reg, short opindex) {
|
|
|
|
if (firstRead[reg] == -1)
|
|
|
|
firstRead[reg] = (short)(opindex);
|
|
|
|
lastRead[reg] = (short)(opindex);
|
|
|
|
numReads[reg]++;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void SetOutputRegister(int reg, short opindex) {
|
|
|
|
if (firstWrite[reg] == -1)
|
|
|
|
firstWrite[reg] = (short)(opindex);
|
|
|
|
lastWrite[reg] = (short)(opindex);
|
|
|
|
numWrites[reg]++;
|
|
|
|
}
|
2008-12-08 04:46:09 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2008-12-18 10:44:03 +00:00
|
|
|
class CodeBuffer
|
|
|
|
{
|
2008-12-20 17:22:30 +00:00
|
|
|
int size_;
|
2008-12-18 10:44:03 +00:00
|
|
|
public:
|
|
|
|
CodeBuffer(int size);
|
|
|
|
~CodeBuffer();
|
2008-12-08 04:46:09 +00:00
|
|
|
|
2008-12-20 17:22:30 +00:00
|
|
|
int GetSize() const { return size_; }
|
|
|
|
|
2008-12-18 10:44:03 +00:00
|
|
|
PPCAnalyst::CodeOp *codebuffer;
|
2008-12-20 17:22:30 +00:00
|
|
|
|
|
|
|
|
2008-12-18 10:44:03 +00:00
|
|
|
};
|
2008-12-08 04:46:09 +00:00
|
|
|
|
2010-09-22 02:42:17 +00:00
|
|
|
u32 Flatten(u32 address, int *realsize, BlockStats *st, BlockRegStats *gpa,
|
|
|
|
BlockRegStats *fpa, bool &broken_block, CodeBuffer *buffer,
|
|
|
|
int blockSize, u32* merged_addresses,
|
|
|
|
int capacity_of_merged_addresses, int& size_of_merged_addresses);
|
2008-12-18 10:44:03 +00:00
|
|
|
void LogFunctionCall(u32 addr);
|
2009-06-21 08:39:21 +00:00
|
|
|
void FindFunctions(u32 startAddr, u32 endAddr, PPCSymbolDB *func_db);
|
2008-12-08 04:46:09 +00:00
|
|
|
bool AnalyzeFunction(u32 startAddr, Symbol &func, int max_size = 0);
|
|
|
|
|
|
|
|
} // namespace
|