From f1295f6262623745bdf1d2e0776f0fc1aedc05df Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 19 Jan 2013 02:48:48 -0800 Subject: [PATCH 1/9] Don't muck with currentMIPS->r in the slowmem jit. --- Common/ABI.cpp | 26 +++++++++++++++++ Common/x64Emitter.h | 1 + Core/MIPS/x86/CompLoadStore.cpp | 50 ++++++++++++++++++--------------- 3 files changed, 55 insertions(+), 22 deletions(-) diff --git a/Common/ABI.cpp b/Common/ABI.cpp index f0489e346d..4a79b64434 100644 --- a/Common/ABI.cpp +++ b/Common/ABI.cpp @@ -170,6 +170,16 @@ void XEmitter::ABI_CallFunctionACC(void *func, const Gen::OpArg &arg1, u32 param ABI_RestoreStack(3 * 4); } +void XEmitter::ABI_CallFunctionAAC(void *func, const Gen::OpArg &arg1, const Gen::OpArg &arg2, u32 param3) +{ + ABI_AlignStack(3 * 4); + PUSH(32, Imm32(param3)); + PUSH(32, arg2); + PUSH(32, arg1); + CALL(func); + ABI_RestoreStack(3 * 4); +} + void XEmitter::ABI_CallFunctionA(void *func, const Gen::OpArg &arg1) { ABI_AlignStack(1 * 4); @@ -430,6 +440,22 @@ void XEmitter::ABI_CallFunctionACC(void *func, const Gen::OpArg &arg1, u32 param } } +void XEmitter::ABI_CallFunctionAAC(void *func, const Gen::OpArg &arg1, const Gen::OpArg &arg2, u32 param3) +{ + MOV(32, R(ABI_PARAM1), arg1); + MOV(32, R(ABI_PARAM2), arg2); + MOV(64, R(ABI_PARAM3), Imm64(param3)); + u64 distance = u64(func) - (u64(code) + 5); + if (distance >= 0x0000000080000000ULL + && distance < 0xFFFFFFFF80000000ULL) { + // Far call + MOV(64, R(RAX), Imm64((u64)func)); + CALLptr(R(RAX)); + } else { + CALL(func); + } +} + void XEmitter::ABI_CallFunctionA(void *func, const Gen::OpArg &arg1) { if (!arg1.IsSimpleReg(ABI_PARAM1)) diff --git a/Common/x64Emitter.h b/Common/x64Emitter.h index e0b85e6b85..fb8ec8694b 100644 --- a/Common/x64Emitter.h +++ b/Common/x64Emitter.h @@ -657,6 +657,7 @@ public: void ABI_CallFunctionPPC(void *func, void *param1, void *param2,u32 param3); void ABI_CallFunctionAC(void *func, const Gen::OpArg &arg1, u32 param2); void ABI_CallFunctionACC(void *func, const Gen::OpArg &arg1, u32 param2, u32 param3); + void ABI_CallFunctionAAC(void *func, const Gen::OpArg &arg1, const Gen::OpArg &arg2, u32 param3); void ABI_CallFunctionA(void *func, const Gen::OpArg &arg1); // Pass a register as a paremeter. diff --git a/Core/MIPS/x86/CompLoadStore.cpp b/Core/MIPS/x86/CompLoadStore.cpp index f53338823a..1b9695612b 100644 --- a/Core/MIPS/x86/CompLoadStore.cpp +++ b/Core/MIPS/x86/CompLoadStore.cpp @@ -41,24 +41,24 @@ namespace MIPSComp { - static void ReadMemSafe32(u32 addr, int preg, u32 offset) + static u32 ReadMemSafe32(u32 addr, u32 offset) { - currentMIPS->r[preg] = Memory::Read_U32(addr + offset); + return Memory::Read_U32(addr + offset); } - static void ReadMemSafe16(u32 addr, int preg, u32 offset) + static u32 ReadMemSafe16(u32 addr, u32 offset) { - currentMIPS->r[preg] = Memory::Read_U16(addr + offset); + return Memory::Read_U16(addr + offset); } - static void WriteMemSafe32(u32 addr, int preg, u32 offset) + static void WriteMemSafe32(u32 addr, u32 value, u32 offset) { - Memory::Write_U32(currentMIPS->r[preg], addr + offset); + Memory::Write_U32(value, addr + offset); } - static void WriteMemSafe16(u32 addr, int preg, u32 offset) + static void WriteMemSafe16(u32 addr, u32 value, u32 offset) { - Memory::Write_U16(currentMIPS->r[preg], addr + offset); + Memory::Write_U16(value, addr + offset); } void Jit::Comp_ITypeMem(u32 op) @@ -92,14 +92,16 @@ namespace MIPSComp #else MOVZX(32, 16, gpr.RX(rt), MComplex(RBX, EAX, SCALE_1, offset)); #endif - gpr.UnlockAll(); - FlushAll(); FixupBranch skip = J(); SetJumpTarget(tooLow); SetJumpTarget(tooHigh); - ABI_CallFunctionACC((void *) &ReadMemSafe16, gpr.R(rs), rt, offset); + + ABI_CallFunctionAC((void *) &ReadMemSafe16, R(EAX), offset); + MOVZX(32, 16, gpr.RX(rt), R(EAX)); + SetJumpTarget(skip); + gpr.UnlockAll(); } else { @@ -139,14 +141,16 @@ namespace MIPSComp #else MOV(32, gpr.R(rt), MComplex(RBX, EAX, SCALE_1, offset)); #endif - gpr.UnlockAll(); - FlushAll(); FixupBranch skip = J(); SetJumpTarget(tooLow); SetJumpTarget(tooHigh); - ABI_CallFunctionACC((void *) &ReadMemSafe32, gpr.R(rs), rt, offset); + + ABI_CallFunctionAC((void *) &ReadMemSafe32, R(EAX), offset); + MOV(32, gpr.R(rt), R(EAX)); + SetJumpTarget(skip); + gpr.UnlockAll(); } else { @@ -177,7 +181,7 @@ namespace MIPSComp FlushAll(); gpr.Lock(rt, rs); - gpr.BindToRegister(rt, true, true); + gpr.BindToRegister(rt, true, false); MOV(32, R(EAX), gpr.R(rs)); CMP(32, R(EAX), Imm32(0x08000000)); @@ -189,14 +193,15 @@ namespace MIPSComp #else MOV(16, MComplex(RBX, EAX, SCALE_1, offset), gpr.R(rt)); #endif - gpr.UnlockAll(); - FlushAll(); FixupBranch skip = J(); SetJumpTarget(tooLow); SetJumpTarget(tooHigh); - ABI_CallFunctionACC((void *) &WriteMemSafe16, gpr.R(rs), rt, offset); + + ABI_CallFunctionAAC((void *) &WriteMemSafe16, R(EAX), gpr.R(rt), offset); + SetJumpTarget(skip); + gpr.UnlockAll(); } else { @@ -220,7 +225,7 @@ namespace MIPSComp FlushAll(); gpr.Lock(rt, rs); - gpr.BindToRegister(rt, true, true); + gpr.BindToRegister(rt, true, false); MOV(32, R(EAX), gpr.R(rs)); CMP(32, R(EAX), Imm32(0x08000000)); @@ -232,14 +237,15 @@ namespace MIPSComp #else MOV(32, MComplex(RBX, EAX, SCALE_1, offset), gpr.R(rt)); #endif - gpr.UnlockAll(); - FlushAll(); FixupBranch skip = J(); SetJumpTarget(tooLow); SetJumpTarget(tooHigh); - ABI_CallFunctionACC((void *) &WriteMemSafe32, gpr.R(rs), rt, offset); + + ABI_CallFunctionAAC((void *) &WriteMemSafe32, R(EAX), gpr.R(rt), offset); + SetJumpTarget(skip); + gpr.UnlockAll(); } else { From 5305017fc3a5356f9611475fe8ed8fea70a2a90d Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 19 Jan 2013 10:49:19 -0800 Subject: [PATCH 2/9] Properly save registers before the slowmem call. --- Common/ABI.cpp | 30 ++++++++++++------------- Common/x64Emitter.h | 2 +- Core/MIPS/x86/CompLoadStore.cpp | 40 +++++++-------------------------- Core/MIPS/x86/Jit.h | 2 ++ 4 files changed, 26 insertions(+), 48 deletions(-) diff --git a/Common/ABI.cpp b/Common/ABI.cpp index 4a79b64434..3d0d792984 100644 --- a/Common/ABI.cpp +++ b/Common/ABI.cpp @@ -170,16 +170,6 @@ void XEmitter::ABI_CallFunctionACC(void *func, const Gen::OpArg &arg1, u32 param ABI_RestoreStack(3 * 4); } -void XEmitter::ABI_CallFunctionAAC(void *func, const Gen::OpArg &arg1, const Gen::OpArg &arg2, u32 param3) -{ - ABI_AlignStack(3 * 4); - PUSH(32, Imm32(param3)); - PUSH(32, arg2); - PUSH(32, arg1); - CALL(func); - ABI_RestoreStack(3 * 4); -} - void XEmitter::ABI_CallFunctionA(void *func, const Gen::OpArg &arg1) { ABI_AlignStack(1 * 4); @@ -188,6 +178,15 @@ void XEmitter::ABI_CallFunctionA(void *func, const Gen::OpArg &arg1) ABI_RestoreStack(1 * 4); } +void XEmitter::ABI_CallFunctionAA(void *func, const Gen::OpArg &arg1, const Gen::OpArg &arg2) +{ + ABI_AlignStack(2 * 4); + PUSH(32, arg2); + PUSH(32, arg1); + CALL(func); + ABI_RestoreStack(2 * 4); +} + void XEmitter::ABI_PushAllCalleeSavedRegsAndAdjustStack() { // Note: 4 * 4 = 16 bytes, so alignment is preserved. PUSH(EBP); @@ -440,11 +439,10 @@ void XEmitter::ABI_CallFunctionACC(void *func, const Gen::OpArg &arg1, u32 param } } -void XEmitter::ABI_CallFunctionAAC(void *func, const Gen::OpArg &arg1, const Gen::OpArg &arg2, u32 param3) +void XEmitter::ABI_CallFunctionA(void *func, const Gen::OpArg &arg1) { - MOV(32, R(ABI_PARAM1), arg1); - MOV(32, R(ABI_PARAM2), arg2); - MOV(64, R(ABI_PARAM3), Imm64(param3)); + if (!arg1.IsSimpleReg(ABI_PARAM1)) + MOV(32, R(ABI_PARAM1), arg1); u64 distance = u64(func) - (u64(code) + 5); if (distance >= 0x0000000080000000ULL && distance < 0xFFFFFFFF80000000ULL) { @@ -456,10 +454,12 @@ void XEmitter::ABI_CallFunctionAAC(void *func, const Gen::OpArg &arg1, const Gen } } -void XEmitter::ABI_CallFunctionA(void *func, const Gen::OpArg &arg1) +void XEmitter::ABI_CallFunctionAA(void *func, const Gen::OpArg &arg1, const Gen::OpArg &arg2) { if (!arg1.IsSimpleReg(ABI_PARAM1)) MOV(32, R(ABI_PARAM1), arg1); + if (!arg2.IsSimpleReg(ABI_PARAM2)) + MOV(32, R(ABI_PARAM2), arg2); u64 distance = u64(func) - (u64(code) + 5); if (distance >= 0x0000000080000000ULL && distance < 0xFFFFFFFF80000000ULL) { diff --git a/Common/x64Emitter.h b/Common/x64Emitter.h index fb8ec8694b..cb690593a3 100644 --- a/Common/x64Emitter.h +++ b/Common/x64Emitter.h @@ -657,8 +657,8 @@ public: void ABI_CallFunctionPPC(void *func, void *param1, void *param2,u32 param3); void ABI_CallFunctionAC(void *func, const Gen::OpArg &arg1, u32 param2); void ABI_CallFunctionACC(void *func, const Gen::OpArg &arg1, u32 param2, u32 param3); - void ABI_CallFunctionAAC(void *func, const Gen::OpArg &arg1, const Gen::OpArg &arg2, u32 param3); void ABI_CallFunctionA(void *func, const Gen::OpArg &arg1); + void ABI_CallFunctionAA(void *func, const Gen::OpArg &arg1, const Gen::OpArg &arg2); // Pass a register as a paremeter. void ABI_CallFunctionR(void *func, Gen::X64Reg reg1); diff --git a/Core/MIPS/x86/CompLoadStore.cpp b/Core/MIPS/x86/CompLoadStore.cpp index 1b9695612b..4110a60b1b 100644 --- a/Core/MIPS/x86/CompLoadStore.cpp +++ b/Core/MIPS/x86/CompLoadStore.cpp @@ -41,26 +41,6 @@ namespace MIPSComp { - static u32 ReadMemSafe32(u32 addr, u32 offset) - { - return Memory::Read_U32(addr + offset); - } - - static u32 ReadMemSafe16(u32 addr, u32 offset) - { - return Memory::Read_U16(addr + offset); - } - - static void WriteMemSafe32(u32 addr, u32 value, u32 offset) - { - Memory::Write_U32(value, addr + offset); - } - - static void WriteMemSafe16(u32 addr, u32 value, u32 offset) - { - Memory::Write_U16(value, addr + offset); - } - void Jit::Comp_ITypeMem(u32 op) { int offset = (signed short)(op&0xFFFF); @@ -77,8 +57,6 @@ namespace MIPSComp case 37: //R(rt) = ReadMem16(addr); break; //lhu if (!g_Config.bFastMemory) { - FlushAll(); - gpr.Lock(rt, rs); gpr.BindToRegister(rt, rt == rs, true); @@ -97,7 +75,8 @@ namespace MIPSComp SetJumpTarget(tooLow); SetJumpTarget(tooHigh); - ABI_CallFunctionAC((void *) &ReadMemSafe16, R(EAX), offset); + ADD(32, R(EAX), Imm32(offset)); + ABI_CallFunctionA(thunks.ProtectFunction((void *) &Memory::Read_U16, 1), R(EAX)); MOVZX(32, 16, gpr.RX(rt), R(EAX)); SetJumpTarget(skip); @@ -126,8 +105,6 @@ namespace MIPSComp case 35: //R(rt) = ReadMem32(addr); break; //lw if (!g_Config.bFastMemory) { - FlushAll(); - gpr.Lock(rt, rs); gpr.BindToRegister(rt, rt == rs, true); @@ -146,7 +123,8 @@ namespace MIPSComp SetJumpTarget(tooLow); SetJumpTarget(tooHigh); - ABI_CallFunctionAC((void *) &ReadMemSafe32, R(EAX), offset); + ADD(32, R(EAX), Imm32(offset)); + ABI_CallFunctionA(thunks.ProtectFunction((void *) &Memory::Read_U32, 1), R(EAX)); MOV(32, gpr.R(rt), R(EAX)); SetJumpTarget(skip); @@ -178,8 +156,6 @@ namespace MIPSComp case 41: //WriteMem16(addr, R(rt)); break; //sh if (!g_Config.bFastMemory) { - FlushAll(); - gpr.Lock(rt, rs); gpr.BindToRegister(rt, true, false); @@ -198,7 +174,8 @@ namespace MIPSComp SetJumpTarget(tooLow); SetJumpTarget(tooHigh); - ABI_CallFunctionAAC((void *) &WriteMemSafe16, R(EAX), gpr.R(rt), offset); + ADD(32, R(EAX), Imm32(offset)); + ABI_CallFunctionAA(thunks.ProtectFunction((void *) &Memory::Write_U16, 2), gpr.R(rt), R(EAX)); SetJumpTarget(skip); gpr.UnlockAll(); @@ -222,8 +199,6 @@ namespace MIPSComp case 43: //WriteMem32(addr, R(rt)); break; //sw if (!g_Config.bFastMemory) { - FlushAll(); - gpr.Lock(rt, rs); gpr.BindToRegister(rt, true, false); @@ -242,7 +217,8 @@ namespace MIPSComp SetJumpTarget(tooLow); SetJumpTarget(tooHigh); - ABI_CallFunctionAAC((void *) &WriteMemSafe32, R(EAX), gpr.R(rt), offset); + ADD(32, R(EAX), Imm32(offset)); + ABI_CallFunctionAA(thunks.ProtectFunction((void *) &Memory::Write_U32, 2), gpr.R(rt), R(EAX)); SetJumpTarget(skip); gpr.UnlockAll(); diff --git a/Core/MIPS/x86/Jit.h b/Core/MIPS/x86/Jit.h index 6d895b697c..34f18c86ef 100644 --- a/Core/MIPS/x86/Jit.h +++ b/Core/MIPS/x86/Jit.h @@ -18,6 +18,7 @@ #pragma once #include "../../../Globals.h" +#include "../../../Common/Thunk.h" #include "Asm.h" #if defined(ARM) @@ -131,6 +132,7 @@ private: FPURegCache fpr; AsmRoutineManager asm_; + ThunkManager thunks; MIPSState *mips_; }; From 72e547420dd935b0293d8d0c57c5554c780f0b2d Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 19 Jan 2013 11:04:18 -0800 Subject: [PATCH 3/9] Refactor jit slowmem, add lbu to jit since easy. --- Core/MIPS/x86/CompLoadStore.cpp | 268 ++++++++++++-------------------- Core/MIPS/x86/Jit.h | 2 + 2 files changed, 105 insertions(+), 165 deletions(-) diff --git a/Core/MIPS/x86/CompLoadStore.cpp b/Core/MIPS/x86/CompLoadStore.cpp index 4110a60b1b..133e63c080 100644 --- a/Core/MIPS/x86/CompLoadStore.cpp +++ b/Core/MIPS/x86/CompLoadStore.cpp @@ -41,6 +41,103 @@ namespace MIPSComp { + void Jit::CompITypeMemRead(u32 op, u32 bits, void *func) + { + int offset = (signed short)(op&0xFFFF); + int rt = _RT; + int rs = _RS; + + if (!g_Config.bFastMemory) + { + gpr.Lock(rt, rs); + gpr.BindToRegister(rt, rt == rs, true); + + MOV(32, R(EAX), gpr.R(rs)); + CMP(32, R(EAX), Imm32(0x08000000)); + FixupBranch tooLow = J_CC(CC_L); + CMP(32, R(EAX), Imm32(0x0A000000)); + FixupBranch tooHigh = J_CC(CC_GE); +#ifdef _M_IX86 + MOVZX(32, bits, gpr.RX(rt), MDisp(EAX, (u32)Memory::base + offset)); +#else + MOVZX(32, bits, gpr.RX(rt), MComplex(RBX, EAX, SCALE_1, offset)); +#endif + + FixupBranch skip = J(); + SetJumpTarget(tooLow); + SetJumpTarget(tooHigh); + + ADD(32, R(EAX), Imm32(offset)); + ABI_CallFunctionA(thunks.ProtectFunction(func, 1), R(EAX)); + MOVZX(32, bits, gpr.RX(rt), R(EAX)); + + SetJumpTarget(skip); + gpr.UnlockAll(); + } + else + { + gpr.Lock(rt, rs); + gpr.BindToRegister(rt, rt == rs, true); +#ifdef _M_IX86 + MOV(32, R(EAX), gpr.R(rs)); + AND(32, R(EAX), Imm32(Memory::MEMVIEW32_MASK)); + MOVZX(32, bits, gpr.RX(rt), MDisp(EAX, (u32)Memory::base + offset)); +#else + MOV(32, R(EAX), gpr.R(rs)); + MOVZX(32, bits, gpr.RX(rt), MComplex(RBX, EAX, SCALE_1, offset)); +#endif + gpr.UnlockAll(); + } + } + + void Jit::CompITypeMemWrite(u32 op, u32 bits, void *func) + { + int offset = (signed short)(op&0xFFFF); + int rt = _RT; + int rs = _RS; + + if (!g_Config.bFastMemory) + { + gpr.Lock(rt, rs); + gpr.BindToRegister(rt, true, false); + + MOV(32, R(EAX), gpr.R(rs)); + CMP(32, R(EAX), Imm32(0x08000000)); + FixupBranch tooLow = J_CC(CC_L); + CMP(32, R(EAX), Imm32(0x0A000000)); + FixupBranch tooHigh = J_CC(CC_GE); +#ifdef _M_IX86 + MOV(bits, MDisp(EAX, (u32)Memory::base + offset), gpr.R(rt)); +#else + MOV(bits, MComplex(RBX, EAX, SCALE_1, offset), gpr.R(rt)); +#endif + + FixupBranch skip = J(); + SetJumpTarget(tooLow); + SetJumpTarget(tooHigh); + + ADD(32, R(EAX), Imm32(offset)); + ABI_CallFunctionAA(thunks.ProtectFunction(func, 2), gpr.R(rt), R(EAX)); + + SetJumpTarget(skip); + gpr.UnlockAll(); + } + else + { + gpr.Lock(rt, rs); + gpr.BindToRegister(rt, true, false); +#ifdef _M_IX86 + MOV(32, R(EAX), gpr.R(rs)); + AND(32, R(EAX), Imm32(Memory::MEMVIEW32_MASK)); + MOV(bits, MDisp(EAX, (u32)Memory::base + offset), gpr.R(rt)); +#else + MOV(32, R(EAX), gpr.R(rs)); + MOV(bits, MComplex(RBX, EAX, SCALE_1, offset), gpr.R(rt)); +#endif + gpr.UnlockAll(); + } + } + void Jit::Comp_ITypeMem(u32 op) { int offset = (signed short)(op&0xFFFF); @@ -55,188 +152,29 @@ namespace MIPSComp switch (o) { case 37: //R(rt) = ReadMem16(addr); break; //lhu - if (!g_Config.bFastMemory) - { - gpr.Lock(rt, rs); - gpr.BindToRegister(rt, rt == rs, true); - - MOV(32, R(EAX), gpr.R(rs)); - CMP(32, R(EAX), Imm32(0x08000000)); - FixupBranch tooLow = J_CC(CC_L); - CMP(32, R(EAX), Imm32(0x0A000000)); - FixupBranch tooHigh = J_CC(CC_GE); -#ifdef _M_IX86 - MOVZX(32, 16, gpr.RX(rt), MDisp(EAX, (u32)Memory::base + offset)); -#else - MOVZX(32, 16, gpr.RX(rt), MComplex(RBX, EAX, SCALE_1, offset)); -#endif - - FixupBranch skip = J(); - SetJumpTarget(tooLow); - SetJumpTarget(tooHigh); - - ADD(32, R(EAX), Imm32(offset)); - ABI_CallFunctionA(thunks.ProtectFunction((void *) &Memory::Read_U16, 1), R(EAX)); - MOVZX(32, 16, gpr.RX(rt), R(EAX)); - - SetJumpTarget(skip); - gpr.UnlockAll(); - } - else - { - gpr.Lock(rt, rs); - gpr.BindToRegister(rt, rt == rs, true); -#ifdef _M_IX86 - MOV(32, R(EAX), gpr.R(rs)); - AND(32, R(EAX), Imm32(Memory::MEMVIEW32_MASK)); - MOVZX(32, 16, gpr.RX(rt), MDisp(EAX, (u32)Memory::base + offset)); -#else - MOV(32, R(EAX), gpr.R(rs)); - MOVZX(32, 16, gpr.RX(rt), MComplex(RBX, EAX, SCALE_1, offset)); -#endif - gpr.UnlockAll(); - } + CompITypeMemRead(op, 16, (void *) &Memory::Read_U16); break; case 36: //R(rt) = ReadMem8 (addr); break; //lbu - Comp_Generic(op); - return; + CompITypeMemRead(op, 8, (void *) &Memory::Read_U8); + break; case 35: //R(rt) = ReadMem32(addr); break; //lw - if (!g_Config.bFastMemory) - { - gpr.Lock(rt, rs); - gpr.BindToRegister(rt, rt == rs, true); - - MOV(32, R(EAX), gpr.R(rs)); - CMP(32, R(EAX), Imm32(0x08000000)); - FixupBranch tooLow = J_CC(CC_L); - CMP(32, R(EAX), Imm32(0x0A000000)); - FixupBranch tooHigh = J_CC(CC_GE); -#ifdef _M_IX86 - MOV(32, gpr.R(rt), MDisp(EAX, (u32)Memory::base + offset)); -#else - MOV(32, gpr.R(rt), MComplex(RBX, EAX, SCALE_1, offset)); -#endif - - FixupBranch skip = J(); - SetJumpTarget(tooLow); - SetJumpTarget(tooHigh); - - ADD(32, R(EAX), Imm32(offset)); - ABI_CallFunctionA(thunks.ProtectFunction((void *) &Memory::Read_U32, 1), R(EAX)); - MOV(32, gpr.R(rt), R(EAX)); - - SetJumpTarget(skip); - gpr.UnlockAll(); - } - else - { - gpr.Lock(rt, rs); - gpr.BindToRegister(rt, rt == rs, true); -#ifdef _M_IX86 - MOV(32, R(EAX), gpr.R(rs)); - AND(32, R(EAX), Imm32(Memory::MEMVIEW32_MASK)); - MOV(32, gpr.R(rt), MDisp(EAX, (u32)Memory::base + offset)); -#else - MOV(32, R(EAX), gpr.R(rs)); - MOV(32, gpr.R(rt), MComplex(RBX, EAX, SCALE_1, offset)); -#endif - gpr.UnlockAll(); - } + CompITypeMemRead(op, 32, (void *) &Memory::Read_U16); break; case 132: //R(rt) = (u32)(s32)(s8) ReadMem8 (addr); break; //lb case 133: //R(rt) = (u32)(s32)(s16)ReadMem16(addr); break; //lh - case 136: //R(rt) = ReadMem8 (addr); break; //lbu case 140: //WriteMem8 (addr, R(rt)); break; //sb Comp_Generic(op); return; case 41: //WriteMem16(addr, R(rt)); break; //sh - if (!g_Config.bFastMemory) - { - gpr.Lock(rt, rs); - gpr.BindToRegister(rt, true, false); - - MOV(32, R(EAX), gpr.R(rs)); - CMP(32, R(EAX), Imm32(0x08000000)); - FixupBranch tooLow = J_CC(CC_L); - CMP(32, R(EAX), Imm32(0x0A000000)); - FixupBranch tooHigh = J_CC(CC_GE); -#ifdef _M_IX86 - MOV(16, MDisp(EAX, (u32)Memory::base + offset), gpr.R(rt)); -#else - MOV(16, MComplex(RBX, EAX, SCALE_1, offset), gpr.R(rt)); -#endif - - FixupBranch skip = J(); - SetJumpTarget(tooLow); - SetJumpTarget(tooHigh); - - ADD(32, R(EAX), Imm32(offset)); - ABI_CallFunctionAA(thunks.ProtectFunction((void *) &Memory::Write_U16, 2), gpr.R(rt), R(EAX)); - - SetJumpTarget(skip); - gpr.UnlockAll(); - } - else - { - gpr.Lock(rt, rs); - gpr.BindToRegister(rt, true, false); -#ifdef _M_IX86 - MOV(32, R(EAX), gpr.R(rs)); - AND(32, R(EAX), Imm32(Memory::MEMVIEW32_MASK)); - MOV(16, MDisp(EAX, (u32)Memory::base + offset), gpr.R(rt)); -#else - MOV(32, R(EAX), gpr.R(rs)); - MOV(16, MComplex(RBX, EAX, SCALE_1, offset), gpr.R(rt)); -#endif - gpr.UnlockAll(); - } + CompITypeMemWrite(op, 16, (void *) &Memory::Write_U16); break; case 43: //WriteMem32(addr, R(rt)); break; //sw - if (!g_Config.bFastMemory) - { - gpr.Lock(rt, rs); - gpr.BindToRegister(rt, true, false); - - MOV(32, R(EAX), gpr.R(rs)); - CMP(32, R(EAX), Imm32(0x08000000)); - FixupBranch tooLow = J_CC(CC_L); - CMP(32, R(EAX), Imm32(0x0A000000)); - FixupBranch tooHigh = J_CC(CC_GE); -#ifdef _M_IX86 - MOV(32, MDisp(EAX, (u32)Memory::base + offset), gpr.R(rt)); -#else - MOV(32, MComplex(RBX, EAX, SCALE_1, offset), gpr.R(rt)); -#endif - - FixupBranch skip = J(); - SetJumpTarget(tooLow); - SetJumpTarget(tooHigh); - - ADD(32, R(EAX), Imm32(offset)); - ABI_CallFunctionAA(thunks.ProtectFunction((void *) &Memory::Write_U32, 2), gpr.R(rt), R(EAX)); - - SetJumpTarget(skip); - gpr.UnlockAll(); - } - else - { - gpr.Lock(rt, rs); - gpr.BindToRegister(rt, true, false); -#ifdef _M_IX86 - MOV(32, R(EAX), gpr.R(rs)); - AND(32, R(EAX), Imm32(Memory::MEMVIEW32_MASK)); - MOV(32, MDisp(EAX, (u32)Memory::base + offset), gpr.R(rt)); -#else - MOV(32, R(EAX), gpr.R(rs)); - MOV(32, MComplex(RBX, EAX, SCALE_1, offset), gpr.R(rt)); -#endif - gpr.UnlockAll(); - } + CompITypeMemWrite(op, 32, (void *) &Memory::Write_U32); break; case 134: //lwl diff --git a/Core/MIPS/x86/Jit.h b/Core/MIPS/x86/Jit.h index 34f18c86ef..bec37c9d7a 100644 --- a/Core/MIPS/x86/Jit.h +++ b/Core/MIPS/x86/Jit.h @@ -121,6 +121,8 @@ private: void CompTriArith(u32 op, void (XEmitter::*arith)(int, const OpArg &, const OpArg &)); void CompShiftImm(u32 op, void (XEmitter::*shift)(int, OpArg, OpArg)); void CompShiftVar(u32 op, void (XEmitter::*shift)(int, OpArg, OpArg)); + void CompITypeMemRead(u32 op, u32 bits, void *func); + void CompITypeMemWrite(u32 op, u32 bits, void *func); void CompFPTriArith(u32 op, void (XEmitter::*arith)(X64Reg reg, OpArg), bool orderMatters); From 37fb64ac831206765bd4f52d0d6039cbb759c6ae Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 19 Jan 2013 11:10:28 -0800 Subject: [PATCH 4/9] Fast path scratchpad too, shouldn't be expensive. --- Core/MIPS/x86/CompLoadStore.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/Core/MIPS/x86/CompLoadStore.cpp b/Core/MIPS/x86/CompLoadStore.cpp index 133e63c080..56037aed74 100644 --- a/Core/MIPS/x86/CompLoadStore.cpp +++ b/Core/MIPS/x86/CompLoadStore.cpp @@ -53,10 +53,13 @@ namespace MIPSComp gpr.BindToRegister(rt, rt == rs, true); MOV(32, R(EAX), gpr.R(rs)); + // Is it in physical ram? CMP(32, R(EAX), Imm32(0x08000000)); FixupBranch tooLow = J_CC(CC_L); CMP(32, R(EAX), Imm32(0x0A000000)); FixupBranch tooHigh = J_CC(CC_GE); + + const u8* safe = GetCodePtr(); #ifdef _M_IX86 MOVZX(32, bits, gpr.RX(rt), MDisp(EAX, (u32)Memory::base + offset)); #else @@ -67,6 +70,13 @@ namespace MIPSComp SetJumpTarget(tooLow); SetJumpTarget(tooHigh); + // Might also be the scratchpad. + CMP(32, R(EAX), Imm32(0x00010000)); + FixupBranch tooLow2 = J_CC(CC_L); + CMP(32, R(EAX), Imm32(0x00014000)); + J_CC(CC_L, safe); + SetJumpTarget(tooLow2); + ADD(32, R(EAX), Imm32(offset)); ABI_CallFunctionA(thunks.ProtectFunction(func, 1), R(EAX)); MOVZX(32, bits, gpr.RX(rt), R(EAX)); @@ -102,10 +112,13 @@ namespace MIPSComp gpr.BindToRegister(rt, true, false); MOV(32, R(EAX), gpr.R(rs)); + // Is it in physical ram? CMP(32, R(EAX), Imm32(0x08000000)); FixupBranch tooLow = J_CC(CC_L); CMP(32, R(EAX), Imm32(0x0A000000)); FixupBranch tooHigh = J_CC(CC_GE); + + const u8* safe = GetCodePtr(); #ifdef _M_IX86 MOV(bits, MDisp(EAX, (u32)Memory::base + offset), gpr.R(rt)); #else @@ -116,6 +129,13 @@ namespace MIPSComp SetJumpTarget(tooLow); SetJumpTarget(tooHigh); + // Might also be the scratchpad. + CMP(32, R(EAX), Imm32(0x00010000)); + FixupBranch tooLow2 = J_CC(CC_L); + CMP(32, R(EAX), Imm32(0x00014000)); + J_CC(CC_L, safe); + SetJumpTarget(tooLow2); + ADD(32, R(EAX), Imm32(offset)); ABI_CallFunctionAA(thunks.ProtectFunction(func, 2), gpr.R(rt), R(EAX)); From c64966c16e6ef957bb86936010f8c7bce02f912f Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 19 Jan 2013 11:54:57 -0800 Subject: [PATCH 5/9] Oops, lost the CONDITIONAL_DISABLE. --- Core/MIPS/x86/CompLoadStore.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Core/MIPS/x86/CompLoadStore.cpp b/Core/MIPS/x86/CompLoadStore.cpp index 56037aed74..97a23805cb 100644 --- a/Core/MIPS/x86/CompLoadStore.cpp +++ b/Core/MIPS/x86/CompLoadStore.cpp @@ -43,6 +43,7 @@ namespace MIPSComp { void Jit::CompITypeMemRead(u32 op, u32 bits, void *func) { + CONDITIONAL_DISABLE; int offset = (signed short)(op&0xFFFF); int rt = _RT; int rs = _RS; @@ -102,6 +103,7 @@ namespace MIPSComp void Jit::CompITypeMemWrite(u32 op, u32 bits, void *func) { + CONDITIONAL_DISABLE; int offset = (signed short)(op&0xFFFF); int rt = _RT; int rs = _RS; @@ -160,6 +162,7 @@ namespace MIPSComp void Jit::Comp_ITypeMem(u32 op) { + CONDITIONAL_DISABLE; int offset = (signed short)(op&0xFFFF); int rt = _RT; int rs = _RS; From 90e6f0b7dfff57654346106f5d0b7e0a480c86b7 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 19 Jan 2013 12:34:02 -0800 Subject: [PATCH 6/9] Optimize static memory read/writes in jit as well. Like the arm jit does. --- Core/MIPS/x86/CompLoadStore.cpp | 54 +++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 20 deletions(-) diff --git a/Core/MIPS/x86/CompLoadStore.cpp b/Core/MIPS/x86/CompLoadStore.cpp index 97a23805cb..be544b105f 100644 --- a/Core/MIPS/x86/CompLoadStore.cpp +++ b/Core/MIPS/x86/CompLoadStore.cpp @@ -48,11 +48,19 @@ namespace MIPSComp int rt = _RT; int rs = _RS; - if (!g_Config.bFastMemory) - { - gpr.Lock(rt, rs); - gpr.BindToRegister(rt, rt == rs, true); + gpr.Lock(rt, rs); + gpr.BindToRegister(rt, rt == rs, true); + if (gpr.R(rs).IsImm()) + { + void *data = Memory::GetPointer(gpr.R(rs).GetImmValue() + offset); + if (data) + MOVZX(32, bits, gpr.RX(rt), M(data)); + else + MOV(32, gpr.R(rt), Imm32(0)); + } + else if (!g_Config.bFastMemory) + { MOV(32, R(EAX), gpr.R(rs)); // Is it in physical ram? CMP(32, R(EAX), Imm32(0x08000000)); @@ -83,22 +91,19 @@ namespace MIPSComp MOVZX(32, bits, gpr.RX(rt), R(EAX)); SetJumpTarget(skip); - gpr.UnlockAll(); } else { - gpr.Lock(rt, rs); - gpr.BindToRegister(rt, rt == rs, true); -#ifdef _M_IX86 MOV(32, R(EAX), gpr.R(rs)); +#ifdef _M_IX86 AND(32, R(EAX), Imm32(Memory::MEMVIEW32_MASK)); MOVZX(32, bits, gpr.RX(rt), MDisp(EAX, (u32)Memory::base + offset)); #else - MOV(32, R(EAX), gpr.R(rs)); MOVZX(32, bits, gpr.RX(rt), MComplex(RBX, EAX, SCALE_1, offset)); #endif - gpr.UnlockAll(); } + + gpr.UnlockAll(); } void Jit::CompITypeMemWrite(u32 op, u32 bits, void *func) @@ -108,11 +113,23 @@ namespace MIPSComp int rt = _RT; int rs = _RS; - if (!g_Config.bFastMemory) - { - gpr.Lock(rt, rs); - gpr.BindToRegister(rt, true, false); + gpr.Lock(rt, rs); + gpr.BindToRegister(rt, true, false); + if (gpr.R(rs).IsImm()) + { + void *data = Memory::GetPointer(gpr.R(rs).GetImmValue() + offset); + if (data) + MOV(bits, M(data), gpr.R(rt)); + else if (bits == 8) + MOV(bits, M(data), Imm8(0)); + else if (bits == 16) + MOV(bits, M(data), Imm16(0)); + else + MOV(bits, M(data), Imm32(0)); + } + else if (!g_Config.bFastMemory) + { MOV(32, R(EAX), gpr.R(rs)); // Is it in physical ram? CMP(32, R(EAX), Imm32(0x08000000)); @@ -142,22 +159,19 @@ namespace MIPSComp ABI_CallFunctionAA(thunks.ProtectFunction(func, 2), gpr.R(rt), R(EAX)); SetJumpTarget(skip); - gpr.UnlockAll(); } else { - gpr.Lock(rt, rs); - gpr.BindToRegister(rt, true, false); -#ifdef _M_IX86 MOV(32, R(EAX), gpr.R(rs)); +#ifdef _M_IX86 AND(32, R(EAX), Imm32(Memory::MEMVIEW32_MASK)); MOV(bits, MDisp(EAX, (u32)Memory::base + offset), gpr.R(rt)); #else - MOV(32, R(EAX), gpr.R(rs)); MOV(bits, MComplex(RBX, EAX, SCALE_1, offset), gpr.R(rt)); #endif - gpr.UnlockAll(); } + + gpr.UnlockAll(); } void Jit::Comp_ITypeMem(u32 op) From 5e8f1917ee8213ff1285ce23825077d7833a3609 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 19 Jan 2013 15:47:32 -0800 Subject: [PATCH 7/9] Fix 64-bit memory dereferencing. --- Core/MIPS/x86/CompLoadStore.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Core/MIPS/x86/CompLoadStore.cpp b/Core/MIPS/x86/CompLoadStore.cpp index be544b105f..e5c8f586b2 100644 --- a/Core/MIPS/x86/CompLoadStore.cpp +++ b/Core/MIPS/x86/CompLoadStore.cpp @@ -55,7 +55,13 @@ namespace MIPSComp { void *data = Memory::GetPointer(gpr.R(rs).GetImmValue() + offset); if (data) + { +#ifdef _M_IX86 MOVZX(32, bits, gpr.RX(rt), M(data)); +#else + MOVZX(32, bits, gpr.RX(rt), MDisp(RBX, gpr.R(rs).GetImmValue() + offset)); +#endif + } else MOV(32, gpr.R(rt), Imm32(0)); } @@ -120,7 +126,13 @@ namespace MIPSComp { void *data = Memory::GetPointer(gpr.R(rs).GetImmValue() + offset); if (data) + { +#ifdef _M_IX86 MOV(bits, M(data), gpr.R(rt)); +#else + MOV(bits, MDisp(RBX, gpr.R(rs).GetImmValue() + offset), gpr.R(rt)); +#endif + } else if (bits == 8) MOV(bits, M(data), Imm8(0)); else if (bits == 16) From e78223d2c0439c6eb9bfb6aff31edbba5255295d Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 19 Jan 2013 16:02:56 -0800 Subject: [PATCH 8/9] Since flipping the op is easy, also do lb/lh. --- Core/MIPS/x86/CompLoadStore.cpp | 38 +++++++++++++++++++-------------- Core/MIPS/x86/Jit.h | 4 ++-- 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/Core/MIPS/x86/CompLoadStore.cpp b/Core/MIPS/x86/CompLoadStore.cpp index e5c8f586b2..da45913400 100644 --- a/Core/MIPS/x86/CompLoadStore.cpp +++ b/Core/MIPS/x86/CompLoadStore.cpp @@ -41,7 +41,7 @@ namespace MIPSComp { - void Jit::CompITypeMemRead(u32 op, u32 bits, void *func) + void Jit::CompITypeMemRead(u32 op, u32 bits, void (XEmitter::*mov)(int, int, X64Reg, OpArg), void *safeFunc) { CONDITIONAL_DISABLE; int offset = (signed short)(op&0xFFFF); @@ -57,9 +57,9 @@ namespace MIPSComp if (data) { #ifdef _M_IX86 - MOVZX(32, bits, gpr.RX(rt), M(data)); + (this->*mov)(32, bits, gpr.RX(rt), M(data)); #else - MOVZX(32, bits, gpr.RX(rt), MDisp(RBX, gpr.R(rs).GetImmValue() + offset)); + (this->*mov)(32, bits, gpr.RX(rt), MDisp(RBX, gpr.R(rs).GetImmValue() + offset)); #endif } else @@ -76,9 +76,9 @@ namespace MIPSComp const u8* safe = GetCodePtr(); #ifdef _M_IX86 - MOVZX(32, bits, gpr.RX(rt), MDisp(EAX, (u32)Memory::base + offset)); + (this->*mov)(32, bits, gpr.RX(rt), MDisp(EAX, (u32)Memory::base + offset)); #else - MOVZX(32, bits, gpr.RX(rt), MComplex(RBX, EAX, SCALE_1, offset)); + (this->*mov)(32, bits, gpr.RX(rt), MComplex(RBX, EAX, SCALE_1, offset)); #endif FixupBranch skip = J(); @@ -93,8 +93,8 @@ namespace MIPSComp SetJumpTarget(tooLow2); ADD(32, R(EAX), Imm32(offset)); - ABI_CallFunctionA(thunks.ProtectFunction(func, 1), R(EAX)); - MOVZX(32, bits, gpr.RX(rt), R(EAX)); + ABI_CallFunctionA(thunks.ProtectFunction(safeFunc, 1), R(EAX)); + (this->*mov)(32, bits, gpr.RX(rt), R(EAX)); SetJumpTarget(skip); } @@ -103,16 +103,16 @@ namespace MIPSComp MOV(32, R(EAX), gpr.R(rs)); #ifdef _M_IX86 AND(32, R(EAX), Imm32(Memory::MEMVIEW32_MASK)); - MOVZX(32, bits, gpr.RX(rt), MDisp(EAX, (u32)Memory::base + offset)); + (this->*mov)(32, bits, gpr.RX(rt), MDisp(EAX, (u32)Memory::base + offset)); #else - MOVZX(32, bits, gpr.RX(rt), MComplex(RBX, EAX, SCALE_1, offset)); + (this->*mov)(32, bits, gpr.RX(rt), MComplex(RBX, EAX, SCALE_1, offset)); #endif } gpr.UnlockAll(); } - void Jit::CompITypeMemWrite(u32 op, u32 bits, void *func) + void Jit::CompITypeMemWrite(u32 op, u32 bits, void *safeFunc) { CONDITIONAL_DISABLE; int offset = (signed short)(op&0xFFFF); @@ -168,7 +168,7 @@ namespace MIPSComp SetJumpTarget(tooLow2); ADD(32, R(EAX), Imm32(offset)); - ABI_CallFunctionAA(thunks.ProtectFunction(func, 2), gpr.R(rt), R(EAX)); + ABI_CallFunctionAA(thunks.ProtectFunction(safeFunc, 2), gpr.R(rt), R(EAX)); SetJumpTarget(skip); } @@ -201,19 +201,25 @@ namespace MIPSComp switch (o) { case 37: //R(rt) = ReadMem16(addr); break; //lhu - CompITypeMemRead(op, 16, (void *) &Memory::Read_U16); + CompITypeMemRead(op, 16, &XEmitter::MOVZX, (void *) &Memory::Read_U16); break; case 36: //R(rt) = ReadMem8 (addr); break; //lbu - CompITypeMemRead(op, 8, (void *) &Memory::Read_U8); + CompITypeMemRead(op, 8, &XEmitter::MOVZX, (void *) &Memory::Read_U8); break; case 35: //R(rt) = ReadMem32(addr); break; //lw - CompITypeMemRead(op, 32, (void *) &Memory::Read_U16); + CompITypeMemRead(op, 32, &XEmitter::MOVZX, (void *) &Memory::Read_U16); + break; + + case 32: //R(rt) = (u32)(s32)(s8) ReadMem8 (addr); break; //lb + CompITypeMemRead(op, 8, &XEmitter::MOVSX, (void *) &Memory::Read_U8); + break; + + case 33: //R(rt) = (u32)(s32)(s16)ReadMem16(addr); break; //lh + CompITypeMemRead(op, 16, &XEmitter::MOVSX, (void *) &Memory::Read_U16); break; - case 132: //R(rt) = (u32)(s32)(s8) ReadMem8 (addr); break; //lb - case 133: //R(rt) = (u32)(s32)(s16)ReadMem16(addr); break; //lh case 140: //WriteMem8 (addr, R(rt)); break; //sb Comp_Generic(op); return; diff --git a/Core/MIPS/x86/Jit.h b/Core/MIPS/x86/Jit.h index bec37c9d7a..27c094a9ef 100644 --- a/Core/MIPS/x86/Jit.h +++ b/Core/MIPS/x86/Jit.h @@ -121,8 +121,8 @@ private: void CompTriArith(u32 op, void (XEmitter::*arith)(int, const OpArg &, const OpArg &)); void CompShiftImm(u32 op, void (XEmitter::*shift)(int, OpArg, OpArg)); void CompShiftVar(u32 op, void (XEmitter::*shift)(int, OpArg, OpArg)); - void CompITypeMemRead(u32 op, u32 bits, void *func); - void CompITypeMemWrite(u32 op, u32 bits, void *func); + void CompITypeMemRead(u32 op, u32 bits, void (XEmitter::*mov)(int, int, X64Reg, OpArg), void *safeFunc); + void CompITypeMemWrite(u32 op, u32 bits, void *safeFunc); void CompFPTriArith(u32 op, void (XEmitter::*arith)(X64Reg reg, OpArg), bool orderMatters); From 53600161baeb3e35c3c4aed76113512bfee53ef9 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 20 Jan 2013 00:19:18 -0800 Subject: [PATCH 9/9] Don't write anything to a bad static pointer. Not sure what came over me... --- Core/MIPS/x86/CompLoadStore.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Core/MIPS/x86/CompLoadStore.cpp b/Core/MIPS/x86/CompLoadStore.cpp index da45913400..d6889ba92d 100644 --- a/Core/MIPS/x86/CompLoadStore.cpp +++ b/Core/MIPS/x86/CompLoadStore.cpp @@ -133,12 +133,6 @@ namespace MIPSComp MOV(bits, MDisp(RBX, gpr.R(rs).GetImmValue() + offset), gpr.R(rt)); #endif } - else if (bits == 8) - MOV(bits, M(data), Imm8(0)); - else if (bits == 16) - MOV(bits, M(data), Imm16(0)); - else - MOV(bits, M(data), Imm32(0)); } else if (!g_Config.bFastMemory) {