summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authornodchip <nodchip@gmail.com>2010-11-23 13:35:44 +0000
committernodchip <nodchip@gmail.com>2010-11-23 13:35:44 +0000
commitb0c94a47f97e4233cd12574db0b5f9680a588b26 (patch)
tree69de6741cdbe5d0a49eb1a5649f38b5cc3e59749 /Source/Core
parent1830342d66d1b819133e7de6f80a3d8035892d68 (diff)
JitIL: Implemented JitIL IR Disassembler. If you want to use it, add "OutputIR = True" in the "Core" section of Dolphin.ini.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6462 8ced0084-cf51-0410-be5f-012b33b47a6e
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Core/Src/ConfigManager.cpp3
-rw-r--r--Source/Core/Core/Src/CoreParameter.cpp2
-rw-r--r--Source/Core/Core/Src/CoreParameter.h1
-rw-r--r--Source/Core/Core/Src/PowerPC/Jit64IL/IR.cpp155
-rw-r--r--Source/Core/Core/Src/PowerPC/Jit64IL/IR.h9
-rw-r--r--Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp5
-rw-r--r--Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp17
7 files changed, 185 insertions, 7 deletions
diff --git a/Source/Core/Core/Src/ConfigManager.cpp b/Source/Core/Core/Src/ConfigManager.cpp
index 3b8f5d2643..483730e882 100644
--- a/Source/Core/Core/Src/ConfigManager.cpp
+++ b/Source/Core/Core/Src/ConfigManager.cpp
@@ -282,7 +282,8 @@ void SConfig::LoadSettings()
ini.Get("Core", "SlotB", (int*)&m_EXIDevice[1], EXIDEVICE_MEMORYCARD_B);
ini.Get("Core", "SerialPort1", (int*)&m_EXIDevice[2], EXIDEVICE_NONE);
ini.Get("Core", "ProfiledReJIT",&m_LocalCoreStartupParameter.bJITProfiledReJIT, false);
- ini.Get("Core", "TimeProfiling",&m_LocalCoreStartupParameter.bJITILTimeProfiling, false);
+ ini.Get("Core", "TimeProfiling",&m_LocalCoreStartupParameter.bJITILTimeProfiling, false);
+ ini.Get("Core", "OutputIR", &m_LocalCoreStartupParameter.bJITILOutputIR, false);
char sidevicenum[16];
for (int i = 0; i < 4; ++i)
{
diff --git a/Source/Core/Core/Src/CoreParameter.cpp b/Source/Core/Core/Src/CoreParameter.cpp
index 6a043a9e3f..f1f9ae9372 100644
--- a/Source/Core/Core/Src/CoreParameter.cpp
+++ b/Source/Core/Core/Src/CoreParameter.cpp
@@ -40,7 +40,7 @@ SCoreStartupParameter::SCoreStartupParameter()
bJITFloatingPointOff(false), bJITIntegerOff(false),
bJITPairedOff(false), bJITSystemRegistersOff(false),
bJITBranchOff(false), bJITProfiledReJIT(false),
- bJITILTimeProfiling(false),
+ bJITILTimeProfiling(false), bJITILOutputIR(false),
bEnableFPRF(false),
bCPUThread(true), bDSPThread(false),
bSkipIdle(true), bNTSC(false), bNTSCJ(false),
diff --git a/Source/Core/Core/Src/CoreParameter.h b/Source/Core/Core/Src/CoreParameter.h
index 4630c63f7a..10f27f1b0f 100644
--- a/Source/Core/Core/Src/CoreParameter.h
+++ b/Source/Core/Core/Src/CoreParameter.h
@@ -63,6 +63,7 @@ struct SCoreStartupParameter
bool bJITBranchOff;
bool bJITProfiledReJIT;
bool bJITILTimeProfiling;
+ bool bJITILOutputIR;
bool bEnableFPRF;
diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/IR.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/IR.cpp
index a0cb2d91b4..faf8f4da4e 100644
--- a/Source/Core/Core/Src/PowerPC/Jit64IL/IR.cpp
+++ b/Source/Core/Core/Src/PowerPC/Jit64IL/IR.cpp
@@ -146,6 +146,7 @@ namespace IREmitter {
InstLoc IRBuilder::EmitZeroOp(unsigned Opcode, unsigned extra = 0) {
InstLoc curIndex = &InstList[InstList.size()];
InstList.push_back(Opcode | (extra << 8));
+ MarkUsed.push_back(false);
return curIndex;
}
@@ -154,10 +155,12 @@ InstLoc IRBuilder::EmitUOp(unsigned Opcode, InstLoc Op1, unsigned extra) {
unsigned backOp1 = (s32)(curIndex - 1 - Op1);
if (backOp1 >= 256) {
InstList.push_back(Tramp | backOp1 << 8);
+ MarkUsed.push_back(false);
backOp1 = 0;
curIndex++;
}
InstList.push_back(Opcode | (backOp1 << 8) | (extra << 16));
+ MarkUsed.push_back(false);
return curIndex;
}
@@ -166,17 +169,20 @@ InstLoc IRBuilder::EmitBiOp(unsigned Opcode, InstLoc Op1, InstLoc Op2, unsigned
unsigned backOp1 = (s32)(curIndex - 1 - Op1);
if (backOp1 >= 255) {
InstList.push_back(Tramp | backOp1 << 8);
+ MarkUsed.push_back(false);
backOp1 = 0;
curIndex++;
}
unsigned backOp2 = (s32)(curIndex - 1 - Op2);
if (backOp2 >= 256) {
InstList.push_back(Tramp | backOp2 << 8);
+ MarkUsed.push_back(false);
backOp2 = 0;
backOp1++;
curIndex++;
}
InstList.push_back(Opcode | (backOp1 << 8) | (backOp2 << 16) | (extra << 24));
+ MarkUsed.push_back(false);
return curIndex;
}
@@ -186,12 +192,14 @@ InstLoc IRBuilder::EmitTriOp(unsigned Opcode, InstLoc Op1, InstLoc Op2, InstLoc
unsigned backOp1 = curIndex - 1 - Op1;
if (backOp1 >= 254) {
InstList.push_back(Tramp | backOp1 << 8);
+ MarkUsed.push_back(false);
backOp1 = 0;
curIndex++;
}
unsigned backOp2 = curIndex - 1 - Op2;
if (backOp2 >= 255) {
InstList.push_back((Tramp | backOp2 << 8));
+ MarkUsed.push_back(false);
backOp2 = 0;
backOp1++;
curIndex++;
@@ -199,12 +207,14 @@ InstLoc IRBuilder::EmitTriOp(unsigned Opcode, InstLoc Op1, InstLoc Op2, InstLoc
unsigned backOp3 = curIndex - 1 - Op3;
if (backOp3 >= 256) {
InstList.push_back(Tramp | (backOp3 << 8));
+ MarkUsed.push_back(false);
backOp3 = 0;
backOp2++;
backOp1++;
curIndex++;
}
InstList.push_back(Opcode | (backOp1 << 8) | (backOp2 << 16) | (backOp3 << 24));
+ MarkUsed.push_back(false);
return curIndex;
}
#endif
@@ -1054,6 +1064,7 @@ InstLoc IRBuilder::FoldBiOp(unsigned Opcode, InstLoc Op1, InstLoc Op2, unsigned
InstLoc IRBuilder::EmitIntConst(unsigned value) {
InstLoc curIndex = &InstList[InstList.size()];
InstList.push_back(CInt32 | ((unsigned int)ConstList.size() << 8));
+ MarkUsed.push_back(false);
ConstList.push_back(value);
return curIndex;
}
@@ -1062,6 +1073,16 @@ unsigned IRBuilder::GetImmValue(InstLoc I) const {
return ConstList[*I >> 8];
}
+void IRBuilder::SetMarkUsed(InstLoc I) {
+ const unsigned i = (unsigned)(I - &InstList[0]);
+ MarkUsed[i] = true;
+}
+
+bool IRBuilder::IsMarkUsed(InstLoc I) const {
+ const unsigned i = (unsigned)(I - &InstList[0]);
+ return MarkUsed[i];
+}
+
unsigned IRBuilder::isSameValue(InstLoc Op1, InstLoc Op2) const {
if (Op1 == Op2) {
return true;
@@ -1200,4 +1221,138 @@ InstLoc IRBuilder::isNeg(InstLoc I) const {
return NULL;
}
+// TODO: Move the following code to a separated file.
+struct Writer {
+ FILE* file;
+ Writer() : file(NULL) {
+ char buffer[1024];
+ sprintf(buffer, "JitIL_IR_%d.txt", time(NULL));
+ file = fopen(buffer, "w");
+ setvbuf(file, NULL, _IOFBF, 1024 * 1024);
+ }
+ virtual ~Writer() {
+ if (file) {
+ fclose(file);
+ file = NULL;
+ }
+ }
+};
+static std::auto_ptr<Writer> writer;
+
+static const std::string opcodeNames[] = {
+ "Nop", "LoadGReg", "LoadLink", "LoadCR", "LoadCarry", "LoadCTR",
+ "LoadMSR", "LoadGQR", "SExt8", "SExt16", "BSwap32", "BSwap16", "Cntlzw",
+ "Not", "Load8", "Load16", "Load32", "BranchUncond", "StoreGReg",
+ "StoreCR", "StoreLink", "StoreCarry", "StoreCTR", "StoreMSR", "StoreFPRF",
+ "StoreGQR", "StoreSRR", "InterpreterFallback", "Add", "Mul", "And", "Or",
+ "Xor", "MulHighUnsigned", "Sub", "Shl", "Shrl", "Sarl", "Rol",
+ "ICmpCRSigned", "ICmpCRUnsigned", "ICmpEq", "ICmpNe", "ICmpUgt",
+ "ICmpUlt", "ICmpUge", "ICmpUle", "ICmpSgt", "ICmpSlt", "ICmpSge",
+ "ICmpSle", "Store8", "Store16", "Store32", "BranchCond", "FResult_Start",
+ "LoadSingle", "LoadDouble", "LoadPaired", "DoubleToSingle",
+ "DupSingleToMReg", "DupSingleToPacked", "InsertDoubleInMReg",
+ "ExpandPackedToMReg", "CompactMRegToPacked", "LoadFReg",
+ "LoadFRegDENToZero", "FSMul", "FSAdd", "FSSub", "FSNeg", "FSRSqrt",
+ "FPAdd", "FPMul", "FPSub", "FPNeg", "FDMul", "FDAdd", "FDSub", "FDNeg",
+ "FPMerge00", "FPMerge01", "FPMerge10", "FPMerge11", "FPDup0", "FPDup1",
+ "FResult_End", "StorePaired", "StoreSingle", "StoreDouble", "StoreFReg",
+ "FDCmpCR", "CInt16", "CInt32", "SystemCall", "RFIExit",
+ "InterpreterBranch", "IdleBranch", "ShortIdleLoop",
+ "FPExceptionCheckStart", "FPExceptionCheckEnd", "ISIException", "Tramp",
+ "BlockStart", "BlockEnd", "Int3",
+};
+static const unsigned alwaysUsedList[] = {
+ InterpreterFallback, StoreGReg, StoreCR, StoreLink, StoreCTR, StoreMSR,
+ StoreGQR, StoreSRR, StoreCarry, StoreFPRF, Load8, Load16, Load32, Store8,
+ Store16, Store32, StoreSingle, StoreDouble, StorePaired, StoreFReg, FDCmpCR,
+ BlockStart, BlockEnd, IdleBranch, BranchCond, BranchUncond, ShortIdleLoop,
+ SystemCall, InterpreterBranch, RFIExit, FPExceptionCheckStart,
+ FPExceptionCheckEnd, ISIException, Int3, Tramp, Nop
+};
+static const unsigned extra8RegList[] = {
+ LoadGReg, LoadCR, LoadGQR, LoadFReg, LoadFRegDENToZero,
+};
+static const unsigned extra16RegList[] = {
+ StoreGReg, StoreCR, StoreGQR, StoreSRR, LoadPaired, StoreFReg,
+};
+static const unsigned extra24RegList[] = {
+ StorePaired,
+};
+
+static const std::set<unsigned> alwaysUseds(alwaysUsedList, alwaysUsedList + sizeof(alwaysUsedList) / sizeof(alwaysUsedList[0]));
+static const std::set<unsigned> extra8Regs(extra8RegList, extra8RegList + sizeof(extra8RegList) / sizeof(extra8RegList[0]));
+static const std::set<unsigned> extra16Regs(extra16RegList, extra16RegList + sizeof(extra16RegList) / sizeof(extra16RegList[0]));
+static const std::set<unsigned> extra24Regs(extra24RegList, extra24RegList + sizeof(extra24RegList) / sizeof(extra24RegList[0]));
+
+void IRBuilder::WriteToFile(u64 codeHash) {
+ assert(sizeof(opcodeNames) / sizeof(opcodeNames[0]) == Int3 + 1);
+
+ if (!writer.get()) {
+ writer = std::auto_ptr<Writer>(new Writer);
+ }
+
+ FILE* file = writer->file;
+ fprintf(file, "\ncode hash:%016llx\n", codeHash);
+
+ const InstLoc lastCurReadPtr = curReadPtr;
+ StartForwardPass();
+ const unsigned numInsts = getNumInsts();
+ for (int i = 0; i < numInsts; ++i) {
+ const InstLoc I = ReadForward();
+ const unsigned opcode = getOpcode(*I);
+ const bool thisUsed = IsMarkUsed(I) ||
+ alwaysUseds.find(opcode) != alwaysUseds.end();
+
+ // Line number
+ fprintf(file, "%4d", i);
+
+ if (!thisUsed) {
+ fprintf(file, "%*c", 32, ' ');
+ }
+
+ // Opcode
+ const std::string& opcodeName = opcodeNames[opcode];
+ fprintf(file, " %-20s", opcodeName.c_str());
+ const unsigned numberOfOperands = getNumberOfOperands(I);
+
+ // Op1
+ if (numberOfOperands >= 1) {
+ const IREmitter::InstLoc inst = getOp1(I);
+ if (isImm(*inst)) {
+ fprintf(file, " 0x%08x", GetImmValue(inst));
+ } else {
+ fprintf(file, " %10d", i - (I - inst));
+ }
+ }
+
+ // Op2
+ if (numberOfOperands >= 2) {
+ const IREmitter::InstLoc inst = getOp2(I);
+ if (isImm(*inst)) {
+ fprintf(file, " 0x%08x", GetImmValue(inst));
+ } else {
+ fprintf(file, " %10d", i - (I - inst));
+ }
+ }
+
+ if (extra8Regs.count(opcode)) {
+ fprintf(file, " R%d", *I >> 8);
+ }
+ if (extra16Regs.count(opcode)) {
+ fprintf(file, " R%d", *I >> 16);
+ }
+ if (extra24Regs.count(opcode)) {
+ fprintf(file, " R%d", *I >> 24);
+ }
+
+ if (opcode == CInt32 || opcode == CInt16) {
+ fprintf(file, " 0x%08x", GetImmValue(I));
+ }
+
+ fprintf(file, "\n");
+ }
+
+ curReadPtr = lastCurReadPtr;
+}
+
}
diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/IR.h b/Source/Core/Core/Src/PowerPC/Jit64IL/IR.h
index c18bfeddc2..7d94661053 100644
--- a/Source/Core/Core/Src/PowerPC/Jit64IL/IR.h
+++ b/Source/Core/Core/Src/PowerPC/Jit64IL/IR.h
@@ -544,10 +544,15 @@ public:
unsigned int getNumInsts() { return (unsigned int)InstList.size(); }
unsigned int ReadInst(InstLoc I) { return *I; }
unsigned int GetImmValue(InstLoc I) const;
+ void SetMarkUsed(InstLoc I);
+ bool IsMarkUsed(InstLoc I) const;
+ void WriteToFile(u64 codeHash);
void Reset() {
InstList.clear();
InstList.reserve(100000);
+ MarkUsed.clear();
+ MarkUsed.reserve(100000);
for (unsigned i = 0; i < 32; i++) {
GRegCache[i] = 0;
GRegCacheStore[i] = 0;
@@ -576,8 +581,8 @@ private:
bool maskedValueIsZero(InstLoc Op1, InstLoc Op2) const;
InstLoc isNeg(InstLoc I) const;
- std::vector<Inst> InstList; // FIXME: We must ensure this is
- // continuous!
+ std::vector<Inst> InstList; // FIXME: We must ensure this is continuous!
+ std::vector<bool> MarkUsed; // Used for IRWriter
std::vector<unsigned> ConstList;
InstLoc curReadPtr;
InstLoc GRegCache[32];
diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp
index 371d1c69f4..7af2405488 100644
--- a/Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp
+++ b/Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp
@@ -892,6 +892,11 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, bool UseProfile, bool Mak
for (unsigned i = 0; i != RI.IInfo.size(); i++) {
InstLoc I = ibuild->ReadForward();
bool thisUsed = regReadUse(RI, I) ? true : false;
+ if (thisUsed) {
+ // Needed for IR Writer
+ ibuild->SetMarkUsed(I);
+ }
+
switch (getOpcode(*I)) {
case InterpreterFallback: {
unsigned InstCode = ibuild->GetImmValue(getOp1(I));
diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp
index bf586f04ea..1f6ae83486 100644
--- a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp
+++ b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp
@@ -582,15 +582,21 @@ const u8* JitIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
js.rewriteStart = (u8*)GetCodePtr();
- if (SConfig::GetInstance().m_LocalCoreStartupParameter.bJITILTimeProfiling) {
- // For profiling
- u64 codeHash = -1;
+ u64 codeHash = -1;
+ if (SConfig::GetInstance().m_LocalCoreStartupParameter.bJITILTimeProfiling ||
+ SConfig::GetInstance().m_LocalCoreStartupParameter.bJITILOutputIR)
+ {
+ // For profiling and IR Writer
for (int i = 0; i < (int)size; i++)
{
const u64 inst = ops[i].inst.hex;
// Ported from boost::hash
codeHash ^= inst + (codeHash << 6) + (codeHash >> 2);
}
+ }
+
+ if (SConfig::GetInstance().m_LocalCoreStartupParameter.bJITILTimeProfiling)
+ {
JitILProfiler::Block& block = JitILProfiler::Add(codeHash);
ABI_CallFunctionC((void *)JitILProfiler::Begin, block.index);
}
@@ -661,5 +667,10 @@ const u8* JitIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
LogGeneratedX86(size, code_buf, normalEntry, b);
#endif
+ if (SConfig::GetInstance().m_LocalCoreStartupParameter.bJITILOutputIR)
+ {
+ ibuild.WriteToFile(codeHash);
+ }
+
return normalEntry;
}