diff --git a/Source/Core/Core/Src/Debugger/DebugInterface.h b/Source/Core/Core/Src/Debugger/DebugInterface.h index 819f69073a..3c3413f3f9 100644 --- a/Source/Core/Core/Src/Debugger/DebugInterface.h +++ b/Source/Core/Core/Src/Debugger/DebugInterface.h @@ -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;} diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp index 956a3d5da8..fb874666e2 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp @@ -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 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++) diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit.h b/Source/Core/Core/Src/PowerPC/Jit64/Jit.h index a73b677600..323c5fdd08 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit.h +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit.h @@ -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 diff --git a/Source/Core/Core/Src/PowerPC/Jit64/JitAsm.cpp b/Source/Core/Core/Src/PowerPC/Jit64/JitAsm.cpp index 17d2b508fb..71c72f91c3 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/JitAsm.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/JitAsm.cpp @@ -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(&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(&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(&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) { diff --git a/Source/Core/Core/Src/PowerPC/Jit64/JitCache.cpp b/Source/Core/Core/Src/PowerPC/Jit64/JitCache.cpp index 18a3df758a..37e5392b52 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/JitCache.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/JitCache.cpp @@ -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]); diff --git a/Source/Core/Core/Src/PowerPC/Jit64/JitCache.h b/Source/Core/Core/Src/PowerPC/Jit64/JitCache.h index e3818e965f..2fe648b403 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/JitCache.h +++ b/Source/Core/Core/Src/PowerPC/Jit64/JitCache.h @@ -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 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 diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStore.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStore.cpp index 1406d47c35..fe84930abf 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStore.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStore.cpp @@ -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 } diff --git a/Source/Core/DebuggerWX/Src/JitWindow.cpp b/Source/Core/DebuggerWX/Src/JitWindow.cpp index 4405b8b7fc..1768fd3ef9 100644 --- a/Source/Core/DebuggerWX/Src/JitWindow.cpp +++ b/Source/Core/DebuggerWX/Src/JitWindow.cpp @@ -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; }