Fix 32-bit lmw/stmw (well, disable). Merge the two dispatchers.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@1606 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
614dc1069e
commit
66853d6f1b
|
@ -7,8 +7,9 @@ class DebugInterface
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
virtual ~DebugInterface() {}
|
virtual ~DebugInterface() {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual void disasm(unsigned int /*address*/, char *dest, int max_size) {strcpy(dest, "NODEBUGGER");}
|
virtual void disasm(unsigned int /*address*/, char *dest, int /*max_size*/) {strcpy(dest, "NODEBUGGER");}
|
||||||
virtual void getRawMemoryString(unsigned int /*address*/, char *dest, int /*max_size*/) {strcpy(dest, "NODEBUGGER");}
|
virtual void getRawMemoryString(unsigned int /*address*/, char *dest, int /*max_size*/) {strcpy(dest, "NODEBUGGER");}
|
||||||
virtual int getInstructionSize(int /*instruction*/) {return 1;}
|
virtual int getInstructionSize(int /*instruction*/) {return 1;}
|
||||||
|
|
||||||
|
|
|
@ -255,6 +255,15 @@ namespace CPUCompare
|
||||||
// Yup, just don't do anything.
|
// Yup, just don't do anything.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Jit64::NotifyBreakpoint(u32 em_address, bool set)
|
||||||
|
{
|
||||||
|
int block_num = blocks.GetBlockNumberFromStartAddress(em_address);
|
||||||
|
if (block_num >= 0)
|
||||||
|
{
|
||||||
|
blocks.DestroyBlock(block_num, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static const bool ImHereDebug = false;
|
static const bool ImHereDebug = false;
|
||||||
static const bool ImHereLog = false;
|
static const bool ImHereLog = false;
|
||||||
static std::map<u32, int> been_here;
|
static std::map<u32, int> been_here;
|
||||||
|
@ -300,7 +309,7 @@ namespace CPUCompare
|
||||||
b->exitPtrs[exit_num] = GetWritableCodePtr();
|
b->exitPtrs[exit_num] = GetWritableCodePtr();
|
||||||
|
|
||||||
// Link opportunity!
|
// Link opportunity!
|
||||||
int block = blocks.GetBlockNumberFromAddress(destination);
|
int block = blocks.GetBlockNumberFromStartAddress(destination);
|
||||||
if (block >= 0 && jo.enableBlocklink)
|
if (block >= 0 && jo.enableBlocklink)
|
||||||
{
|
{
|
||||||
// It exists! Joy of joy!
|
// It exists! Joy of joy!
|
||||||
|
@ -353,17 +362,17 @@ namespace CPUCompare
|
||||||
return blocks.Jit(em_address);
|
return blocks.Jit(em_address);
|
||||||
}
|
}
|
||||||
|
|
||||||
const u8* Jit64::DoJit(u32 emaddress, JitBlock &b)
|
const u8* Jit64::DoJit(u32 em_address, JitBlock &b)
|
||||||
{
|
{
|
||||||
if (emaddress == 0)
|
if (em_address == 0)
|
||||||
PanicAlert("ERROR : Trying to compile at 0. LR=%08x", LR);
|
PanicAlert("ERROR : Trying to compile at 0. LR=%08x", LR);
|
||||||
|
|
||||||
// if (emaddress == 0x800aa278)
|
// if (em_address == 0x800aa278)
|
||||||
// DebugBreak();
|
// DebugBreak();
|
||||||
|
|
||||||
int size;
|
int size;
|
||||||
js.isLastInstruction = false;
|
js.isLastInstruction = false;
|
||||||
js.blockStart = emaddress;
|
js.blockStart = em_address;
|
||||||
js.fifoBytesThisBlock = 0;
|
js.fifoBytesThisBlock = 0;
|
||||||
js.curBlock = &b;
|
js.curBlock = &b;
|
||||||
js.blockSetsQuantizers = false;
|
js.blockSetsQuantizers = false;
|
||||||
|
@ -373,7 +382,7 @@ namespace CPUCompare
|
||||||
//Analyze the block, collect all instructions it is made of (including inlining,
|
//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.
|
//if that is enabled), reorder instructions for optimal performance, and join joinable instructions.
|
||||||
|
|
||||||
PPCAnalyst::Flatten(emaddress, &size, &js.st, &js.gpa, &js.fpa, &code_buffer);
|
PPCAnalyst::Flatten(em_address, &size, &js.st, &js.gpa, &js.fpa, &code_buffer);
|
||||||
PPCAnalyst::CodeOp *ops = code_buffer.codebuffer;
|
PPCAnalyst::CodeOp *ops = code_buffer.codebuffer;
|
||||||
|
|
||||||
const u8 *start = AlignCode4(); //TODO: Test if this or AlignCode16 make a difference from GetCodePtr
|
const u8 *start = AlignCode4(); //TODO: Test if this or AlignCode16 make a difference from GetCodePtr
|
||||||
|
@ -430,7 +439,7 @@ namespace CPUCompare
|
||||||
gpr.Start(js.gpa);
|
gpr.Start(js.gpa);
|
||||||
fpr.Start(js.fpa);
|
fpr.Start(js.fpa);
|
||||||
|
|
||||||
js.downcountAmount = js.st.numCycles + PatchEngine::GetSpeedhackCycles(emaddress);
|
js.downcountAmount = js.st.numCycles + PatchEngine::GetSpeedhackCycles(em_address);
|
||||||
js.blockSize = size;
|
js.blockSize = size;
|
||||||
// Translate instructions
|
// Translate instructions
|
||||||
for (int i = 0; i < (int)size; i++)
|
for (int i = 0; i < (int)size; i++)
|
||||||
|
|
|
@ -128,11 +128,13 @@ public:
|
||||||
|
|
||||||
// Jit!
|
// Jit!
|
||||||
|
|
||||||
const u8 *Jit(u32 emAddress); // calls blocks.Jit, which in turn calls DoJit below after setting up a block.
|
const u8 *Jit(u32 em_address); // 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 em_address, JitBlock &b);
|
||||||
|
|
||||||
JitBlockCache *GetBlockCache() { return &blocks; }
|
JitBlockCache *GetBlockCache() { return &blocks; }
|
||||||
|
|
||||||
|
void NotifyBreakpoint(u32 em_address, bool set);
|
||||||
|
|
||||||
void ClearCache()
|
void ClearCache()
|
||||||
{
|
{
|
||||||
blocks.Clear();
|
blocks.Clear();
|
||||||
|
@ -142,7 +144,7 @@ public:
|
||||||
// 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 em_address, CONTEXT *ctx);
|
||||||
|
|
||||||
#define JIT_OPCODE 0
|
#define JIT_OPCODE 0
|
||||||
|
|
||||||
|
@ -274,7 +276,7 @@ public:
|
||||||
|
|
||||||
extern Jit64 jit;
|
extern Jit64 jit;
|
||||||
|
|
||||||
const u8 *Jit(u32 emaddress);
|
const u8 *Jit(u32 em_address);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -64,16 +64,21 @@ AsmRoutineManager asm_routines;
|
||||||
// At this offset - 4, there is an int specifying the block number.
|
// At this offset - 4, there is an int specifying the block number.
|
||||||
|
|
||||||
|
|
||||||
#ifdef _M_IX86
|
|
||||||
void AsmRoutineManager::Generate()
|
void AsmRoutineManager::Generate()
|
||||||
{
|
{
|
||||||
enterCode = AlignCode16();
|
enterCode = AlignCode16();
|
||||||
|
#ifdef _M_IX86
|
||||||
PUSH(EBP);
|
PUSH(EBP);
|
||||||
PUSH(EBX);
|
PUSH(EBX);
|
||||||
PUSH(ESI);
|
PUSH(ESI);
|
||||||
PUSH(EDI);
|
PUSH(EDI);
|
||||||
|
#else
|
||||||
|
ABI_PushAllCalleeSavedRegsAndAdjustStack();
|
||||||
|
// Two statically allocated registers.
|
||||||
|
MOV(64, R(RBX), Imm64((u64)Memory::base));
|
||||||
|
MOV(64, R(R15), Imm64((u64)jit.GetBlockCache()->GetCodePointers())); //It's below 2GB so 32 bits are good enough
|
||||||
|
#endif
|
||||||
|
|
||||||
//MOV(32, R(EBX), Imm32((u32)&Memory::base));
|
|
||||||
const u8 *outerLoop = GetCodePtr();
|
const u8 *outerLoop = GetCodePtr();
|
||||||
CALL(reinterpret_cast<void *>(&CoreTiming::Advance));
|
CALL(reinterpret_cast<void *>(&CoreTiming::Advance));
|
||||||
FixupBranch skipToRealDispatch = J(); //skip the sync and compare first time
|
FixupBranch skipToRealDispatch = J(); //skip the sync and compare first time
|
||||||
|
@ -84,22 +89,18 @@ void AsmRoutineManager::Generate()
|
||||||
//The result of slice decrementation should be in flags if somebody jumped here
|
//The result of slice decrementation should be in flags if somebody jumped here
|
||||||
//Jump on negative, not carry!!!
|
//Jump on negative, not carry!!!
|
||||||
FixupBranch bail = J_CC(CC_BE);
|
FixupBranch bail = J_CC(CC_BE);
|
||||||
if (Core::bReadTrace || Core::bWriteTrace)
|
|
||||||
{
|
|
||||||
CALL(reinterpret_cast<void *>(&Core::SyncTrace));
|
|
||||||
// CMP(32, R(EAX),Imm32(0));
|
|
||||||
// bail2 = J_CC();
|
|
||||||
}
|
|
||||||
SetJumpTarget(skipToRealDispatch);
|
SetJumpTarget(skipToRealDispatch);
|
||||||
//TEST(32,M(&PowerPC::ppcState.Exceptions), Imm32(0xFFFFFFFF));
|
|
||||||
//FixupBranch bail2 = J_CC(CC_NZ);
|
|
||||||
dispatcherNoCheck = GetCodePtr();
|
dispatcherNoCheck = GetCodePtr();
|
||||||
MOV(32, R(EAX), M(&PowerPC::ppcState.pc));
|
MOV(32, R(EAX), M(&PowerPC::ppcState.pc));
|
||||||
dispatcherPcInEAX = GetCodePtr();
|
dispatcherPcInEAX = GetCodePtr();
|
||||||
|
#ifdef _M_IX86
|
||||||
AND(32, R(EAX), Imm32(Memory::MEMVIEW32_MASK));
|
AND(32, R(EAX), Imm32(Memory::MEMVIEW32_MASK));
|
||||||
MOV(32, R(EBX), Imm32((u32)Memory::base));
|
MOV(32, R(EBX), Imm32((u32)Memory::base));
|
||||||
MOV(32, R(EAX), MComplex(EBX, EAX, SCALE_1, 0));
|
MOV(32, R(EAX), MComplex(EBX, EAX, SCALE_1, 0));
|
||||||
|
#else
|
||||||
|
MOV(32, R(EAX), MComplex(RBX, RAX, SCALE_1, 0));
|
||||||
|
#endif
|
||||||
TEST(32, R(EAX), Imm32(0xFC));
|
TEST(32, R(EAX), Imm32(0xFC));
|
||||||
FixupBranch notfound = J_CC(CC_NZ);
|
FixupBranch notfound = J_CC(CC_NZ);
|
||||||
BSWAP(32, EAX);
|
BSWAP(32, EAX);
|
||||||
|
@ -113,15 +114,24 @@ void AsmRoutineManager::Generate()
|
||||||
ADD(32, M(&PowerPC::ppcState.DebugCount), Imm8(1));
|
ADD(32, M(&PowerPC::ppcState.DebugCount), Imm8(1));
|
||||||
}
|
}
|
||||||
//grab from list and jump to it
|
//grab from list and jump to it
|
||||||
MOV(32, R(EDX), ImmPtr(jit.GetCodePointers()));
|
#ifdef _M_IX86
|
||||||
|
MOV(32, R(EDX), ImmPtr(jit.GetBlockCache()->GetCodePointers()));
|
||||||
JMPptr(MComplex(EDX, EAX, 4, 0));
|
JMPptr(MComplex(EDX, EAX, 4, 0));
|
||||||
|
#else
|
||||||
|
JMPptr(MComplex(R15, RAX, 8, 0));
|
||||||
|
#endif
|
||||||
SetJumpTarget(notfound);
|
SetJumpTarget(notfound);
|
||||||
|
|
||||||
//Ok, no block, let's jit
|
//Ok, no block, let's jit
|
||||||
|
#ifdef _M_IX86
|
||||||
ABI_AlignStack(4);
|
ABI_AlignStack(4);
|
||||||
PUSH(32, M(&PowerPC::ppcState.pc));
|
PUSH(32, M(&PowerPC::ppcState.pc));
|
||||||
CALL(reinterpret_cast<void *>(&Jit));
|
CALL(reinterpret_cast<void *>(&Jit));
|
||||||
ABI_RestoreStack(4);
|
ABI_RestoreStack(4);
|
||||||
|
#else
|
||||||
|
MOV(32, R(ABI_PARAM1), M(&PowerPC::ppcState.pc));
|
||||||
|
CALL((void *)&Jit);
|
||||||
|
#endif
|
||||||
JMP(dispatcherNoCheck); // no point in special casing this
|
JMP(dispatcherNoCheck); // no point in special casing this
|
||||||
|
|
||||||
//FP blocks test for FPU available, jump here if false
|
//FP blocks test for FPU available, jump here if false
|
||||||
|
@ -152,100 +162,21 @@ void AsmRoutineManager::Generate()
|
||||||
TEST(32, M((void*)&PowerPC::state), Imm32(0xFFFFFFFF));
|
TEST(32, M((void*)&PowerPC::state), Imm32(0xFFFFFFFF));
|
||||||
J_CC(CC_Z, outerLoop, true);
|
J_CC(CC_Z, outerLoop, true);
|
||||||
|
|
||||||
|
#ifdef _M_IX86
|
||||||
POP(EDI);
|
POP(EDI);
|
||||||
POP(ESI);
|
POP(ESI);
|
||||||
POP(EBX);
|
POP(EBX);
|
||||||
POP(EBP);
|
POP(EBP);
|
||||||
RET();
|
#else
|
||||||
|
|
||||||
GenerateCommon();
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif defined(_M_X64)
|
|
||||||
|
|
||||||
void AsmRoutineManager::Generate()
|
|
||||||
{
|
|
||||||
enterCode = AlignCode16();
|
|
||||||
|
|
||||||
ABI_PushAllCalleeSavedRegsAndAdjustStack();
|
|
||||||
|
|
||||||
MOV(64, R(RBX), Imm64((u64)Memory::base));
|
|
||||||
MOV(64, R(R15), Imm64((u64)jit.GetBlockCache()->GetCodePointers())); //It's below 2GB so 32 bits are good enough
|
|
||||||
const u8 *outerLoop = GetCodePtr();
|
|
||||||
|
|
||||||
CALL((void *)&CoreTiming::Advance);
|
|
||||||
FixupBranch skipToRealDispatch = J(); //skip the sync and compare first time
|
|
||||||
|
|
||||||
dispatcher = GetCodePtr();
|
|
||||||
//The result of slice decrementation should be in flags if somebody jumped here
|
|
||||||
//Jump on negative, not carry!!!
|
|
||||||
FixupBranch bail = J_CC(CC_BE);
|
|
||||||
SetJumpTarget(skipToRealDispatch);
|
|
||||||
|
|
||||||
dispatcherNoCheck = GetCodePtr();
|
|
||||||
MOV(32, R(EAX), M(&PowerPC::ppcState.pc));
|
|
||||||
dispatcherPcInEAX = GetCodePtr();
|
|
||||||
MOV(32, R(EAX), MComplex(RBX, RAX, SCALE_1, 0));
|
|
||||||
TEST(32, R(EAX), Imm32(0xFC));
|
|
||||||
|
|
||||||
FixupBranch notfound = J_CC(CC_NZ);
|
|
||||||
BSWAP(32, EAX);
|
|
||||||
//IDEA - we have 26 bits, why not just use offsets from base of code?
|
|
||||||
if (enableStatistics)
|
|
||||||
{
|
|
||||||
ADD(32, M(&blocksExecuted), Imm8(1));
|
|
||||||
}
|
|
||||||
if (enableDebug)
|
|
||||||
{
|
|
||||||
ADD(32, M(&PowerPC::ppcState.DebugCount), Imm8(1));
|
|
||||||
}
|
|
||||||
//grab from list and jump to it
|
|
||||||
JMPptr(MComplex(R15, RAX, 8, 0));
|
|
||||||
SetJumpTarget(notfound);
|
|
||||||
|
|
||||||
//Ok, no block, let's jit
|
|
||||||
MOV(32, R(ABI_PARAM1), M(&PowerPC::ppcState.pc));
|
|
||||||
CALL((void *)&Jit);
|
|
||||||
JMP(dispatcherNoCheck); // no point in special casing this, not the "fast path"
|
|
||||||
|
|
||||||
//FP blocks test for FPU available, jump here if false
|
|
||||||
fpException = AlignCode4();
|
|
||||||
MOV(32, R(EAX), M(&PC));
|
|
||||||
MOV(32, M(&NPC), R(EAX));
|
|
||||||
OR(32, M(&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_FPU_UNAVAILABLE));
|
|
||||||
CALL((void *)&PowerPC::CheckExceptions);
|
|
||||||
MOV(32, R(EAX), M(&NPC));
|
|
||||||
MOV(32, M(&PC), R(EAX));
|
|
||||||
JMP(dispatcherNoCheck);
|
|
||||||
|
|
||||||
SetJumpTarget(bail);
|
|
||||||
doTiming = GetCodePtr();
|
|
||||||
TEST(32, M(&PC), Imm32(0xFFFFFFFF));
|
|
||||||
FixupBranch mojs = J_CC(CC_NZ);
|
|
||||||
INT3(); // if you hit this, PC == 0 - no good
|
|
||||||
SetJumpTarget(mojs);
|
|
||||||
CALL((void *)&CoreTiming::Advance);
|
|
||||||
|
|
||||||
testExceptions = GetCodePtr();
|
|
||||||
TEST(32, M(&PowerPC::ppcState.Exceptions), Imm32(0xFFFFFFFF));
|
|
||||||
FixupBranch skipExceptions = J_CC(CC_Z);
|
|
||||||
MOV(32, R(EAX), M(&PC));
|
|
||||||
MOV(32, M(&NPC), R(EAX));
|
|
||||||
CALL((void *)&PowerPC::CheckExceptions);
|
|
||||||
MOV(32, R(EAX), M(&NPC));
|
|
||||||
MOV(32, M(&PC), R(EAX));
|
|
||||||
SetJumpTarget(skipExceptions);
|
|
||||||
|
|
||||||
TEST(32, M((void*)&PowerPC::state), Imm32(0xFFFFFFFF));
|
|
||||||
J_CC(CC_Z, outerLoop, true);
|
|
||||||
|
|
||||||
//Landing pad for drec space
|
//Landing pad for drec space
|
||||||
ABI_PopAllCalleeSavedRegsAndAdjustStack();
|
ABI_PopAllCalleeSavedRegsAndAdjustStack();
|
||||||
RET();
|
RET();
|
||||||
|
#endif
|
||||||
|
RET();
|
||||||
|
|
||||||
GenerateCommon();
|
GenerateCommon();
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
void AsmRoutineManager::GenFifoWrite(int size)
|
void AsmRoutineManager::GenFifoWrite(int size)
|
||||||
{
|
{
|
||||||
|
|
|
@ -194,7 +194,7 @@ using namespace Gen;
|
||||||
return blockCodePointers;
|
return blockCodePointers;
|
||||||
}
|
}
|
||||||
|
|
||||||
int JitBlockCache::GetBlockNumberFromAddress(u32 addr)
|
int JitBlockCache::GetBlockNumberFromStartAddress(u32 addr)
|
||||||
{
|
{
|
||||||
if (!blocks)
|
if (!blocks)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -222,22 +222,13 @@ using namespace Gen;
|
||||||
|
|
||||||
u32 JitBlockCache::GetOriginalCode(u32 address)
|
u32 JitBlockCache::GetOriginalCode(u32 address)
|
||||||
{
|
{
|
||||||
int num = GetBlockNumberFromAddress(address);
|
int num = GetBlockNumberFromStartAddress(address);
|
||||||
if (num == -1)
|
if (num == -1)
|
||||||
return Memory::ReadUnchecked_U32(address);
|
return Memory::ReadUnchecked_U32(address);
|
||||||
else
|
else
|
||||||
return blocks[num].originalFirstOpcode;
|
return blocks[num].originalFirstOpcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
CompiledCode JitBlockCache::GetCompiledCode(u32 address)
|
|
||||||
{
|
|
||||||
int num = GetBlockNumberFromAddress(address);
|
|
||||||
if (num == -1)
|
|
||||||
return 0;
|
|
||||||
else
|
|
||||||
return (CompiledCode)blockCodePointers[num];
|
|
||||||
}
|
|
||||||
|
|
||||||
CompiledCode JitBlockCache::GetCompiledCodeFromBlock(int blockNumber)
|
CompiledCode JitBlockCache::GetCompiledCodeFromBlock(int blockNumber)
|
||||||
{
|
{
|
||||||
return (CompiledCode)blockCodePointers[blockNumber];
|
return (CompiledCode)blockCodePointers[blockNumber];
|
||||||
|
@ -261,7 +252,7 @@ using namespace Gen;
|
||||||
{
|
{
|
||||||
if (b.exitAddress[e] != INVALID_EXIT && !b.linkStatus[e])
|
if (b.exitAddress[e] != INVALID_EXIT && !b.linkStatus[e])
|
||||||
{
|
{
|
||||||
int destinationBlock = GetBlockNumberFromAddress(b.exitAddress[e]);
|
int destinationBlock = GetBlockNumberFromStartAddress(b.exitAddress[e]);
|
||||||
if (destinationBlock != -1)
|
if (destinationBlock != -1)
|
||||||
{
|
{
|
||||||
XEmitter emit(b.exitPtrs[e]);
|
XEmitter emit(b.exitPtrs[e]);
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#ifndef _JITCACHE_H
|
#ifndef _JITCACHE_H
|
||||||
#define _JITCACHE_H
|
#define _JITCACHE_H
|
||||||
|
|
||||||
|
@ -70,34 +71,41 @@ class JitBlockCache
|
||||||
std::multimap<u32, int> links_to;
|
std::multimap<u32, int> links_to;
|
||||||
|
|
||||||
int MAX_NUM_BLOCKS;
|
int MAX_NUM_BLOCKS;
|
||||||
|
bool RangeIntersect(int s1, int e1, int s2, int e2) const;
|
||||||
|
void LinkBlockExits(int i);
|
||||||
|
void LinkBlock(int i);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
JitBlockCache() {}
|
JitBlockCache() {}
|
||||||
|
|
||||||
void SetJit(Jit64 *jit_) { jit = jit_; }
|
void SetJit(Jit64 *jit_) { jit = jit_; }
|
||||||
|
|
||||||
const u8* Jit(u32 emaddress);
|
const u8* Jit(u32 emaddress);
|
||||||
|
|
||||||
void Clear();
|
void Clear();
|
||||||
void Init();
|
void Init();
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
void Reset();
|
void Reset();
|
||||||
|
|
||||||
bool IsFull() const;
|
bool IsFull() const;
|
||||||
|
|
||||||
// Code Cache
|
// Code Cache
|
||||||
u32 GetOriginalCode(u32 address);
|
|
||||||
JitBlock *GetBlock(int no);
|
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;
|
int GetNumBlocks() const;
|
||||||
u8 **GetCodePointers();
|
u8 **GetCodePointers();
|
||||||
void DestroyBlocksWithFlag(BlockFlag death_flag);
|
|
||||||
void LinkBlocks();
|
// Fast way to get a block. Only works on the first ppc instruction of a block.
|
||||||
void LinkBlockExits(int i);
|
int GetBlockNumberFromStartAddress(u32 address);
|
||||||
void LinkBlock(int i);
|
// slower, but can get numbers from within blocks, not just the first instruction. WARNING! DOES NOT WORK WITH INLINING ENABLED (not yet a feature but will be soon)
|
||||||
|
int GetBlockNumberFromInternalAddress(u32 address);
|
||||||
|
|
||||||
|
u32 GetOriginalCode(u32 address);
|
||||||
|
CompiledCode GetCompiledCodeFromBlock(int blockNumber);
|
||||||
|
|
||||||
|
// DOES NOT WORK CORRECTLY WITH INLINING
|
||||||
|
void InvalidateCodeRange(u32 address, u32 length);
|
||||||
void DestroyBlock(int blocknum, bool invalidate);
|
void DestroyBlock(int blocknum, bool invalidate);
|
||||||
bool RangeIntersect(int s1, int e1, int s2, int e2) const;
|
|
||||||
|
// Not currently used
|
||||||
|
void DestroyBlocksWithFlag(BlockFlag death_flag);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -393,6 +393,9 @@
|
||||||
// A few games use these heavily in video codecs.
|
// A few games use these heavily in video codecs.
|
||||||
void Jit64::lmw(UGeckoInstruction inst)
|
void Jit64::lmw(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
|
#ifdef _M_IX86
|
||||||
|
Default(inst); return;
|
||||||
|
#else
|
||||||
gpr.FlushLockX(ECX);
|
gpr.FlushLockX(ECX);
|
||||||
MOV(32, R(EAX), Imm32((u32)(s32)inst.SIMM_16));
|
MOV(32, R(EAX), Imm32((u32)(s32)inst.SIMM_16));
|
||||||
if (inst.RA)
|
if (inst.RA)
|
||||||
|
@ -407,10 +410,14 @@ void Jit64::lmw(UGeckoInstruction inst)
|
||||||
MOV(32, gpr.R(i), R(ECX));
|
MOV(32, gpr.R(i), R(ECX));
|
||||||
}
|
}
|
||||||
gpr.UnlockAllX();
|
gpr.UnlockAllX();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Jit64::stmw(UGeckoInstruction inst)
|
void Jit64::stmw(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
|
#ifdef _M_IX86
|
||||||
|
Default(inst); return;
|
||||||
|
#else
|
||||||
gpr.FlushLockX(ECX);
|
gpr.FlushLockX(ECX);
|
||||||
MOV(32, R(EAX), Imm32((u32)(s32)inst.SIMM_16));
|
MOV(32, R(EAX), Imm32((u32)(s32)inst.SIMM_16));
|
||||||
if (inst.RA)
|
if (inst.RA)
|
||||||
|
@ -424,4 +431,5 @@ void Jit64::stmw(UGeckoInstruction inst)
|
||||||
MOV(32, MComplex(EBX, EAX, SCALE_1, (i - inst.RD) * 4), R(ECX));
|
MOV(32, MComplex(EBX, EAX, SCALE_1, (i - inst.RD) * 4), R(ECX));
|
||||||
}
|
}
|
||||||
gpr.UnlockAllX();
|
gpr.UnlockAllX();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -138,11 +138,11 @@ void CJitWindow::Compare(u32 em_address)
|
||||||
disassembler x64disasm;
|
disassembler x64disasm;
|
||||||
x64disasm.set_syntax_intel();
|
x64disasm.set_syntax_intel();
|
||||||
|
|
||||||
int block_num = jit.GetBlockCache()->GetBlockNumberFromAddress(em_address);
|
int block_num = jit.GetBlockCache()->GetBlockNumberFromStartAddress(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.GetBlockCache()->GetBlockNumberFromAddress(em_address - 4 * i);
|
block_num = jit.GetBlockCache()->GetBlockNumberFromStartAddress(em_address - 4 * i);
|
||||||
if (block_num >= 0)
|
if (block_num >= 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue