diff --git a/pcsx2/x86/iCOP0.cpp b/pcsx2/x86/iCOP0.cpp index fd06fd0db6..6a66b5863d 100644 --- a/pcsx2/x86/iCOP0.cpp +++ b/pcsx2/x86/iCOP0.cpp @@ -34,45 +34,6 @@ namespace Interp = R5900::Interpreter::OpcodeImpl::COP0; namespace R5900 { namespace Dynarec { - -// R5900 branch hepler! -// Recompiles code for a branch test and/or skip, complete with delay slot -// handling. Note, for "likely" branches use iDoBranchImm_Likely instead, which -// handles delay slots differently. -// Parameters: -// jmpSkip - This parameter is the result of the appropriate J32 instruction -// (usually JZ32 or JNZ32). -static void recDoBranchImm( u32* jmpSkip, bool isLikely = false ) -{ - // All R5900 branches use this format: - const u32 branchTo = (s32)_Imm_ * 4 + pc; - - // First up is the Branch Taken Path : Save the recompiler's state, compile the - // DelaySlot, and issue a BranchTest insertion. The state is reloaded below for - // the "did not branch" path (maintains consts, register allocations, and other optimizations). - - SaveBranchState(); - recompileNextInstruction(1); - SetBranchImm(branchTo); - - // Jump target when the branch is *not* taken, skips the branchtest code - // insertion above. - x86SetJ32(jmpSkip); - - // if it's a likely branch then we'll need to skip the delay slot here, since - // MIPS cancels the delay slot instruction when branches aren't taken. - if( !isLikely ) pc -= 4; // instruction rewinde for delay slot ,if non-likely. - LoadBranchState(); - recompileNextInstruction(1); - - SetBranchImm(pc); -} - -static void recDoBranchImm_Likely( u32* jmpSkip ) -{ - recDoBranchImm( jmpSkip, true ); -} - namespace OpcodeImpl { namespace COP0 { diff --git a/pcsx2/x86/iCOP2.cpp b/pcsx2/x86/iCOP2.cpp index 6e909a6280..55329d6782 100644 --- a/pcsx2/x86/iCOP2.cpp +++ b/pcsx2/x86/iCOP2.cpp @@ -379,10 +379,49 @@ static void recQMTC2(s32 info) ////////////////////////////////////////////////////////////////////////// // BC2: Instructions ////////////////////////////////////////////////////////////////////////// -REC_COP2_FUNC(BC2F); -REC_COP2_FUNC(BC2T); -REC_COP2_FUNC(BC2FL); -REC_COP2_FUNC(BC2TL); +//REC_COP2_FUNC(BC2F); +//REC_COP2_FUNC(BC2T); +//REC_COP2_FUNC(BC2FL); +//REC_COP2_FUNC(BC2TL); + +using namespace R5900::Dynarec; + +static void _setupBranchTest() +{ + _eeFlushAllUnused(); + + // COP2 branch conditionals are based on the following equation: + // ((VU0.VI[REG_VPU_STAT].US[0] >> 8) & 1) + // BC2F checks if the statement is false, BC2T checks if the statement is true. + + MOV32MtoR( EAX, (uptr)&VU0.VI[REG_VPU_STAT].UL ); + TEST32ItoR( EAX, 0x100 ); +} + +void recBC2F( s32 info ) +{ + _setupBranchTest(); + recDoBranchImm(JNZ32(0)); +} + +void recBC2T( s32 info ) +{ + _setupBranchTest(); + recDoBranchImm(JZ32(0)); +} + +void recBC2FL( s32 info ) +{ + _setupBranchTest(); + recDoBranchImm_Likely(JNZ32(0)); +} + +void recBC2TL( s32 info ) +{ + _setupBranchTest(); + recDoBranchImm_Likely(JZ32(0)); +} + ////////////////////////////////////////////////////////////////////////// // Special1 instructions diff --git a/pcsx2/x86/iFPU.cpp b/pcsx2/x86/iFPU.cpp index da296ff6d0..07167cd64e 100644 --- a/pcsx2/x86/iFPU.cpp +++ b/pcsx2/x86/iFPU.cpp @@ -644,87 +644,44 @@ void recADDA_S_xmm(int info) FPURECOMPILE_CONSTCODE(ADDA_S, XMMINFO_WRITEACC|XMMINFO_READS|XMMINFO_READT); //------------------------------------------------------------------ - //------------------------------------------------------------------ // BC1x XMM //------------------------------------------------------------------ -void recBC1F( void ) { - u32 branchTo = (s32)_Imm_ * 4 + pc; - + +static void _setupBranchTest() +{ _eeFlushAllUnused(); + + // COP1 branch conditionals are based on the following equation: + // (fpuRegs.fprc[31] & 0x00800000) + // BC2F checks if the statement is false, BC2T checks if the statement is true. + MOV32MtoR(EAX, (uptr)&fpuRegs.fprc[31]); TEST32ItoR(EAX, FPUflagC); - j32Ptr[0] = JNZ32(0); - - SaveBranchState(); - recompileNextInstruction(1); - SetBranchImm(branchTo); - - x86SetJ32(j32Ptr[0]); - - // recopy the next inst - pc -= 4; - LoadBranchState(); - recompileNextInstruction(1); - - SetBranchImm(pc); } -void recBC1T( void ) { - u32 branchTo = (s32)_Imm_ * 4 + pc; - - _eeFlushAllUnused(); - MOV32MtoR(EAX, (uptr)&fpuRegs.fprc[31]); - TEST32ItoR(EAX, FPUflagC); - j32Ptr[0] = JZ32(0); - - SaveBranchState(); - recompileNextInstruction(1); - SetBranchImm(branchTo); - - x86SetJ32(j32Ptr[0]); - - // recopy the next inst - pc -= 4; - LoadBranchState(); - recompileNextInstruction(1); - - SetBranchImm(pc); +void recBC1F( void ) +{ + _setupBranchTest(); + recDoBranchImm(JNZ32(0)); } -void recBC1FL( void ) { - u32 branchTo = _Imm_ * 4 + pc; - - _eeFlushAllUnused(); - MOV32MtoR(EAX, (uptr)&fpuRegs.fprc[31]); - TEST32ItoR(EAX, FPUflagC); - j32Ptr[0] = JNZ32(0); - - SaveBranchState(); - recompileNextInstruction(1); - SetBranchImm(branchTo); - - x86SetJ32(j32Ptr[0]); - - LoadBranchState(); - SetBranchImm(pc); +void recBC1T( void ) +{ + _setupBranchTest(); + recDoBranchImm(JZ32(0)); } -void recBC1TL( void ) { - u32 branchTo = _Imm_ * 4 + pc; +void recBC1FL( void ) +{ + _setupBranchTest(); + recDoBranchImm_Likely(JNZ32(0)); +} - _eeFlushAllUnused(); - MOV32MtoR(EAX, (uptr)&fpuRegs.fprc[31]); - TEST32ItoR(EAX, FPUflagC); - j32Ptr[0] = JZ32(0); - - SaveBranchState(); - recompileNextInstruction(1); - SetBranchImm(branchTo); - x86SetJ32(j32Ptr[0]); - - LoadBranchState(); - SetBranchImm(pc); +void recBC1TL( void ) +{ + _setupBranchTest(); + recDoBranchImm_Likely(JZ32(0)); } //------------------------------------------------------------------ diff --git a/pcsx2/x86/iR5900.h b/pcsx2/x86/iR5900.h index 8df6c61d5d..3dcae15a7c 100644 --- a/pcsx2/x86/iR5900.h +++ b/pcsx2/x86/iR5900.h @@ -111,6 +111,11 @@ void SaveCW(int type); extern void recExecute(); // same as recCpu.Execute(), but faster (can be inline'd) +namespace R5900{ +namespace Dynarec { +extern void recDoBranchImm( u32* jmpSkip, bool isLikely = false ); +extern void recDoBranchImm_Likely( u32* jmpSkip ); +} } //////////////////////////////////////////////////////////////////// // Constant Propagation - From here to the end of the header! diff --git a/pcsx2/x86/iR5900Misc.cpp b/pcsx2/x86/iR5900Misc.cpp index 178d17c650..274c542996 100644 --- a/pcsx2/x86/iR5900Misc.cpp +++ b/pcsx2/x86/iR5900Misc.cpp @@ -7,6 +7,47 @@ namespace R5900 { namespace Dynarec { + +// R5900 branch hepler! +// Recompiles code for a branch test and/or skip, complete with delay slot +// handling. Note, for "likely" branches use iDoBranchImm_Likely instead, which +// handles delay slots differently. +// Parameters: +// jmpSkip - This parameter is the result of the appropriate J32 instruction +// (usually JZ32 or JNZ32). +void recDoBranchImm( u32* jmpSkip, bool isLikely ) +{ + // All R5900 branches use this format: + const u32 branchTo = ((s32)_Imm_ * 4) + pc; + + // First up is the Branch Taken Path : Save the recompiler's state, compile the + // DelaySlot, and issue a BranchTest insertion. The state is reloaded below for + // the "did not branch" path (maintains consts, register allocations, and other optimizations). + + SaveBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); + + // Jump target when the branch is *not* taken, skips the branchtest code + // insertion above. + x86SetJ32(jmpSkip); + + // if it's a likely branch then we'll need to skip the delay slot here, since + // MIPS cancels the delay slot instruction when branches aren't taken. + LoadBranchState(); + if( !isLikely ) + { + pc -= 4; // instruction rewinder for delay slot, if non-likely. + recompileNextInstruction(1); + } + SetBranchImm(pc); +} + +void recDoBranchImm_Likely( u32* jmpSkip ) +{ + recDoBranchImm( jmpSkip, true ); +} + namespace OpcodeImpl { //////////////////////////////////////////////////// diff --git a/pcsx2/x86/ix86-32/iR5900-32.cpp b/pcsx2/x86/ix86-32/iR5900-32.cpp index 1259f39743..c34540f009 100644 --- a/pcsx2/x86/ix86-32/iR5900-32.cpp +++ b/pcsx2/x86/ix86-32/iR5900-32.cpp @@ -1112,8 +1112,8 @@ void SaveBranchState() s_saveRegHasSignExt = g_cpuRegHasSignExt; // save all mmx regs - memcpy(s_saveMMXregs, mmxregs, sizeof(mmxregs)); - memcpy(s_saveXMMregs, xmmregs, sizeof(xmmregs)); + memcpy_fast(s_saveMMXregs, mmxregs, sizeof(mmxregs)); + memcpy_fast(s_saveXMMregs, xmmregs, sizeof(xmmregs)); } void LoadBranchState() @@ -1142,8 +1142,8 @@ void LoadBranchState() g_cpuRegHasSignExt = g_cpuPrevRegHasSignExt = s_saveRegHasSignExt; // restore all mmx regs - memcpy(mmxregs, s_saveMMXregs, sizeof(mmxregs)); - memcpy(xmmregs, s_saveXMMregs, sizeof(xmmregs)); + memcpy_fast(mmxregs, s_saveMMXregs, sizeof(mmxregs)); + memcpy_fast(xmmregs, s_saveXMMregs, sizeof(xmmregs)); } void iFlushCall(int flushtype)