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:
hrydgard 2008-12-20 12:46:14 +00:00
parent 614dc1069e
commit 66853d6f1b
8 changed files with 86 additions and 136 deletions

View File

@ -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;}

View File

@ -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++)

View File

@ -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

View File

@ -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)
{

View File

@ -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]);

View File

@ -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

View File

@ -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
}

View File

@ -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;
}