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:
|
||||
virtual ~DebugInterface() {}
|
||||
|
||||
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 int getInstructionSize(int /*instruction*/) {return 1;}
|
||||
|
||||
|
|
|
@ -255,6 +255,15 @@ namespace CPUCompare
|
|||
// 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 ImHereLog = false;
|
||||
static std::map<u32, int> been_here;
|
||||
|
@ -300,7 +309,7 @@ namespace CPUCompare
|
|||
b->exitPtrs[exit_num] = GetWritableCodePtr();
|
||||
|
||||
// Link opportunity!
|
||||
int block = blocks.GetBlockNumberFromAddress(destination);
|
||||
int block = blocks.GetBlockNumberFromStartAddress(destination);
|
||||
if (block >= 0 && jo.enableBlocklink)
|
||||
{
|
||||
// It exists! Joy of joy!
|
||||
|
@ -353,17 +362,17 @@ namespace CPUCompare
|
|||
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);
|
||||
|
||||
// if (emaddress == 0x800aa278)
|
||||
// if (em_address == 0x800aa278)
|
||||
// DebugBreak();
|
||||
|
||||
int size;
|
||||
js.isLastInstruction = false;
|
||||
js.blockStart = emaddress;
|
||||
js.blockStart = em_address;
|
||||
js.fifoBytesThisBlock = 0;
|
||||
js.curBlock = &b;
|
||||
js.blockSetsQuantizers = false;
|
||||
|
@ -373,7 +382,7 @@ namespace CPUCompare
|
|||
//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::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;
|
||||
|
||||
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);
|
||||
fpr.Start(js.fpa);
|
||||
|
||||
js.downcountAmount = js.st.numCycles + PatchEngine::GetSpeedhackCycles(emaddress);
|
||||
js.downcountAmount = js.st.numCycles + PatchEngine::GetSpeedhackCycles(em_address);
|
||||
js.blockSize = size;
|
||||
// Translate instructions
|
||||
for (int i = 0; i < (int)size; i++)
|
||||
|
|
|
@ -128,11 +128,13 @@ public:
|
|||
|
||||
// Jit!
|
||||
|
||||
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 *Jit(u32 em_address); // calls blocks.Jit, which in turn calls DoJit below after setting up a block.
|
||||
const u8* DoJit(u32 em_address, JitBlock &b);
|
||||
|
||||
JitBlockCache *GetBlockCache() { return &blocks; }
|
||||
|
||||
void NotifyBreakpoint(u32 em_address, bool set);
|
||||
|
||||
void ClearCache()
|
||||
{
|
||||
blocks.Clear();
|
||||
|
@ -142,7 +144,7 @@ public:
|
|||
// Run!
|
||||
|
||||
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
|
||||
|
||||
|
@ -274,7 +276,7 @@ public:
|
|||
|
||||
extern Jit64 jit;
|
||||
|
||||
const u8 *Jit(u32 emaddress);
|
||||
const u8 *Jit(u32 em_address);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -64,16 +64,21 @@ AsmRoutineManager asm_routines;
|
|||
// At this offset - 4, there is an int specifying the block number.
|
||||
|
||||
|
||||
#ifdef _M_IX86
|
||||
void AsmRoutineManager::Generate()
|
||||
{
|
||||
enterCode = AlignCode16();
|
||||
#ifdef _M_IX86
|
||||
PUSH(EBP);
|
||||
PUSH(EBX);
|
||||
PUSH(ESI);
|
||||
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();
|
||||
CALL(reinterpret_cast<void *>(&CoreTiming::Advance));
|
||||
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
|
||||
//Jump on negative, not carry!!!
|
||||
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);
|
||||
//TEST(32,M(&PowerPC::ppcState.Exceptions), Imm32(0xFFFFFFFF));
|
||||
//FixupBranch bail2 = J_CC(CC_NZ);
|
||||
|
||||
dispatcherNoCheck = GetCodePtr();
|
||||
MOV(32, R(EAX), M(&PowerPC::ppcState.pc));
|
||||
dispatcherPcInEAX = GetCodePtr();
|
||||
|
||||
#ifdef _M_IX86
|
||||
AND(32, R(EAX), Imm32(Memory::MEMVIEW32_MASK));
|
||||
MOV(32, R(EBX), Imm32((u32)Memory::base));
|
||||
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));
|
||||
FixupBranch notfound = J_CC(CC_NZ);
|
||||
BSWAP(32, EAX);
|
||||
|
@ -113,15 +114,24 @@ void AsmRoutineManager::Generate()
|
|||
ADD(32, M(&PowerPC::ppcState.DebugCount), Imm8(1));
|
||||
}
|
||||
//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));
|
||||
#else
|
||||
JMPptr(MComplex(R15, RAX, 8, 0));
|
||||
#endif
|
||||
SetJumpTarget(notfound);
|
||||
|
||||
//Ok, no block, let's jit
|
||||
#ifdef _M_IX86
|
||||
ABI_AlignStack(4);
|
||||
PUSH(32, M(&PowerPC::ppcState.pc));
|
||||
CALL(reinterpret_cast<void *>(&Jit));
|
||||
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
|
||||
|
||||
//FP blocks test for FPU available, jump here if false
|
||||
|
@ -151,101 +161,22 @@ void AsmRoutineManager::Generate()
|
|||
|
||||
TEST(32, M((void*)&PowerPC::state), Imm32(0xFFFFFFFF));
|
||||
J_CC(CC_Z, outerLoop, true);
|
||||
|
||||
|
||||
#ifdef _M_IX86
|
||||
POP(EDI);
|
||||
POP(ESI);
|
||||
POP(EBX);
|
||||
POP(EBP);
|
||||
#else
|
||||
//Landing pad for drec space
|
||||
ABI_PopAllCalleeSavedRegsAndAdjustStack();
|
||||
RET();
|
||||
#endif
|
||||
RET();
|
||||
|
||||
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
|
||||
ABI_PopAllCalleeSavedRegsAndAdjustStack();
|
||||
RET();
|
||||
|
||||
GenerateCommon();
|
||||
}
|
||||
#endif
|
||||
|
||||
void AsmRoutineManager::GenFifoWrite(int size)
|
||||
{
|
||||
|
|
|
@ -194,7 +194,7 @@ using namespace Gen;
|
|||
return blockCodePointers;
|
||||
}
|
||||
|
||||
int JitBlockCache::GetBlockNumberFromAddress(u32 addr)
|
||||
int JitBlockCache::GetBlockNumberFromStartAddress(u32 addr)
|
||||
{
|
||||
if (!blocks)
|
||||
return -1;
|
||||
|
@ -222,22 +222,13 @@ using namespace Gen;
|
|||
|
||||
u32 JitBlockCache::GetOriginalCode(u32 address)
|
||||
{
|
||||
int num = GetBlockNumberFromAddress(address);
|
||||
int num = GetBlockNumberFromStartAddress(address);
|
||||
if (num == -1)
|
||||
return Memory::ReadUnchecked_U32(address);
|
||||
else
|
||||
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)
|
||||
{
|
||||
return (CompiledCode)blockCodePointers[blockNumber];
|
||||
|
@ -261,7 +252,7 @@ using namespace Gen;
|
|||
{
|
||||
if (b.exitAddress[e] != INVALID_EXIT && !b.linkStatus[e])
|
||||
{
|
||||
int destinationBlock = GetBlockNumberFromAddress(b.exitAddress[e]);
|
||||
int destinationBlock = GetBlockNumberFromStartAddress(b.exitAddress[e]);
|
||||
if (destinationBlock != -1)
|
||||
{
|
||||
XEmitter emit(b.exitPtrs[e]);
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _JITCACHE_H
|
||||
#define _JITCACHE_H
|
||||
|
||||
|
@ -70,34 +71,41 @@ class JitBlockCache
|
|||
std::multimap<u32, int> links_to;
|
||||
|
||||
int MAX_NUM_BLOCKS;
|
||||
bool RangeIntersect(int s1, int e1, int s2, int e2) const;
|
||||
void LinkBlockExits(int i);
|
||||
void LinkBlock(int i);
|
||||
|
||||
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);
|
||||
|
||||
// Fast way to get a block. Only works on the first ppc instruction of a block.
|
||||
int GetBlockNumberFromStartAddress(u32 address);
|
||||
// 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);
|
||||
bool RangeIntersect(int s1, int e1, int s2, int e2) const;
|
||||
|
||||
// Not currently used
|
||||
void DestroyBlocksWithFlag(BlockFlag death_flag);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -393,6 +393,9 @@
|
|||
// A few games use these heavily in video codecs.
|
||||
void Jit64::lmw(UGeckoInstruction inst)
|
||||
{
|
||||
#ifdef _M_IX86
|
||||
Default(inst); return;
|
||||
#else
|
||||
gpr.FlushLockX(ECX);
|
||||
MOV(32, R(EAX), Imm32((u32)(s32)inst.SIMM_16));
|
||||
if (inst.RA)
|
||||
|
@ -407,10 +410,14 @@ void Jit64::lmw(UGeckoInstruction inst)
|
|||
MOV(32, gpr.R(i), R(ECX));
|
||||
}
|
||||
gpr.UnlockAllX();
|
||||
#endif
|
||||
}
|
||||
|
||||
void Jit64::stmw(UGeckoInstruction inst)
|
||||
{
|
||||
#ifdef _M_IX86
|
||||
Default(inst); return;
|
||||
#else
|
||||
gpr.FlushLockX(ECX);
|
||||
MOV(32, R(EAX), Imm32((u32)(s32)inst.SIMM_16));
|
||||
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));
|
||||
}
|
||||
gpr.UnlockAllX();
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -138,11 +138,11 @@ void CJitWindow::Compare(u32 em_address)
|
|||
disassembler x64disasm;
|
||||
x64disasm.set_syntax_intel();
|
||||
|
||||
int block_num = jit.GetBlockCache()->GetBlockNumberFromAddress(em_address);
|
||||
int block_num = jit.GetBlockCache()->GetBlockNumberFromStartAddress(em_address);
|
||||
if (block_num < 0)
|
||||
{
|
||||
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)
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue