From d5ae85201ca9d3614f65ee7bae2383ab51190edb Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 18 Jan 2013 08:30:28 -0800 Subject: [PATCH 1/4] Optimize sw/lw even under safe memory. They're very common instructions, so shaving cycles helps. --- Common/ABI.cpp | 26 +++++++++++++++++++ Common/x64Emitter.h | 1 + Core/MIPS/x86/CompLoadStore.cpp | 45 +++++++++++++++++++++++---------- 3 files changed, 59 insertions(+), 13 deletions(-) diff --git a/Common/ABI.cpp b/Common/ABI.cpp index 3bf8dc41c7..f0489e346d 100644 --- a/Common/ABI.cpp +++ b/Common/ABI.cpp @@ -160,6 +160,16 @@ void XEmitter::ABI_CallFunctionAC(void *func, const Gen::OpArg &arg1, u32 param2 ABI_RestoreStack(2 * 4); } +void XEmitter::ABI_CallFunctionACC(void *func, const Gen::OpArg &arg1, u32 param2, u32 param3) +{ + ABI_AlignStack(3 * 4); + PUSH(32, Imm32(param3)); + PUSH(32, Imm32(param2)); + PUSH(32, arg1); + CALL(func); + ABI_RestoreStack(3 * 4); +} + void XEmitter::ABI_CallFunctionA(void *func, const Gen::OpArg &arg1) { ABI_AlignStack(1 * 4); @@ -404,6 +414,22 @@ void XEmitter::ABI_CallFunctionAC(void *func, const Gen::OpArg &arg1, u32 param2 } } +void XEmitter::ABI_CallFunctionACC(void *func, const Gen::OpArg &arg1, u32 param2, u32 param3) +{ + MOV(32, R(ABI_PARAM1), arg1); + MOV(32, R(ABI_PARAM2), Imm32(param2)); + 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 21a1deaeae..e0b85e6b85 100644 --- a/Common/x64Emitter.h +++ b/Common/x64Emitter.h @@ -656,6 +656,7 @@ public: void ABI_CallFunctionCCCP(void *func, u32 param1, u32 param2,u32 param3, void *param4); 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_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 b262b11699..0b8207ca43 100644 --- a/Core/MIPS/x86/CompLoadStore.cpp +++ b/Core/MIPS/x86/CompLoadStore.cpp @@ -41,13 +41,18 @@ namespace MIPSComp { + void ReadMemSafe(u32 addr, int preg, u32 offset) + { + currentMIPS->r[preg] = Memory::Read_U32(addr + offset); + } + + void WriteMemSafe(u32 addr, int preg, u32 offset) + { + Memory::Write_U32(currentMIPS->r[preg], addr + offset); + } + void Jit::Comp_ITypeMem(u32 op) { - if (!g_Config.bFastMemory) - { - DISABLE; - } - int offset = (signed short)(op&0xFFFF); int rt = _RT; int rs = _RS; @@ -65,17 +70,25 @@ namespace MIPSComp return; case 35: //R(rt) = ReadMem32(addr); break; //lw - gpr.Lock(rt, rs); - gpr.BindToRegister(rt, rt == rs, true); + if (!g_Config.bFastMemory) + { + FlushAll(); + ABI_CallFunctionACC((void *) &ReadMemSafe, gpr.R(rs), rt, offset); + } + 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)); + 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)); + MOV(32, R(EAX), gpr.R(rs)); + MOV(32, gpr.R(rt), MComplex(RBX, EAX, SCALE_1, offset)); #endif - gpr.UnlockAll(); + gpr.UnlockAll(); + } break; case 132: //R(rt) = (u32)(s32)(s8) ReadMem8 (addr); break; //lb @@ -89,6 +102,12 @@ namespace MIPSComp return; case 43: //WriteMem32(addr, R(rt)); break; //sw + if (!g_Config.bFastMemory) + { + FlushAll(); + ABI_CallFunctionACC((void *) &WriteMemSafe, gpr.R(rs), rt, offset); + } + else { gpr.Lock(rt, rs); gpr.BindToRegister(rt, true, false); From bc75b68c36f31761b9e94deb14c6120dc0720613 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 18 Jan 2013 08:48:26 -0800 Subject: [PATCH 2/4] Also jit sh and lhu, which are pretty common ops. --- Core/MIPS/x86/CompLoadStore.cpp | 66 +++++++++++++++++++++++++++++---- 1 file changed, 59 insertions(+), 7 deletions(-) diff --git a/Core/MIPS/x86/CompLoadStore.cpp b/Core/MIPS/x86/CompLoadStore.cpp index 0b8207ca43..9645e768e6 100644 --- a/Core/MIPS/x86/CompLoadStore.cpp +++ b/Core/MIPS/x86/CompLoadStore.cpp @@ -41,16 +41,26 @@ namespace MIPSComp { - void ReadMemSafe(u32 addr, int preg, u32 offset) + static void ReadMemSafe32(u32 addr, int preg, u32 offset) { currentMIPS->r[preg] = Memory::Read_U32(addr + offset); } - void WriteMemSafe(u32 addr, int preg, u32 offset) + static void ReadMemSafe16(u32 addr, int preg, u32 offset) + { + currentMIPS->r[preg] = Memory::Read_U16(addr + offset); + } + + static void WriteMemSafe32(u32 addr, int preg, u32 offset) { Memory::Write_U32(currentMIPS->r[preg], addr + offset); } + static void WriteMemSafe16(u32 addr, int preg, u32 offset) + { + Memory::Write_U16(currentMIPS->r[preg], addr + offset); + } + void Jit::Comp_ITypeMem(u32 op) { int offset = (signed short)(op&0xFFFF); @@ -65,6 +75,29 @@ namespace MIPSComp switch (o) { case 37: //R(rt) = ReadMem16(addr); break; //lhu + if (!g_Config.bFastMemory) + { + FlushAll(); + ABI_CallFunctionACC((void *) &ReadMemSafe16, gpr.R(rs), rt, offset); + } + 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), Imm32(0)); + MOV(16, gpr.R(rt), MDisp(EAX, (u32)Memory::base + offset)); +#else + MOV(32, R(EAX), gpr.R(rs)); + MOV(32, gpr.R(rt), Imm32(0)); + MOV(16, gpr.R(rt), MComplex(RBX, EAX, SCALE_1, offset)); +#endif + gpr.UnlockAll(); + } + break; + case 36: //R(rt) = ReadMem8 (addr); break; //lbu Comp_Generic(op); return; @@ -73,7 +106,7 @@ namespace MIPSComp if (!g_Config.bFastMemory) { FlushAll(); - ABI_CallFunctionACC((void *) &ReadMemSafe, gpr.R(rs), rt, offset); + ABI_CallFunctionACC((void *) &ReadMemSafe32, gpr.R(rs), rt, offset); } else { @@ -95,17 +128,36 @@ namespace MIPSComp 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 - - case 40: - case 41: //WriteMem16(addr, R(rt)); break; //sh Comp_Generic(op); return; + case 41: //WriteMem16(addr, R(rt)); break; //sh + if (!g_Config.bFastMemory) + { + FlushAll(); + ABI_CallFunctionACC((void *) &WriteMemSafe16, gpr.R(rs), rt, offset); + } + 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(); + } + break; + case 43: //WriteMem32(addr, R(rt)); break; //sw if (!g_Config.bFastMemory) { FlushAll(); - ABI_CallFunctionACC((void *) &WriteMemSafe, gpr.R(rs), rt, offset); + ABI_CallFunctionACC((void *) &WriteMemSafe32, gpr.R(rs), rt, offset); } else { From 09422d5adbb4f05332f40cd5ad7117b8e11fac9d Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 19 Jan 2013 01:02:47 -0800 Subject: [PATCH 3/4] Avoid a func if possible when fastmem is off. --- Core/MIPS/x86/CompLoadStore.cpp | 82 +++++++++++++++++++++++++++++++-- 1 file changed, 78 insertions(+), 4 deletions(-) diff --git a/Core/MIPS/x86/CompLoadStore.cpp b/Core/MIPS/x86/CompLoadStore.cpp index 9645e768e6..7b958ebdf1 100644 --- a/Core/MIPS/x86/CompLoadStore.cpp +++ b/Core/MIPS/x86/CompLoadStore.cpp @@ -78,7 +78,26 @@ namespace MIPSComp if (!g_Config.bFastMemory) { FlushAll(); + + 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); ABI_CallFunctionACC((void *) &ReadMemSafe16, gpr.R(rs), rt, offset); + SetJumpTarget(skip); + gpr.UnlockAll(); } else { @@ -87,12 +106,10 @@ namespace MIPSComp #ifdef _M_IX86 MOV(32, R(EAX), gpr.R(rs)); AND(32, R(EAX), Imm32(Memory::MEMVIEW32_MASK)); - MOV(32, gpr.R(rt), Imm32(0)); - MOV(16, gpr.R(rt), MDisp(EAX, (u32)Memory::base + offset)); + MOVZX(32, 16, gpr.RX(rt), MDisp(EAX, (u32)Memory::base + offset)); #else MOV(32, R(EAX), gpr.R(rs)); - MOV(32, gpr.R(rt), Imm32(0)); - MOV(16, gpr.R(rt), MComplex(RBX, EAX, SCALE_1, offset)); + MOVZX(32, 16, gpr.RX(rt), MComplex(RBX, EAX, SCALE_1, offset)); #endif gpr.UnlockAll(); } @@ -106,7 +123,26 @@ namespace MIPSComp if (!g_Config.bFastMemory) { FlushAll(); + + 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); ABI_CallFunctionACC((void *) &ReadMemSafe32, gpr.R(rs), rt, offset); + SetJumpTarget(skip); + gpr.UnlockAll(); } else { @@ -135,7 +171,26 @@ namespace MIPSComp if (!g_Config.bFastMemory) { FlushAll(); + + gpr.Lock(rt, rs); + gpr.BindToRegister(rt, true, 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(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); ABI_CallFunctionACC((void *) &WriteMemSafe16, gpr.R(rs), rt, offset); + SetJumpTarget(skip); + gpr.UnlockAll(); } else { @@ -157,7 +212,26 @@ namespace MIPSComp if (!g_Config.bFastMemory) { FlushAll(); + + gpr.Lock(rt, rs); + gpr.BindToRegister(rt, true, 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, 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); ABI_CallFunctionACC((void *) &WriteMemSafe32, gpr.R(rs), rt, offset); + SetJumpTarget(skip); + gpr.UnlockAll(); } else { From 2ad77aa9c8ea9f876c79d1cb97f5266366419de5 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 19 Jan 2013 01:53:11 -0800 Subject: [PATCH 4/4] Gotta flush before the call, too. --- Core/MIPS/x86/CompLoadStore.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/Core/MIPS/x86/CompLoadStore.cpp b/Core/MIPS/x86/CompLoadStore.cpp index 7b958ebdf1..f53338823a 100644 --- a/Core/MIPS/x86/CompLoadStore.cpp +++ b/Core/MIPS/x86/CompLoadStore.cpp @@ -92,12 +92,14 @@ 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); SetJumpTarget(skip); - gpr.UnlockAll(); } else { @@ -137,12 +139,14 @@ 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); SetJumpTarget(skip); - gpr.UnlockAll(); } else { @@ -185,12 +189,14 @@ 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); SetJumpTarget(skip); - gpr.UnlockAll(); } else { @@ -226,12 +232,14 @@ 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); SetJumpTarget(skip); - gpr.UnlockAll(); } else {