From 9e14b2575df7824769771eec77d450038c8aae39 Mon Sep 17 00:00:00 2001 From: hrydgard Date: Tue, 28 Oct 2008 22:38:53 +0000 Subject: [PATCH] Random grab-bag of stuff: Finer grained JIT disabling (jpeterson's debug tool), show activated cheats, some comments, one more jitted instruction, support in backpatcher for writes, currently disabled because Beyond Good and Evil crashes when using it. yes this change should be split but i'm just too lazy, sorry. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@996 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Core/Core/Src/ActionReplay.cpp | 7 +- Source/Core/Core/Src/CoreParameter.cpp | 2 + Source/Core/Core/Src/CoreParameter.h | 2 + Source/Core/Core/Src/HW/VideoInterface.cpp | 1 + Source/Core/Core/Src/MemTools.cpp | 5 +- Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp | 7 + Source/Core/Core/Src/PowerPC/Jit64/Jit.h | 4 + .../Core/Src/PowerPC/Jit64/JitBackpatch.cpp | 141 ++++++++++++------ .../Core/Src/PowerPC/Jit64/JitBackpatch.h | 7 +- .../Core/Src/PowerPC/Jit64/JitRegCache.cpp | 7 +- .../Core/Src/PowerPC/Jit64/Jit_Integer.cpp | 17 +++ .../Core/Src/PowerPC/Jit64/Jit_LoadStore.cpp | 18 ++- .../PowerPC/Jit64/Jit_LoadStoreFloating.cpp | 10 +- .../Src/PowerPC/Jit64/Jit_LoadStorePaired.cpp | 4 +- .../Src/PowerPC/Jit64/Jit_SystemRegisters.cpp | 10 ++ .../Core/Core/Src/PowerPC/Jit64/Jit_Util.cpp | 2 + Source/Core/Core/Src/PowerPC/PPCTables.cpp | 4 +- Source/Core/Core/Src/PowerPC/Profiler.h | 11 ++ Source/Core/DebuggerWX/Src/CodeWindow.cpp | 12 ++ Source/Core/DebuggerWX/Src/CodeWindow.h | 6 + 20 files changed, 215 insertions(+), 62 deletions(-) diff --git a/Source/Core/Core/Src/ActionReplay.cpp b/Source/Core/Core/Src/ActionReplay.cpp index 70574b8a48..00b94ff865 100644 --- a/Source/Core/Core/Src/ActionReplay.cpp +++ b/Source/Core/Core/Src/ActionReplay.cpp @@ -99,8 +99,11 @@ void LoadActionReplayCodes(IniFile &ini) encryptedLines.clear(); } currentCode.name = line; - if (line[0] == '+') currentCode.active = true; - else currentCode.active = false; + Core::DisplayMessage("AR code active: " + line, 5000); + if (line[0] == '+') + currentCode.active = true; + else + currentCode.active = false; continue; } diff --git a/Source/Core/Core/Src/CoreParameter.cpp b/Source/Core/Core/Src/CoreParameter.cpp index 2f005328be..609303bbdb 100644 --- a/Source/Core/Core/Src/CoreParameter.cpp +++ b/Source/Core/Core/Src/CoreParameter.cpp @@ -40,6 +40,8 @@ void SCoreStartupParameter::LoadDefaults() bJITOff = false; // debugger only settings bJITLoadStoreOff = false; + bJITLoadStoreFloatingOff = false; + bJITLoadStorePairedOff = false; bJITFloatingPointOff = false; bJITIntegerOff = false; bJITPairedOff = false; diff --git a/Source/Core/Core/Src/CoreParameter.h b/Source/Core/Core/Src/CoreParameter.h index c77c3d4b1e..e3176968be 100644 --- a/Source/Core/Core/Src/CoreParameter.h +++ b/Source/Core/Core/Src/CoreParameter.h @@ -39,6 +39,8 @@ struct SCoreStartupParameter bool bUseJIT; bool bJITOff; bool bJITLoadStoreOff; + bool bJITLoadStoreFloatingOff; + bool bJITLoadStorePairedOff; bool bJITFloatingPointOff; bool bJITIntegerOff; bool bJITPairedOff; diff --git a/Source/Core/Core/Src/HW/VideoInterface.cpp b/Source/Core/Core/Src/HW/VideoInterface.cpp index b7423aeccf..51330a73d3 100644 --- a/Source/Core/Core/Src/HW/VideoInterface.cpp +++ b/Source/Core/Core/Src/HW/VideoInterface.cpp @@ -181,6 +181,7 @@ void DoState(PointerWrap &p) p.Do(LineCount); p.Do(LinesPerField); p.Do(LastTime); + // p.Do(NextXFBRender); // Activate when changing saves next time. } void Init() diff --git a/Source/Core/Core/Src/MemTools.cpp b/Source/Core/Core/Src/MemTools.cpp index e5c04982bc..5bbc6ca3e5 100644 --- a/Source/Core/Core/Src/MemTools.cpp +++ b/Source/Core/Core/Src/MemTools.cpp @@ -80,11 +80,12 @@ LONG NTAPI Handler(PEXCEPTION_POINTERS pPtrs) //We could emulate the memory accesses here, but then they would still be around to take up //execution resources. Instead, we backpatch into a generic memory call and retry. - Jit64::BackPatch(codePtr, accessType, emAddress); + u8 *new_rip = Jit64::BackPatch(codePtr, accessType, emAddress, ctx); // We no longer touch Rip, since we return back to the instruction, after overwriting it with a // trampoline jump and some nops - //ctx->Rip = (DWORD_PTR)codeAddr + info.instructionSize; + if (new_rip) + ctx->Rip = (DWORD_PTR)new_rip; } return (DWORD)EXCEPTION_CONTINUE_EXECUTION; diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp index c64faea0c5..a708973b88 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp @@ -108,7 +108,14 @@ extern int blocksExecuted; (single precision can be used in write gather pipe, specialized fast check added) * AMD only - use movaps instead of movapd when loading ps from memory? * HLE functions like floorf, sin, memcpy, etc - they can be much faster + * ABI optimizations - drop F0-F13 on blr, for example. Watch out for context switching. + CR2-CR4 are non-volatile, rest of CR is volatile -> dropped on blr. + R5-R12 are volatile -> dropped on blr. + * classic inlining across calls. +Metroid wants +subc +subfe Low hanging fruit: stfd -- guaranteed in memory diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit.h b/Source/Core/Core/Src/PowerPC/Jit64/Jit.h index fc5f4e868c..32470eba24 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit.h +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit.h @@ -122,6 +122,7 @@ namespace Jit64 void mfmsr(UGeckoInstruction inst); void mftb(UGeckoInstruction inst); void mtcrf(UGeckoInstruction inst); + void mfcr(UGeckoInstruction inst); void reg_imm(UGeckoInstruction inst); @@ -166,9 +167,12 @@ namespace Jit64 void srwx(UGeckoInstruction inst); void dcbz(UGeckoInstruction inst); void lfsx(UGeckoInstruction inst); + void subfic(UGeckoInstruction inst); void subfcx(UGeckoInstruction inst); void subfx(UGeckoInstruction inst); + void subfex(UGeckoInstruction inst); + void lbzx(UGeckoInstruction inst); void lmw(UGeckoInstruction inst); diff --git a/Source/Core/Core/Src/PowerPC/Jit64/JitBackpatch.cpp b/Source/Core/Core/Src/PowerPC/Jit64/JitBackpatch.cpp index ae8602f9d9..f4e729a86e 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/JitBackpatch.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/JitBackpatch.cpp @@ -19,6 +19,7 @@ #include "Common.h" #include "disasm.h" +#include "JitAsm.h" #include "JitBackpatch.h" #include "../../HW/Memmap.h" @@ -58,28 +59,28 @@ void BackPatchError(const std::string &text, u8 *codePtr, u32 emAddress) { // 1) It's really necessary. We don't know anything about the context. // 2) It doesn't really hurt. Only instructions that access I/O will get these, and there won't be // that many of them in a typical program/game. -void BackPatch(u8 *codePtr, int accessType, u32 emAddress) +u8 *BackPatch(u8 *codePtr, int accessType, u32 emAddress, CONTEXT *ctx) { #ifdef _M_X64 if (!IsInJitCode(codePtr)) - return; // this will become a regular crash real soon after this + return 0; // this will become a regular crash real soon after this - // TODO: also mark and remember the instruction address as known HW memory access, for use in later compiles. - // But to do that we need to be able to reconstruct what instruction wrote this code, and we can't do that yet. u8 *oldCodePtr = GetWritableCodePtr(); InstructionInfo info; if (!DisassembleMov(codePtr, info, accessType)) { BackPatchError("BackPatch - failed to disassemble MOV instruction", codePtr, emAddress); } + /* if (info.isMemoryWrite) { if (!Memory::IsRAMAddress(emAddress, true)) { - PanicAlert("Write to invalid address %08x", emAddress); + PanicAlert("Exception: Caught write to invalid address %08x", emAddress); return; } BackPatchError("BackPatch - determined that MOV is write, not yet supported and should have been caught before", codePtr, emAddress); - } + }*/ + if (info.operandSize != 4) { BackPatchError(StringFromFormat("BackPatch - no support for operand size %i", info.operandSize), codePtr, emAddress); } @@ -89,9 +90,9 @@ void BackPatch(u8 *codePtr, int accessType, u32 emAddress) if (info.otherReg != RBX) PanicAlert("BackPatch : Base reg not RBX." "\n\nAttempted to access %08x.", emAddress); - if (accessType == OP_ACCESS_WRITE) - PanicAlert("BackPatch : Currently only supporting reads." - "\n\nAttempted to write to %08x.", emAddress); + //if (accessType == OP_ACCESS_WRITE) + // PanicAlert("BackPatch : Currently only supporting reads." + // "\n\nAttempted to write to %08x.", emAddress); // OK, let's write a trampoline, and a jump to it. // Later, let's share trampolines. @@ -100,42 +101,94 @@ void BackPatch(u8 *codePtr, int accessType, u32 emAddress) // Next step - support writes, special case FIFO writes. Also, support 32-bit mode. u8 *trampoline = trampolineCodePtr; SetCodePtr(trampolineCodePtr); - // * Save all volatile regs - ABI_PushAllCallerSavedRegsAndAdjustStack(); - // * Set up stack frame. - // * Call ReadMemory32 - //LEA(32, ABI_PARAM1, MDisp((X64Reg)addrReg, info.displacement)); - MOV(32, R(ABI_PARAM1), R((X64Reg)addrReg)); - if (info.displacement) { - ADD(32, R(ABI_PARAM1), Imm32(info.displacement)); - } - switch (info.operandSize) { - //case 1: - // CALL((void *)&Memory::Read_U8); - // break; - case 4: - CALL(ProtectFunction((void *)&Memory::Read_U32, 1)); - break; - default: - BackPatchError(StringFromFormat("We don't handle the size %i yet in backpatch", info.operandSize), codePtr, emAddress); - break; - } - // * Tear down stack frame. - ABI_PopAllCallerSavedRegsAndAdjustStack(); - MOV(32, R(dataReg), R(EAX)); - RET(); - trampolineCodePtr = GetWritableCodePtr(); - SetCodePtr(codePtr); - int bswapNopCount; - // Check the following BSWAP for REX byte - if ((GetCodePtr()[info.instructionSize] & 0xF0) == 0x40) - bswapNopCount = 3; - else - bswapNopCount = 2; - CALL(trampoline); - NOP((int)info.instructionSize + bswapNopCount - 5); - SetCodePtr(oldCodePtr); + if (accessType == 0) + { + // It's a read. Easy. + ABI_PushAllCallerSavedRegsAndAdjustStack(); + MOV(32, R(ABI_PARAM1), R((X64Reg)addrReg)); + if (info.displacement) { + ADD(32, R(ABI_PARAM1), Imm32(info.displacement)); + } + switch (info.operandSize) { + case 4: + CALL(ProtectFunction((void *)&Memory::Read_U32, 1)); + break; + default: + BackPatchError(StringFromFormat("We don't handle the size %i yet in backpatch", info.operandSize), codePtr, emAddress); + break; + } + ABI_PopAllCallerSavedRegsAndAdjustStack(); + MOV(32, R(dataReg), R(EAX)); + RET(); + trampolineCodePtr = GetWritableCodePtr(); + + SetCodePtr(codePtr); + int bswapNopCount; + // Check the following BSWAP for REX byte + if ((GetCodePtr()[info.instructionSize] & 0xF0) == 0x40) + bswapNopCount = 3; + else + bswapNopCount = 2; + CALL(trampoline); + NOP((int)info.instructionSize + bswapNopCount - 5); + SetCodePtr(oldCodePtr); + + return codePtr; + } + else if (accessType == 1) + { + // It's a write. Yay. Remember that we don't have to be super efficient since it's "just" a + // hardware access - we can take shortcuts. + //if (emAddress == 0xCC008000) + // PanicAlert("caught a fifo write"); + if (dataReg != EAX) + PanicAlert("Backpatch write - not through EAX"); + CMP(32, R(addrReg), Imm32(0xCC008000)); + FixupBranch skip_fast = J_CC(CC_NE, false); + MOV(32, R(ABI_PARAM1), R((X64Reg)dataReg)); + CALL((void*)Asm::fifoDirectWrite32); + RET(); + SetJumpTarget(skip_fast); + ABI_PushAllCallerSavedRegsAndAdjustStack(); + if (addrReg != ABI_PARAM1) { + //INT3(); + MOV(32, R(ABI_PARAM1), R((X64Reg)dataReg)); + MOV(32, R(ABI_PARAM2), R((X64Reg)addrReg)); + } else { + MOV(32, R(ABI_PARAM2), R((X64Reg)addrReg)); + MOV(32, R(ABI_PARAM1), R((X64Reg)dataReg)); + } + if (info.displacement) { + ADD(32, R(ABI_PARAM2), Imm32(info.displacement)); + } + switch (info.operandSize) { + case 4: + CALL(ProtectFunction((void *)&Memory::Write_U32, 2)); + break; + default: + BackPatchError(StringFromFormat("We don't handle the size %i yet in backpatch", info.operandSize), codePtr, emAddress); + break; + } + ABI_PopAllCallerSavedRegsAndAdjustStack(); + RET(); + + trampolineCodePtr = GetWritableCodePtr(); + + // We know it's EAX so the BSWAP before will be two byte. Overwrite it. + SetCodePtr(codePtr - 2); + CALL(trampoline); + NOP((int)info.instructionSize - 3); + if (info.instructionSize < 3) + PanicAlert("instruction too small"); + SetCodePtr(oldCodePtr); + + // We entered here with a BSWAP-ed EAX. We'll have to swap it back. + ctx->Rax = _byteswap_ulong(ctx->Rax); + + return codePtr - 2; + } + return 0; #endif } diff --git a/Source/Core/Core/Src/PowerPC/Jit64/JitBackpatch.h b/Source/Core/Core/Src/PowerPC/Jit64/JitBackpatch.h index e64439983c..0c39151e46 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/JitBackpatch.h +++ b/Source/Core/Core/Src/PowerPC/Jit64/JitBackpatch.h @@ -20,8 +20,13 @@ #include "Common.h" +#ifdef _WIN32 +#include +#endif + namespace Jit64 { -void BackPatch(u8 *codePtr, int accessType, u32 emAddress); +// Returns the new RIP value +u8 *BackPatch(u8 *codePtr, int accessType, u32 emAddress, CONTEXT *ctx); } #endif diff --git a/Source/Core/Core/Src/PowerPC/Jit64/JitRegCache.cpp b/Source/Core/Core/Src/PowerPC/Jit64/JitRegCache.cpp index 16649ba64a..645475d92e 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/JitRegCache.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/JitRegCache.cpp @@ -46,17 +46,18 @@ namespace Jit64 } // todo: sort to find the most popular regs - int maxPreload = 3; + /* + int maxPreload = 2; for (int i = 0; i < 32; i++) { if (stats.numReads[i] > 2 || stats.numWrites[i] >= 2) { - LoadToX64(i, true, false); //, stats.firstRead[i] <= stats.firstWrite[i], false); + LoadToX64(i, true, false); //stats.firstRead[i] <= stats.firstWrite[i], false); maxPreload--; if (!maxPreload) break; } - } + }*/ //Find top regs - preload them (load bursts ain't bad) //But only preload IF written OR reads >= 3 } diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp index a4ac9376d1..cdccc5abf2 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp @@ -436,6 +436,23 @@ namespace Jit64 */ } + void subfex(UGeckoInstruction inst) + { + INSTRUCTION_START; + Default(inst); + return; + /* + u32 a = m_GPR[_inst.RA]; + u32 b = m_GPR[_inst.RB]; + int carry = GetCarry(); + m_GPR[_inst.RD] = (~a) + b + carry; + SetCarry(Helper_Carry(~a, b) || Helper_Carry((~a) + b, carry)); + + if (_inst.OE) PanicAlert("OE: subfcx"); + if (_inst.Rc) Helper_UpdateCR0(m_GPR[_inst.RD]); + */ + } + void subfx(UGeckoInstruction inst) { #ifdef JIT_OFF_OPTIONS diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStore.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStore.cpp index 100feafad7..7ffa35babd 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStore.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStore.cpp @@ -112,6 +112,9 @@ namespace Jit64 return; } + // R2 always points to the small read-only data area. We could bake R2-relative loads into immediates. + // R13 always points to the small read/write data area. Not so exciting but at least could drop checks in 32-bit safe mode. + s32 offset = (s32)(s16)inst.SIMM_16; if (!a) { @@ -293,6 +296,19 @@ namespace Jit64 return; } + /* // TODO - figure out why Beyond Good and Evil hates this +#ifdef _M_X64 + if (accessSize == 32 && !update && jo.enableFastMem) + { + // Fast and daring - requires 64-bit + MOV(32, R(EAX), gpr.R(s)); + gpr.LoadToX64(a, true, false); + BSWAP(32, EAX); + MOV(accessSize, MComplex(RBX, gpr.RX(a), SCALE_1, (u32)offset), R(EAX)); + return; + } +#endif*/ + //Still here? Do regular path. #ifndef _WIN32 if(accessSize == 8) @@ -345,6 +361,7 @@ namespace Jit64 INSTRUCTION_START; Default(inst); return; + /* /// BUGGY //return _inst.RA ? (m_GPR[_inst.RA] + _inst.SIMM_16) : _inst.SIMM_16; @@ -363,7 +380,6 @@ namespace Jit64 ADD(32, R(ESI), Imm8(4)); ADD(32, R(ECX), Imm8(1)); CMP(32, R(ECX), Imm8(32)); - J_CC(CC_NE, loopPtr, false); gpr.UnlockAllX();*/ } diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStoreFloating.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStoreFloating.cpp index 4b0b8249ba..740149554d 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStoreFloating.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStoreFloating.cpp @@ -67,7 +67,7 @@ u32 GC_ALIGNED16(temp32); void lfs(UGeckoInstruction inst) { #ifdef JIT_OFF_OPTIONS - if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITLoadStoreOff) + if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITLoadStoreFloatingOff) {Default(inst); return;} // turn off from debugger #endif INSTRUCTION_START; @@ -107,7 +107,7 @@ void lfd(UGeckoInstruction inst) Default(inst); return; #ifdef JIT_OFF_OPTIONS - if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITLoadStoreOff) + if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITLoadStoreFloatingOff) {Default(inst); return;} // turn off from debugger #endif INSTRUCTION_START; @@ -155,7 +155,7 @@ void lfd(UGeckoInstruction inst) void stfd(UGeckoInstruction inst) { #ifdef JIT_OFF_OPTIONS - if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITLoadStoreOff) + if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITLoadStoreFloatingOff) {Default(inst); return;} // turn off from debugger #endif INSTRUCTION_START; @@ -202,7 +202,7 @@ void stfd(UGeckoInstruction inst) void stfs(UGeckoInstruction inst) { #ifdef JIT_OFF_OPTIONS - if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITLoadStoreOff) + if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITLoadStoreFloatingOff) {Default(inst); return;} // turn off from debugger #endif INSTRUCTION_START; @@ -269,7 +269,7 @@ void stfsx(UGeckoInstruction inst) void lfsx(UGeckoInstruction inst) { #ifdef JIT_OFF_OPTIONS - if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITLoadStoreOff) + if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITLoadStoreFloatingOff) {Default(inst); return;} // turn off from debugger #endif INSTRUCTION_START; diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStorePaired.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStorePaired.cpp index 750e2ff5fb..f3ead8e61c 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStorePaired.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStorePaired.cpp @@ -110,7 +110,7 @@ const double GC_ALIGNED16(m_dequantizeTableD[]) = void psq_st(UGeckoInstruction inst) { #ifdef JIT_OFF_OPTIONS - if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITLoadStoreOff) + if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITLoadStorePairedOff) {Default(inst); return;} // turn off from debugger #endif INSTRUCTION_START; @@ -302,7 +302,7 @@ void psq_st(UGeckoInstruction inst) void psq_l(UGeckoInstruction inst) { #ifdef JIT_OFF_OPTIONS - if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITLoadStoreOff) + if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITLoadStorePairedOff) {Default(inst); return;} // turn off from debugger #endif INSTRUCTION_START; diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit_SystemRegisters.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit_SystemRegisters.cpp index fce6f05268..8e0f2cfa2d 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit_SystemRegisters.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit_SystemRegisters.cpp @@ -49,6 +49,7 @@ namespace Jit64 { case SPR_LR: case SPR_CTR: + case SPR_XER: // These are safe to do the easy way, see the bottom of this function. break; @@ -157,6 +158,13 @@ namespace Jit64 mfspr(inst); } + void mfcr(UGeckoInstruction inst) + { + int d = inst.RD; + gpr.LoadToX64(d, false, true); + MOV(32, gpr.R(d), M(&PowerPC::ppcState.cr)); + } + void mtcrf(UGeckoInstruction inst) { u32 mask = 0; @@ -180,5 +188,7 @@ namespace Jit64 } gpr.UnlockAllX(); } + + } diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit_Util.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit_Util.cpp index 4af056d6c6..26bd014c6a 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit_Util.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit_Util.cpp @@ -131,10 +131,12 @@ void WriteFloatToConstRamAddress(const Gen::X64Reg& xmm_reg, u32 address) } void ForceSinglePrecisionS(X64Reg xmm) { + // Most games don't need these. Zelda requires it though - some platforms get stuck without them. CVTSD2SS(xmm, R(xmm)); CVTSS2SD(xmm, R(xmm)); } void ForceSinglePrecisionP(X64Reg xmm) { + // Most games don't need these. Zelda requires it though - some platforms get stuck without them. CVTPD2PS(xmm, R(xmm)); CVTPS2PD(xmm, R(xmm)); } diff --git a/Source/Core/Core/Src/PowerPC/PPCTables.cpp b/Source/Core/Core/Src/PowerPC/PPCTables.cpp index b2d76d57ce..6733f59375 100644 --- a/Source/Core/Core/Src/PowerPC/PPCTables.cpp +++ b/Source/Core/Core/Src/PowerPC/PPCTables.cpp @@ -357,7 +357,7 @@ GekkoOPTemplate table31[] = {759, Interpreter::stfdux, Jit64::Default, {"stfdux", OPTYPE_STOREFP, FL_IN_A | FL_IN_B}}, {983, Interpreter::stfiwx, Jit64::Default, {"stfiwx", OPTYPE_STOREFP, FL_IN_A0 | FL_IN_B}}, - {19, Interpreter::mfcr, Jit64::Default, {"mfcr", OPTYPE_SYSTEM, 0}}, + {19, Interpreter::mfcr, Jit64::mfcr, {"mfcr", OPTYPE_SYSTEM, 0}}, {83, Interpreter::mfmsr, Jit64::mfmsr, {"mfmsr", OPTYPE_SYSTEM, 0}}, {144, Interpreter::mtcrf, Jit64::mtcrf, {"mtcrf", OPTYPE_SYSTEM, 0}}, {146, Interpreter::mtmsr, Jit64::mtmsr, {"mtmsr", OPTYPE_SYSTEM, FL_ENDBLOCK}}, @@ -399,7 +399,7 @@ GekkoOPTemplate table31_2[] = {104, Interpreter::negx, Jit64::negx, {"negx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A | FL_IN_B | FL_RC_BIT}}, {40, Interpreter::subfx, Jit64::subfx, {"subfx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A | FL_IN_B | FL_RC_BIT}}, {8, Interpreter::subfcx, Jit64::subfcx, {"subfcx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A | FL_IN_B | FL_SET_CA | FL_RC_BIT}}, - {136, Interpreter::subfex, Jit64::Default, {"subfex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A | FL_IN_B | FL_READ_CA | FL_SET_CA | FL_RC_BIT}}, + {136, Interpreter::subfex, Jit64::subfex, {"subfex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A | FL_IN_B | FL_READ_CA | FL_SET_CA | FL_RC_BIT}}, {232, Interpreter::subfmex, Jit64::Default, {"subfmex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A | FL_IN_B | FL_READ_CA | FL_SET_CA | FL_RC_BIT}}, {200, Interpreter::subfzex, Jit64::Default, {"subfzex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A | FL_IN_B | FL_READ_CA | FL_SET_CA | FL_RC_BIT}}, }; diff --git a/Source/Core/Core/Src/PowerPC/Profiler.h b/Source/Core/Core/Src/PowerPC/Profiler.h index 0dae6dbfd1..e07a1f1e02 100644 --- a/Source/Core/Core/Src/PowerPC/Profiler.h +++ b/Source/Core/Core/Src/PowerPC/Profiler.h @@ -20,6 +20,8 @@ #define _PROFILER_H #ifdef _WIN32 + +#ifdef _M_IX86 #define PROFILER_QUERY_PERFORMACE_COUNTER(pt) \ LEA(32, EAX, M(pt)); PUSH(EAX); \ CALL(QueryPerformanceCounter) @@ -38,6 +40,15 @@ #define PROFILER_VPUSH PUSH(EAX);PUSH(ECX);PUSH(EDX) #define PROFILER_VPOP POP(EDX);POP(ECX);POP(EAX) + +#else + +#define PROFILER_QUERY_PERFORMACE_COUNTER(pt) +#define PROFILER_ADD_DIFF_LARGE_INTEGER(pdt, pt1, pt0) +#define PROFILER_VPUSH +#define PROFILER_VPOP +#endif + #else // TODO #define PROFILER_QUERY_PERFORMACE_COUNTER(pt) diff --git a/Source/Core/DebuggerWX/Src/CodeWindow.cpp b/Source/Core/DebuggerWX/Src/CodeWindow.cpp index 1499c7a9ad..b9dba465ea 100644 --- a/Source/Core/DebuggerWX/Src/CodeWindow.cpp +++ b/Source/Core/DebuggerWX/Src/CodeWindow.cpp @@ -92,6 +92,8 @@ BEGIN_EVENT_TABLE(CCodeWindow, wxFrame) EVT_MENU(IDM_INTERPRETER, CCodeWindow::OnInterpreter) // CPU Mode EVT_MENU(IDM_JITOFF, CCodeWindow::OnJITOff) EVT_MENU(IDM_JITLSOFF, CCodeWindow::OnJITLSOff) + EVT_MENU(IDM_JITLSFOFF, CCodeWindow::OnJITLSFOff) + EVT_MENU(IDM_JITLSPOFF, CCodeWindow::OnJITLSPOff) EVT_MENU(IDM_JITFPOFF, CCodeWindow::OnJITFPOff) EVT_MENU(IDM_JITIOFF, CCodeWindow::OnJITIOff) EVT_MENU(IDM_JITPOFF, CCodeWindow::OnJITPOff) @@ -334,6 +336,12 @@ void CCodeWindow::CreateMenu(const SCoreStartupParameter& _LocalCoreStartupParam jitlsoff = pCoreMenu->Append(IDM_JITLSOFF, _T("&JIT LoadStore off"), wxEmptyString, wxITEM_CHECK); jitlsoff->Check(_LocalCoreStartupParameter.bJITLoadStoreOff); + jitlspoff = pCoreMenu->Append(IDM_JITLSFOFF, _T("&JIT LoadStore Floating off"), wxEmptyString, wxITEM_CHECK); + jitlspoff->Check(_LocalCoreStartupParameter.bJITLoadStoreFloatingOff); + + jitlsfoff = pCoreMenu->Append(IDM_JITLSPOFF, _T("&JIT LoadStore Paired off"), wxEmptyString, wxITEM_CHECK); + jitlsfoff->Check(_LocalCoreStartupParameter.bJITLoadStorePairedOff); + jitfpoff = pCoreMenu->Append(IDM_JITFPOFF, _T("&JIT FloatingPoint off"), wxEmptyString, wxITEM_CHECK); jitfpoff->Check(_LocalCoreStartupParameter.bJITFloatingPointOff); @@ -470,6 +478,10 @@ void CCodeWindow::OnJITOff(wxCommandEvent& event) {DoJITOff(event, jitoff, Core::g_CoreStartupParameter.bJITOff);} void CCodeWindow::OnJITLSOff(wxCommandEvent& event) {DoJITOff(event, jitlsoff, Core::g_CoreStartupParameter.bJITLoadStoreOff);} +void CCodeWindow::OnJITLSFOff(wxCommandEvent& event) {DoJITOff(event, jitlsoff, + Core::g_CoreStartupParameter.bJITLoadStoreFloatingOff);} +void CCodeWindow::OnJITLSPOff(wxCommandEvent& event) {DoJITOff(event, jitlsoff, + Core::g_CoreStartupParameter.bJITLoadStorePairedOff);} void CCodeWindow::OnJITFPOff(wxCommandEvent& event) {DoJITOff(event, jitfpoff, Core::g_CoreStartupParameter.bJITFloatingPointOff);} void CCodeWindow::OnJITIOff(wxCommandEvent& event) {DoJITOff(event, jitioff, diff --git a/Source/Core/DebuggerWX/Src/CodeWindow.h b/Source/Core/DebuggerWX/Src/CodeWindow.h index b4ad9c74b3..138ffef4c7 100644 --- a/Source/Core/DebuggerWX/Src/CodeWindow.h +++ b/Source/Core/DebuggerWX/Src/CodeWindow.h @@ -81,6 +81,8 @@ class CCodeWindow IDM_INTERPRETER, IDM_JITOFF, // jit IDM_JITLSOFF, + IDM_JITLSPOFF, + IDM_JITLSFOFF, IDM_JITIOFF, IDM_JITFPOFF, IDM_JITPOFF, @@ -129,6 +131,8 @@ class CCodeWindow wxMenuItem* jitoff; wxMenuItem* jitlsoff; + wxMenuItem* jitlspoff; + wxMenuItem* jitlsfoff; wxMenuItem* jitfpoff; wxMenuItem* jitioff; wxMenuItem* jitpoff; @@ -173,6 +177,8 @@ class CCodeWindow void OnInterpreter(wxCommandEvent& event); // cpu mode menu void OnJITOff(wxCommandEvent& event); void OnJITLSOff(wxCommandEvent& event); + void OnJITLSPOff(wxCommandEvent& event); + void OnJITLSFOff(wxCommandEvent& event); void OnJITFPOff(wxCommandEvent& event); void OnJITIOff(wxCommandEvent& event); void OnJITPOff(wxCommandEvent& event);