More code reorganization.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@1605 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
f0bb8f430a
commit
614dc1069e
|
@ -35,12 +35,6 @@
|
||||||
|
|
||||||
void Console_Submit(const char *cmd)
|
void Console_Submit(const char *cmd)
|
||||||
{
|
{
|
||||||
CASE1("jits")
|
|
||||||
{
|
|
||||||
#ifdef _M_X64
|
|
||||||
jit.PrintStats();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
CASE1("r")
|
CASE1("r")
|
||||||
{
|
{
|
||||||
Core::StartTrace(false);
|
Core::StartTrace(false);
|
||||||
|
@ -57,7 +51,7 @@ void Console_Submit(const char *cmd)
|
||||||
u32 addr;
|
u32 addr;
|
||||||
sscanf(cmd, "%s %08x", temp, &addr);
|
sscanf(cmd, "%s %08x", temp, &addr);
|
||||||
|
|
||||||
if (addr!=0)
|
if (addr)
|
||||||
{
|
{
|
||||||
#ifdef LOGGING
|
#ifdef LOGGING
|
||||||
u32 EA =
|
u32 EA =
|
||||||
|
@ -75,7 +69,7 @@ void Console_Submit(const char *cmd)
|
||||||
TCHAR temp[256];
|
TCHAR temp[256];
|
||||||
u32 addr;
|
u32 addr;
|
||||||
sscanf(cmd, "%s %08x", temp, &addr);
|
sscanf(cmd, "%s %08x", temp, &addr);
|
||||||
if (addr!=0)
|
if (addr)
|
||||||
{
|
{
|
||||||
g_symbolDB.PrintCalls(addr);
|
g_symbolDB.PrintCalls(addr);
|
||||||
}
|
}
|
||||||
|
@ -89,7 +83,7 @@ void Console_Submit(const char *cmd)
|
||||||
TCHAR temp[256];
|
TCHAR temp[256];
|
||||||
u32 addr;
|
u32 addr;
|
||||||
sscanf(cmd, "%s %08x", temp, &addr);
|
sscanf(cmd, "%s %08x", temp, &addr);
|
||||||
if (addr!=0)
|
if (addr)
|
||||||
{
|
{
|
||||||
g_symbolDB.PrintCallers(addr);
|
g_symbolDB.PrintCallers(addr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include "../HW/CPU.h"
|
#include "../HW/CPU.h"
|
||||||
#include "../Host.h"
|
#include "../Host.h"
|
||||||
#include "../PowerPC/SymbolDB.h"
|
#include "../PowerPC/SymbolDB.h"
|
||||||
|
#include "../PowerPC/Jit64/Jit.h"
|
||||||
#include "Debugger_BreakPoints.h"
|
#include "Debugger_BreakPoints.h"
|
||||||
|
|
||||||
CBreakPoints::TBreakPoints CBreakPoints::m_BreakPoints;
|
CBreakPoints::TBreakPoints CBreakPoints::m_BreakPoints;
|
||||||
|
@ -99,16 +100,17 @@ TMemCheck *CBreakPoints::GetMemCheck(u32 address)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBreakPoints::AddBreakPoint(u32 _iAddress, bool temp)
|
void CBreakPoints::AddBreakPoint(u32 em_address, bool temp)
|
||||||
{
|
{
|
||||||
if (!IsAddressBreakPoint(_iAddress)) // only add new addresses
|
if (!IsAddressBreakPoint(em_address)) // only add new addresses
|
||||||
{
|
{
|
||||||
TBreakPoint pt; // breakpoint settings
|
TBreakPoint pt; // breakpoint settings
|
||||||
pt.bOn = true;
|
pt.bOn = true;
|
||||||
pt.bTemporary = temp;
|
pt.bTemporary = temp;
|
||||||
pt.iAddress = _iAddress;
|
pt.iAddress = em_address;
|
||||||
|
|
||||||
m_BreakPoints.push_back(pt);
|
m_BreakPoints.push_back(pt);
|
||||||
|
// jit.NotifyBreakpoint(em_address, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,11 +123,10 @@ void CBreakPoints::RemoveBreakPoint(u32 _iAddress)
|
||||||
if ((*iter).iAddress == _iAddress)
|
if ((*iter).iAddress == _iAddress)
|
||||||
{
|
{
|
||||||
m_BreakPoints.erase(iter);
|
m_BreakPoints.erase(iter);
|
||||||
|
// jit.NotifyBreakpoint(em_address, false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Host_UpdateBreakPointView();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBreakPoints::ClearAllBreakPoints()
|
void CBreakPoints::ClearAllBreakPoints()
|
||||||
|
|
|
@ -72,7 +72,7 @@ public:
|
||||||
static bool IsTempBreakPoint(u32 _iAddress);
|
static bool IsTempBreakPoint(u32 _iAddress);
|
||||||
|
|
||||||
// AddBreakPoint
|
// AddBreakPoint
|
||||||
static void AddBreakPoint(u32 _iAddress, bool temp=false);
|
static void AddBreakPoint(u32 em_address, bool temp=false);
|
||||||
|
|
||||||
// Remove Breakpoint
|
// Remove Breakpoint
|
||||||
static void RemoveBreakPoint(u32 _iAddress);
|
static void RemoveBreakPoint(u32 _iAddress);
|
||||||
|
|
|
@ -757,9 +757,9 @@ bool AreMemoryBreakpointsActivated()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
u32 Read_Instruction(const u32 _Address)
|
u32 Read_Instruction(const u32 em_address)
|
||||||
{
|
{
|
||||||
return jit.GetOriginalCode(_Address);
|
return jit.GetBlockCache()->GetOriginalCode(em_address);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 Read_Opcode(const u32 _Address)
|
u32 Read_Opcode(const u32 _Address)
|
||||||
|
|
|
@ -340,7 +340,7 @@ void icbi(UGeckoInstruction _inst)
|
||||||
// VERY IMPORTANT when we start linking blocks
|
// VERY IMPORTANT when we start linking blocks
|
||||||
// There are a TON of these so hopefully we can make this mechanism
|
// There are a TON of these so hopefully we can make this mechanism
|
||||||
// fast in the JIT
|
// fast in the JIT
|
||||||
jit.InvalidateCodeRange(address, 0x20);
|
jit.GetBlockCache()->InvalidateCodeRange(address, 0x20);
|
||||||
}
|
}
|
||||||
|
|
||||||
void lbzux(UGeckoInstruction _inst)
|
void lbzux(UGeckoInstruction _inst)
|
||||||
|
|
|
@ -196,20 +196,28 @@ namespace CPUCompare
|
||||||
|
|
||||||
trampolines.Init();
|
trampolines.Init();
|
||||||
AllocCodeSpace(CODE_SIZE);
|
AllocCodeSpace(CODE_SIZE);
|
||||||
InitCache();
|
|
||||||
|
blocks.Init();
|
||||||
asm_routines.Init();
|
asm_routines.Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Jit64::Shutdown()
|
void Jit64::Shutdown()
|
||||||
{
|
{
|
||||||
FreeCodeSpace();
|
FreeCodeSpace();
|
||||||
ShutdownCache();
|
|
||||||
|
|
||||||
|
blocks.Shutdown();
|
||||||
trampolines.Shutdown();
|
trampolines.Shutdown();
|
||||||
asm_routines.Shutdown();
|
asm_routines.Shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Jit64::WriteCallInterpreter(UGeckoInstruction _inst)
|
void Jit64::EnterFastRun()
|
||||||
|
{
|
||||||
|
CompiledCode pExecAddr = (CompiledCode)asm_routines.enterCode;
|
||||||
|
pExecAddr();
|
||||||
|
//Will return when PowerPC::state changes
|
||||||
|
}
|
||||||
|
|
||||||
|
void Jit64::WriteCallInterpreter(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
gpr.Flush(FLUSH_ALL);
|
gpr.Flush(FLUSH_ALL);
|
||||||
fpr.Flush(FLUSH_ALL);
|
fpr.Flush(FLUSH_ALL);
|
||||||
|
@ -218,8 +226,14 @@ namespace CPUCompare
|
||||||
MOV(32, M(&PC), Imm32(js.compilerPC));
|
MOV(32, M(&PC), Imm32(js.compilerPC));
|
||||||
MOV(32, M(&NPC), Imm32(js.compilerPC + 4));
|
MOV(32, M(&NPC), Imm32(js.compilerPC + 4));
|
||||||
}
|
}
|
||||||
Interpreter::_interpreterInstruction instr = GetInterpreterOp(_inst);
|
Interpreter::_interpreterInstruction instr = GetInterpreterOp(inst);
|
||||||
ABI_CallFunctionC((void*)instr, _inst.hex);
|
ABI_CallFunctionC((void*)instr, inst.hex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Jit64::unknown_instruction(UGeckoInstruction inst)
|
||||||
|
{
|
||||||
|
// CCPU::Break();
|
||||||
|
PanicAlert("unknown_instruction %08x - Fix me ;)", inst.hex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Jit64::Default(UGeckoInstruction _inst)
|
void Jit64::Default(UGeckoInstruction _inst)
|
||||||
|
@ -286,11 +300,11 @@ namespace CPUCompare
|
||||||
b->exitPtrs[exit_num] = GetWritableCodePtr();
|
b->exitPtrs[exit_num] = GetWritableCodePtr();
|
||||||
|
|
||||||
// Link opportunity!
|
// Link opportunity!
|
||||||
int block = GetBlockNumberFromAddress(destination);
|
int block = blocks.GetBlockNumberFromAddress(destination);
|
||||||
if (block >= 0 && jo.enableBlocklink)
|
if (block >= 0 && jo.enableBlocklink)
|
||||||
{
|
{
|
||||||
// It exists! Joy of joy!
|
// It exists! Joy of joy!
|
||||||
JMP(GetBlock(block)->checkedEntry, true);
|
JMP(blocks.GetBlock(block)->checkedEntry, true);
|
||||||
b->linkStatus[exit_num] = true;
|
b->linkStatus[exit_num] = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -324,6 +338,21 @@ namespace CPUCompare
|
||||||
JMP(asm_routines.testExceptions, true);
|
JMP(asm_routines.testExceptions, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const u8 *Jit64::Jit(u32 em_address)
|
||||||
|
{
|
||||||
|
if (GetSpaceLeft() < 0x10000 || blocks.IsFull())
|
||||||
|
{
|
||||||
|
LOG(DYNA_REC, "JIT cache full - clearing.")
|
||||||
|
if (Core::g_CoreStartupParameter.bJITUnlimitedCache)
|
||||||
|
{
|
||||||
|
PanicAlert("What? JIT cache still full - clearing.");
|
||||||
|
}
|
||||||
|
ClearCache();
|
||||||
|
}
|
||||||
|
|
||||||
|
return blocks.Jit(em_address);
|
||||||
|
}
|
||||||
|
|
||||||
const u8* Jit64::DoJit(u32 emaddress, JitBlock &b)
|
const u8* Jit64::DoJit(u32 emaddress, JitBlock &b)
|
||||||
{
|
{
|
||||||
if (emaddress == 0)
|
if (emaddress == 0)
|
||||||
|
|
|
@ -71,37 +71,7 @@ public:
|
||||||
|
|
||||||
class Jit64 : public Gen::XCodeBlock
|
class Jit64 : public Gen::XCodeBlock
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
// TODO(ector) - optimize this struct for size
|
|
||||||
struct JitBlock
|
|
||||||
{
|
|
||||||
u32 exitAddress[2]; // 0xFFFFFFFF == unknown
|
|
||||||
u8 *exitPtrs[2]; // to be able to rewrite the exit jump
|
|
||||||
bool linkStatus[2];
|
|
||||||
|
|
||||||
u32 originalAddress;
|
|
||||||
u32 originalFirstOpcode; //to be able to restore
|
|
||||||
u32 codeSize;
|
|
||||||
u32 originalSize;
|
|
||||||
int runCount; // for profiling.
|
|
||||||
#ifdef _WIN32
|
|
||||||
// we don't really need to save start and stop
|
|
||||||
// TODO (mb2): ticStart and ticStop -> "local var" mean "in block" ... low priority ;)
|
|
||||||
LARGE_INTEGER ticStart; // for profiling - time.
|
|
||||||
LARGE_INTEGER ticStop; // for profiling - time.
|
|
||||||
LARGE_INTEGER ticCounter; // for profiling - time.
|
|
||||||
#endif
|
|
||||||
const u8 *checkedEntry;
|
|
||||||
bool invalid;
|
|
||||||
int flags;
|
|
||||||
};
|
|
||||||
private:
|
private:
|
||||||
enum BlockFlag
|
|
||||||
{
|
|
||||||
BLOCK_USE_GQR0 = 0x1, BLOCK_USE_GQR1 = 0x2, BLOCK_USE_GQR2 = 0x4, BLOCK_USE_GQR3 = 0x8,
|
|
||||||
BLOCK_USE_GQR4 = 0x10, BLOCK_USE_GQR5 = 0x20, BLOCK_USE_GQR6 = 0x40, BLOCK_USE_GQR7 = 0x80,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct JitState
|
struct JitState
|
||||||
{
|
{
|
||||||
u32 compilerPC;
|
u32 compilerPC;
|
||||||
|
@ -139,20 +109,14 @@ private:
|
||||||
bool accurateSinglePrecision;
|
bool accurateSinglePrecision;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
JitBlockCache blocks;
|
||||||
TrampolineCache trampolines;
|
TrampolineCache trampolines;
|
||||||
GPRRegCache gpr;
|
GPRRegCache gpr;
|
||||||
FPURegCache fpr;
|
FPURegCache fpr;
|
||||||
|
|
||||||
u8 **blockCodePointers;
|
|
||||||
|
|
||||||
std::multimap<u32, int> links_to;
|
|
||||||
|
|
||||||
JitBlock *blocks;
|
|
||||||
int numBlocks;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef void (*CompiledCode)();
|
Jit64() {blocks.SetJit(this);}
|
||||||
|
~Jit64() {}
|
||||||
|
|
||||||
JitState js;
|
JitState js;
|
||||||
JitOptions jo;
|
JitOptions jo;
|
||||||
|
@ -162,40 +126,24 @@ public:
|
||||||
void Init();
|
void Init();
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
|
|
||||||
void PrintStats();
|
|
||||||
|
|
||||||
// Jit!
|
// Jit!
|
||||||
|
|
||||||
const u8* Jit(u32 emaddress);
|
const u8 *Jit(u32 emAddress); // calls blocks.Jit, which in turn calls DoJit below after setting up a block.
|
||||||
const u8* DoJit(u32 emaddress, JitBlock &b);
|
const u8* DoJit(u32 emaddress, JitBlock &b);
|
||||||
|
|
||||||
|
JitBlockCache *GetBlockCache() { return &blocks; }
|
||||||
|
|
||||||
|
void ClearCache()
|
||||||
|
{
|
||||||
|
blocks.Clear();
|
||||||
|
trampolines.ClearCodeSpace();
|
||||||
|
}
|
||||||
|
|
||||||
// Run!
|
// Run!
|
||||||
|
|
||||||
void EnterFastRun();
|
void EnterFastRun();
|
||||||
const u8 *BackPatch(u8 *codePtr, int accessType, u32 emAddress, CONTEXT *ctx);
|
const u8 *BackPatch(u8 *codePtr, int accessType, u32 emAddress, CONTEXT *ctx);
|
||||||
|
|
||||||
// Code Cache
|
|
||||||
|
|
||||||
u32 GetOriginalCode(u32 address);
|
|
||||||
JitBlock *GetBlock(int no);
|
|
||||||
void InvalidateCodeRange(u32 address, u32 length);
|
|
||||||
int GetBlockNumberFromAddress(u32 address);
|
|
||||||
CompiledCode GetCompiledCode(u32 address);
|
|
||||||
CompiledCode GetCompiledCodeFromBlock(int blockNumber);
|
|
||||||
int GetCodeSize();
|
|
||||||
int GetNumBlocks();
|
|
||||||
u8 **GetCodePointers();
|
|
||||||
void DestroyBlocksWithFlag(BlockFlag death_flag);
|
|
||||||
void LinkBlocks();
|
|
||||||
void LinkBlockExits(int i);
|
|
||||||
void LinkBlock(int i);
|
|
||||||
void ClearCache();
|
|
||||||
void InitCache();
|
|
||||||
void ShutdownCache();
|
|
||||||
void ResetCache();
|
|
||||||
void DestroyBlock(int blocknum, bool invalidate);
|
|
||||||
bool RangeIntersect(int s1, int e1, int s2, int e2) const;
|
|
||||||
|
|
||||||
#define JIT_OPCODE 0
|
#define JIT_OPCODE 0
|
||||||
|
|
||||||
// Utilities for use by opcodes
|
// Utilities for use by opcodes
|
||||||
|
|
|
@ -169,10 +169,8 @@ void AsmRoutineManager::Generate()
|
||||||
|
|
||||||
ABI_PushAllCalleeSavedRegsAndAdjustStack();
|
ABI_PushAllCalleeSavedRegsAndAdjustStack();
|
||||||
|
|
||||||
if (!jit.GetCodePointers() || !Memory::base)
|
|
||||||
PanicAlert("Memory::base and jit.GetCodePointers() must return valid values");
|
|
||||||
MOV(64, R(RBX), Imm64((u64)Memory::base));
|
MOV(64, R(RBX), Imm64((u64)Memory::base));
|
||||||
MOV(64, R(R15), Imm64((u64)jit.GetCodePointers())); //It's below 2GB so 32 bits are good enough
|
MOV(64, R(R15), Imm64((u64)jit.GetBlockCache()->GetCodePointers())); //It's below 2GB so 32 bits are good enough
|
||||||
const u8 *outerLoop = GetCodePtr();
|
const u8 *outerLoop = GetCodePtr();
|
||||||
|
|
||||||
CALL((void *)&CoreTiming::Advance);
|
CALL((void *)&CoreTiming::Advance);
|
||||||
|
|
|
@ -204,7 +204,7 @@ const u8 *Jit64::BackPatch(u8 *codePtr, int accessType, u32 emAddress, CONTEXT *
|
||||||
if (info.instructionSize < 3)
|
if (info.instructionSize < 3)
|
||||||
PanicAlert("instruction too small");
|
PanicAlert("instruction too small");
|
||||||
// We entered here with a BSWAP-ed EAX. We'll have to swap it back.
|
// We entered here with a BSWAP-ed EAX. We'll have to swap it back.
|
||||||
ctx->Rax = Common::swap32(ctx->Rax);
|
ctx->Rax = Common::swap32((u32)ctx->Rax);
|
||||||
return codePtr - 2;
|
return codePtr - 2;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -24,8 +24,6 @@
|
||||||
|
|
||||||
//#define OPROFILE_REPORT
|
//#define OPROFILE_REPORT
|
||||||
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
#include "../../Core.h"
|
#include "../../Core.h"
|
||||||
#include "MemoryUtil.h"
|
#include "MemoryUtil.h"
|
||||||
|
@ -50,31 +48,23 @@
|
||||||
#include <opagent.h>
|
#include <opagent.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
using namespace Gen;
|
|
||||||
|
|
||||||
#ifdef OPROFILE_REPORT
|
#ifdef OPROFILE_REPORT
|
||||||
op_agent_t agent;
|
op_agent_t agent;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
using namespace Gen;
|
||||||
|
|
||||||
#define INVALID_EXIT 0xFFFFFFFF
|
#define INVALID_EXIT 0xFFFFFFFF
|
||||||
|
|
||||||
enum
|
|
||||||
|
bool JitBlockCache::IsFull() const
|
||||||
{
|
{
|
||||||
TRAMPOLINE_SIZE = 1024*1024,
|
return GetNumBlocks() >= MAX_NUM_BLOCKS - 1;
|
||||||
};
|
|
||||||
|
|
||||||
int MAX_NUM_BLOCKS = 65536*2;
|
|
||||||
|
|
||||||
|
|
||||||
void Jit64::PrintStats()
|
|
||||||
{
|
|
||||||
LOG(DYNA_REC, "JIT Statistics =======================");
|
|
||||||
LOG(DYNA_REC, "Number of blocks currently: %i", numBlocks);
|
|
||||||
LOG(DYNA_REC, "======================================");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Jit64::InitCache()
|
void JitBlockCache::Init()
|
||||||
{
|
{
|
||||||
|
MAX_NUM_BLOCKS = 65536*2;
|
||||||
if (Core::g_CoreStartupParameter.bJITUnlimitedCache)
|
if (Core::g_CoreStartupParameter.bJITUnlimitedCache)
|
||||||
{
|
{
|
||||||
MAX_NUM_BLOCKS = 65536*8;
|
MAX_NUM_BLOCKS = 65536*8;
|
||||||
|
@ -86,10 +76,10 @@ using namespace Gen;
|
||||||
blocks = new JitBlock[MAX_NUM_BLOCKS];
|
blocks = new JitBlock[MAX_NUM_BLOCKS];
|
||||||
blockCodePointers = new u8*[MAX_NUM_BLOCKS];
|
blockCodePointers = new u8*[MAX_NUM_BLOCKS];
|
||||||
|
|
||||||
ClearCache();
|
Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Jit64::ShutdownCache()
|
void JitBlockCache::Shutdown()
|
||||||
{
|
{
|
||||||
delete [] blocks;
|
delete [] blocks;
|
||||||
delete [] blockCodePointers;
|
delete [] blockCodePointers;
|
||||||
|
@ -103,7 +93,7 @@ using namespace Gen;
|
||||||
|
|
||||||
// This clears the JIT cache. It's called from JitCache.cpp when the JIT cache
|
// This clears the JIT cache. It's called from JitCache.cpp when the JIT cache
|
||||||
// is full and when saving and loading states.
|
// is full and when saving and loading states.
|
||||||
void Jit64::ClearCache()
|
void JitBlockCache::Clear()
|
||||||
{
|
{
|
||||||
Core::DisplayMessage("Cleared code cache.", 3000);
|
Core::DisplayMessage("Cleared code cache.", 3000);
|
||||||
// Is destroying the blocks really necessary?
|
// Is destroying the blocks really necessary?
|
||||||
|
@ -114,11 +104,9 @@ using namespace Gen;
|
||||||
links_to.clear();
|
links_to.clear();
|
||||||
numBlocks = 0;
|
numBlocks = 0;
|
||||||
memset(blockCodePointers, 0, sizeof(u8*)*MAX_NUM_BLOCKS);
|
memset(blockCodePointers, 0, sizeof(u8*)*MAX_NUM_BLOCKS);
|
||||||
|
|
||||||
trampolines.ClearCodeSpace();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Jit64::DestroyBlocksWithFlag(BlockFlag death_flag)
|
void JitBlockCache::DestroyBlocksWithFlag(BlockFlag death_flag)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < numBlocks; i++)
|
for (int i = 0; i < numBlocks; i++)
|
||||||
{
|
{
|
||||||
|
@ -129,23 +117,23 @@ using namespace Gen;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Jit64::ResetCache()
|
void JitBlockCache::Reset()
|
||||||
{
|
{
|
||||||
ShutdownCache();
|
Shutdown();
|
||||||
InitCache();
|
Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
Jit64::JitBlock *Jit64::GetBlock(int no)
|
JitBlock *JitBlockCache::GetBlock(int no)
|
||||||
{
|
{
|
||||||
return &blocks[no];
|
return &blocks[no];
|
||||||
}
|
}
|
||||||
|
|
||||||
int Jit64::GetNumBlocks()
|
int JitBlockCache::GetNumBlocks() const
|
||||||
{
|
{
|
||||||
return numBlocks;
|
return numBlocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Jit64::RangeIntersect(int s1, int e1, int s2, int e2) const
|
bool JitBlockCache::RangeIntersect(int s1, int e1, int s2, int e2) const
|
||||||
{
|
{
|
||||||
// check if any endpoint is inside the other range
|
// check if any endpoint is inside the other range
|
||||||
if ( (s1 >= s2 && s1 <= e2) ||
|
if ( (s1 >= s2 && s1 <= e2) ||
|
||||||
|
@ -162,18 +150,8 @@ using namespace Gen;
|
||||||
return jit.Jit(emAddress);
|
return jit.Jit(emAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
const u8 *Jit64::Jit(u32 emAddress)
|
const u8 *JitBlockCache::Jit(u32 emAddress)
|
||||||
{
|
{
|
||||||
if (GetSpaceLeft() < 0x10000 || numBlocks >= MAX_NUM_BLOCKS - 1)
|
|
||||||
{
|
|
||||||
LOG(DYNA_REC, "JIT cache full - clearing.")
|
|
||||||
if (Core::g_CoreStartupParameter.bJITUnlimitedCache)
|
|
||||||
{
|
|
||||||
PanicAlert("What? JIT cache still full - clearing.");
|
|
||||||
}
|
|
||||||
ClearCache();
|
|
||||||
}
|
|
||||||
|
|
||||||
JitBlock &b = blocks[numBlocks];
|
JitBlock &b = blocks[numBlocks];
|
||||||
b.invalid = false;
|
b.invalid = false;
|
||||||
b.originalAddress = emAddress;
|
b.originalAddress = emAddress;
|
||||||
|
@ -185,10 +163,10 @@ using namespace Gen;
|
||||||
b.linkStatus[0] = false;
|
b.linkStatus[0] = false;
|
||||||
b.linkStatus[1] = false;
|
b.linkStatus[1] = false;
|
||||||
|
|
||||||
blockCodePointers[numBlocks] = (u8*)DoJit(emAddress, b); //cast away const
|
blockCodePointers[numBlocks] = (u8*)jit->DoJit(emAddress, b); //cast away const
|
||||||
Memory::WriteUnchecked_U32((JIT_OPCODE << 26) | numBlocks, emAddress);
|
Memory::WriteUnchecked_U32((JIT_OPCODE << 26) | numBlocks, emAddress);
|
||||||
|
|
||||||
if (jo.enableBlocklink) {
|
if (jit->jo.enableBlocklink) {
|
||||||
for (int i = 0; i < 2; i++) {
|
for (int i = 0; i < 2; i++) {
|
||||||
if (b.exitAddress[i] != INVALID_EXIT) {
|
if (b.exitAddress[i] != INVALID_EXIT) {
|
||||||
links_to.insert(std::pair<u32, int>(b.exitAddress[i], numBlocks));
|
links_to.insert(std::pair<u32, int>(b.exitAddress[i], numBlocks));
|
||||||
|
@ -211,26 +189,12 @@ using namespace Gen;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Jit64::unknown_instruction(UGeckoInstruction _inst)
|
u8 **JitBlockCache::GetCodePointers()
|
||||||
{
|
|
||||||
// CCPU::Break();
|
|
||||||
PanicAlert("unknown_instruction Jit64 - Fix me ;)");
|
|
||||||
_dbg_assert_(DYNA_REC, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 **Jit64::GetCodePointers()
|
|
||||||
{
|
{
|
||||||
return blockCodePointers;
|
return blockCodePointers;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Jit64::EnterFastRun()
|
int JitBlockCache::GetBlockNumberFromAddress(u32 addr)
|
||||||
{
|
|
||||||
CompiledCode pExecAddr = (CompiledCode)asm_routines.enterCode;
|
|
||||||
pExecAddr();
|
|
||||||
//Will return when PowerPC::state changes
|
|
||||||
}
|
|
||||||
|
|
||||||
int Jit64::GetBlockNumberFromAddress(u32 addr)
|
|
||||||
{
|
{
|
||||||
if (!blocks)
|
if (!blocks)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -256,7 +220,7 @@ using namespace Gen;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 Jit64::GetOriginalCode(u32 address)
|
u32 JitBlockCache::GetOriginalCode(u32 address)
|
||||||
{
|
{
|
||||||
int num = GetBlockNumberFromAddress(address);
|
int num = GetBlockNumberFromAddress(address);
|
||||||
if (num == -1)
|
if (num == -1)
|
||||||
|
@ -265,7 +229,7 @@ using namespace Gen;
|
||||||
return blocks[num].originalFirstOpcode;
|
return blocks[num].originalFirstOpcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
Jit64::CompiledCode Jit64::GetCompiledCode(u32 address)
|
CompiledCode JitBlockCache::GetCompiledCode(u32 address)
|
||||||
{
|
{
|
||||||
int num = GetBlockNumberFromAddress(address);
|
int num = GetBlockNumberFromAddress(address);
|
||||||
if (num == -1)
|
if (num == -1)
|
||||||
|
@ -274,7 +238,7 @@ using namespace Gen;
|
||||||
return (CompiledCode)blockCodePointers[num];
|
return (CompiledCode)blockCodePointers[num];
|
||||||
}
|
}
|
||||||
|
|
||||||
Jit64::CompiledCode Jit64::GetCompiledCodeFromBlock(int blockNumber)
|
CompiledCode JitBlockCache::GetCompiledCodeFromBlock(int blockNumber)
|
||||||
{
|
{
|
||||||
return (CompiledCode)blockCodePointers[blockNumber];
|
return (CompiledCode)blockCodePointers[blockNumber];
|
||||||
}
|
}
|
||||||
|
@ -285,7 +249,7 @@ using namespace Gen;
|
||||||
//Can be faster by doing a queue for blocks to link up, and only process those
|
//Can be faster by doing a queue for blocks to link up, and only process those
|
||||||
//Should probably be done
|
//Should probably be done
|
||||||
|
|
||||||
void Jit64::LinkBlockExits(int i)
|
void JitBlockCache::LinkBlockExits(int i)
|
||||||
{
|
{
|
||||||
JitBlock &b = blocks[i];
|
JitBlock &b = blocks[i];
|
||||||
if (b.invalid)
|
if (b.invalid)
|
||||||
|
@ -310,10 +274,10 @@ using namespace Gen;
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
void Jit64::LinkBlock(int i)
|
void JitBlockCache::LinkBlock(int i)
|
||||||
{
|
{
|
||||||
LinkBlockExits(i);
|
LinkBlockExits(i);
|
||||||
Jit64::JitBlock &b = blocks[i];
|
JitBlock &b = blocks[i];
|
||||||
std::map<u32, int>::iterator iter;
|
std::map<u32, int>::iterator iter;
|
||||||
pair<multimap<u32, int>::iterator, multimap<u32, int>::iterator> ppp;
|
pair<multimap<u32, int>::iterator, multimap<u32, int>::iterator> ppp;
|
||||||
// equal_range(b) returns pair<iterator,iterator> representing the range
|
// equal_range(b) returns pair<iterator,iterator> representing the range
|
||||||
|
@ -327,10 +291,10 @@ using namespace Gen;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Jit64::DestroyBlock(int blocknum, bool invalidate)
|
void JitBlockCache::DestroyBlock(int blocknum, bool invalidate)
|
||||||
{
|
{
|
||||||
u32 codebytes = (JIT_OPCODE << 26) | blocknum; //generate from i
|
u32 codebytes = (JIT_OPCODE << 26) | blocknum; //generate from i
|
||||||
Jit64::JitBlock &b = blocks[blocknum];
|
JitBlock &b = blocks[blocknum];
|
||||||
b.invalid = 1;
|
b.invalid = 1;
|
||||||
if (codebytes == Memory::ReadFast32(b.originalAddress))
|
if (codebytes == Memory::ReadFast32(b.originalAddress))
|
||||||
{
|
{
|
||||||
|
@ -363,9 +327,9 @@ using namespace Gen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Jit64::InvalidateCodeRange(u32 address, u32 length)
|
void JitBlockCache::InvalidateCodeRange(u32 address, u32 length)
|
||||||
{
|
{
|
||||||
if (!jo.enableBlocklink)
|
if (!jit->jo.enableBlocklink)
|
||||||
return;
|
return;
|
||||||
return;
|
return;
|
||||||
//This is slow but should be safe (zelda needs it for block linking)
|
//This is slow but should be safe (zelda needs it for block linking)
|
||||||
|
|
|
@ -17,8 +17,87 @@
|
||||||
#ifndef _JITCACHE_H
|
#ifndef _JITCACHE_H
|
||||||
#define _JITCACHE_H
|
#define _JITCACHE_H
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
#include "../Gekko.h"
|
#include "../Gekko.h"
|
||||||
|
|
||||||
// Will soon introduce the JitBlockCache class here.
|
#ifdef _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum BlockFlag
|
||||||
|
{
|
||||||
|
BLOCK_USE_GQR0 = 0x1, BLOCK_USE_GQR1 = 0x2, BLOCK_USE_GQR2 = 0x4, BLOCK_USE_GQR3 = 0x8,
|
||||||
|
BLOCK_USE_GQR4 = 0x10, BLOCK_USE_GQR5 = 0x20, BLOCK_USE_GQR6 = 0x40, BLOCK_USE_GQR7 = 0x80,
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO(ector) - optimize this struct for size
|
||||||
|
struct JitBlock
|
||||||
|
{
|
||||||
|
u32 exitAddress[2]; // 0xFFFFFFFF == unknown
|
||||||
|
u8 *exitPtrs[2]; // to be able to rewrite the exit jump
|
||||||
|
bool linkStatus[2];
|
||||||
|
|
||||||
|
u32 originalAddress;
|
||||||
|
u32 originalFirstOpcode; //to be able to restore
|
||||||
|
u32 codeSize;
|
||||||
|
u32 originalSize;
|
||||||
|
int runCount; // for profiling.
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
// we don't really need to save start and stop
|
||||||
|
// TODO (mb2): ticStart and ticStop -> "local var" mean "in block" ... low priority ;)
|
||||||
|
LARGE_INTEGER ticStart; // for profiling - time.
|
||||||
|
LARGE_INTEGER ticStop; // for profiling - time.
|
||||||
|
LARGE_INTEGER ticCounter; // for profiling - time.
|
||||||
|
#endif
|
||||||
|
const u8 *checkedEntry;
|
||||||
|
bool invalid;
|
||||||
|
int flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Jit64;
|
||||||
|
|
||||||
|
typedef void (*CompiledCode)();
|
||||||
|
|
||||||
|
class JitBlockCache
|
||||||
|
{
|
||||||
|
Jit64 *jit;
|
||||||
|
|
||||||
|
u8 **blockCodePointers;
|
||||||
|
JitBlock *blocks;
|
||||||
|
int numBlocks;
|
||||||
|
std::multimap<u32, int> links_to;
|
||||||
|
|
||||||
|
int MAX_NUM_BLOCKS;
|
||||||
|
|
||||||
|
public:
|
||||||
|
JitBlockCache() {}
|
||||||
|
|
||||||
|
void SetJit(Jit64 *jit_) { jit = jit_; }
|
||||||
|
|
||||||
|
const u8* Jit(u32 emaddress);
|
||||||
|
void Clear();
|
||||||
|
void Init();
|
||||||
|
void Shutdown();
|
||||||
|
void Reset();
|
||||||
|
|
||||||
|
bool IsFull() const;
|
||||||
|
// Code Cache
|
||||||
|
u32 GetOriginalCode(u32 address);
|
||||||
|
JitBlock *GetBlock(int no);
|
||||||
|
void InvalidateCodeRange(u32 address, u32 length);
|
||||||
|
int GetBlockNumberFromAddress(u32 address);
|
||||||
|
CompiledCode GetCompiledCode(u32 address);
|
||||||
|
CompiledCode GetCompiledCodeFromBlock(int blockNumber);
|
||||||
|
int GetNumBlocks() const;
|
||||||
|
u8 **GetCodePointers();
|
||||||
|
void DestroyBlocksWithFlag(BlockFlag death_flag);
|
||||||
|
void LinkBlocks();
|
||||||
|
void LinkBlockExits(int i);
|
||||||
|
void LinkBlock(int i);
|
||||||
|
void DestroyBlock(int blocknum, bool invalidate);
|
||||||
|
bool RangeIntersect(int s1, int e1, int s2, int e2) const;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -131,18 +131,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
if (js.next_inst.OPCD == 16) { // bcx
|
|
||||||
if (!js.next_inst.LK && (js.next_inst.BO & BO_DONT_DECREMENT_FLAG))
|
|
||||||
{
|
|
||||||
// it's clear there's plenty of opportunity.
|
|
||||||
//PanicAlert("merge");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// unsigned
|
|
||||||
void Jit64::cmpXX(UGeckoInstruction inst)
|
void Jit64::cmpXX(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
// USES_CR
|
// USES_CR
|
||||||
|
|
|
@ -41,16 +41,16 @@ struct BlockStat
|
||||||
|
|
||||||
void WriteProfileResults(const char *filename) {
|
void WriteProfileResults(const char *filename) {
|
||||||
std::vector<BlockStat> stats;
|
std::vector<BlockStat> stats;
|
||||||
stats.reserve(jit.GetNumBlocks());
|
stats.reserve(jit.GetBlockCache()->GetNumBlocks());
|
||||||
u64 cost_sum = 0;
|
u64 cost_sum = 0;
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
u64 timecost_sum = 0;
|
u64 timecost_sum = 0;
|
||||||
LARGE_INTEGER countsPerSec;
|
LARGE_INTEGER countsPerSec;
|
||||||
QueryPerformanceFrequency(&countsPerSec);
|
QueryPerformanceFrequency(&countsPerSec);
|
||||||
#endif
|
#endif
|
||||||
for (int i = 0; i < jit.GetNumBlocks(); i++)
|
for (int i = 0; i < jit.GetBlockCache()->GetNumBlocks(); i++)
|
||||||
{
|
{
|
||||||
const Jit64::JitBlock *block = jit.GetBlock(i);
|
const JitBlock *block = jit.GetBlockCache()->GetBlock(i);
|
||||||
u64 cost = (block->originalSize / 4) * block->runCount; // rough heuristic. mem instructions should cost more.
|
u64 cost = (block->originalSize / 4) * block->runCount; // rough heuristic. mem instructions should cost more.
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
u64 timecost = block->ticCounter.QuadPart; // Indeed ;)
|
u64 timecost = block->ticCounter.QuadPart; // Indeed ;)
|
||||||
|
@ -73,8 +73,9 @@ void WriteProfileResults(const char *filename) {
|
||||||
fprintf(f, "origAddr\tblkName\tcost\ttimeCost\tpercent\ttimePercent\tOvAllinBlkTime(ms)\tblkCodeSize\n");
|
fprintf(f, "origAddr\tblkName\tcost\ttimeCost\tpercent\ttimePercent\tOvAllinBlkTime(ms)\tblkCodeSize\n");
|
||||||
for (unsigned int i = 0; i < stats.size(); i++)
|
for (unsigned int i = 0; i < stats.size(); i++)
|
||||||
{
|
{
|
||||||
const Jit64::JitBlock *block = jit.GetBlock(stats[i].blockNum);
|
const JitBlock *block = jit.GetBlockCache()->GetBlock(stats[i].blockNum);
|
||||||
if (block) {
|
if (block)
|
||||||
|
{
|
||||||
std::string name = g_symbolDB.GetDescription(block->originalAddress);
|
std::string name = g_symbolDB.GetDescription(block->originalAddress);
|
||||||
double percent = 100.0 * (double)stats[i].cost / (double)cost_sum;
|
double percent = 100.0 * (double)stats[i].cost / (double)cost_sum;
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
@ -90,4 +91,4 @@ void WriteProfileResults(const char *filename) {
|
||||||
fclose(f);
|
fclose(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} // namespace
|
||||||
|
|
|
@ -216,7 +216,8 @@ void State_Shutdown()
|
||||||
// nothing to do, here for consistency.
|
// nothing to do, here for consistency.
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string MakeStateFilename(int state_number) {
|
std::string MakeStateFilename(int state_number)
|
||||||
|
{
|
||||||
return StringFromFormat(FULL_STATESAVES_DIR "%s.s%02i", Core::GetStartupParameter().GetUniqueID().c_str(), state_number);
|
return StringFromFormat(FULL_STATESAVES_DIR "%s.s%02i", Core::GetStartupParameter().GetUniqueID().c_str(), state_number);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -496,7 +496,9 @@ void CCodeWindow::OnJITOff(wxCommandEvent& event)
|
||||||
// creates the SCoreStartupParameter as a game is loaded
|
// creates the SCoreStartupParameter as a game is loaded
|
||||||
GetMenuBar()->Check(event.GetId(),!event.IsChecked());
|
GetMenuBar()->Check(event.GetId(),!event.IsChecked());
|
||||||
wxMessageBox(_T("Please start a game before changing mode."));
|
wxMessageBox(_T("Please start a game before changing mode."));
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
if (Core::GetState() != Core::CORE_RUN)
|
if (Core::GetState() != Core::CORE_RUN)
|
||||||
{
|
{
|
||||||
switch (event.GetId())
|
switch (event.GetId())
|
||||||
|
@ -504,9 +506,8 @@ void CCodeWindow::OnJITOff(wxCommandEvent& event)
|
||||||
case IDM_JITUNLIMITED:
|
case IDM_JITUNLIMITED:
|
||||||
Core::g_CoreStartupParameter.bJITUnlimitedCache = event.IsChecked();
|
Core::g_CoreStartupParameter.bJITUnlimitedCache = event.IsChecked();
|
||||||
jit.ClearCache(); // allow InitCache() even after the game has started
|
jit.ClearCache(); // allow InitCache() even after the game has started
|
||||||
jit.InitCache();
|
|
||||||
GetMenuBar()->Enable(event.GetId(),!event.IsChecked());
|
GetMenuBar()->Enable(event.GetId(),!event.IsChecked());
|
||||||
break;
|
return; // avoid a second jit.ClearCache
|
||||||
case IDM_JITOFF:
|
case IDM_JITOFF:
|
||||||
Core::g_CoreStartupParameter.bJITOff = event.IsChecked(); break;
|
Core::g_CoreStartupParameter.bJITOff = event.IsChecked(); break;
|
||||||
case IDM_JITLSOFF:
|
case IDM_JITLSOFF:
|
||||||
|
@ -531,15 +532,15 @@ void CCodeWindow::OnJITOff(wxCommandEvent& event)
|
||||||
Core::g_CoreStartupParameter.bJITSystemRegistersOff = event.IsChecked(); break;
|
Core::g_CoreStartupParameter.bJITSystemRegistersOff = event.IsChecked(); break;
|
||||||
}
|
}
|
||||||
jit.ClearCache();
|
jit.ClearCache();
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
//event.Skip(); // this doesn't work
|
//event.Skip(); // this doesn't work
|
||||||
GetMenuBar()->Check(event.GetId(),!event.IsChecked());
|
GetMenuBar()->Check(event.GetId(),!event.IsChecked());
|
||||||
wxMessageBox(_T("Please pause the emulator before changing mode."));
|
wxMessageBox(_T("Please pause the emulator before changing mode."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ==============
|
|
||||||
|
|
||||||
|
|
||||||
void CCodeWindow::OnJitMenu(wxCommandEvent& event)
|
void CCodeWindow::OnJitMenu(wxCommandEvent& event)
|
||||||
{
|
{
|
||||||
|
|
|
@ -138,16 +138,16 @@ void CJitWindow::Compare(u32 em_address)
|
||||||
disassembler x64disasm;
|
disassembler x64disasm;
|
||||||
x64disasm.set_syntax_intel();
|
x64disasm.set_syntax_intel();
|
||||||
|
|
||||||
int block_num = jit.GetBlockNumberFromAddress(em_address);
|
int block_num = jit.GetBlockCache()->GetBlockNumberFromAddress(em_address);
|
||||||
if (block_num < 0)
|
if (block_num < 0)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 500; i++) {
|
for (int i = 0; i < 500; i++) {
|
||||||
block_num = jit.GetBlockNumberFromAddress(em_address - 4 * i);
|
block_num = jit.GetBlockCache()->GetBlockNumberFromAddress(em_address - 4 * i);
|
||||||
if (block_num >= 0)
|
if (block_num >= 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (block_num >= 0) {
|
if (block_num >= 0) {
|
||||||
Jit64::JitBlock *block = jit.GetBlock(block_num);
|
JitBlock *block = jit.GetBlockCache()->GetBlock(block_num);
|
||||||
if (!(block->originalAddress <= em_address && block->originalSize + block->originalAddress >= em_address))
|
if (!(block->originalAddress <= em_address && block->originalSize + block->originalAddress >= em_address))
|
||||||
block_num = -1;
|
block_num = -1;
|
||||||
}
|
}
|
||||||
|
@ -158,13 +158,13 @@ void CJitWindow::Compare(u32 em_address)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Jit64::JitBlock *block = jit.GetBlock(block_num);
|
JitBlock *block = jit.GetBlockCache()->GetBlock(block_num);
|
||||||
|
|
||||||
// 800031f0
|
// 800031f0
|
||||||
// == Fill in x86 box
|
// == Fill in x86 box
|
||||||
|
|
||||||
memset(xDis, 0, 65536);
|
memset(xDis, 0, 65536);
|
||||||
const u8 *code = (const u8 *)jit.GetCompiledCodeFromBlock(block_num);
|
const u8 *code = (const u8 *)jit.GetBlockCache()->GetCompiledCodeFromBlock(block_num);
|
||||||
u64 disasmPtr = (u64)code;
|
u64 disasmPtr = (u64)code;
|
||||||
int size = block->codeSize;
|
int size = block->codeSize;
|
||||||
const u8 *end = code + size;
|
const u8 *end = code + size;
|
||||||
|
|
Loading…
Reference in New Issue