/* Pcsx2 - Pc Ps2 Emulator * Copyright (C) 2002-2003 Pcsx2 Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ // recompiler reworked to add dynamic linking zerofrog(@gmail.com) Jan06 #include #include #include #include "Common.h" #include "InterTables.h" #include "ix86/ix86.h" #include "iR5900.h" #ifdef __WIN32__ #pragma warning(disable:4244) #pragma warning(disable:4761) #endif /********************************************************* * Register branch logic * * Format: OP rs, rt, offset * *********************************************************/ #ifndef BRANCH_RECOMPILE REC_SYS(BEQ); REC_SYS(BEQL); REC_SYS(BNE); REC_SYS(BNEL); REC_SYS(BLTZ); REC_SYS(BGTZ); REC_SYS(BLEZ); REC_SYS(BGEZ); REC_SYS(BGTZL); REC_SYS(BLTZL); REC_SYS(BLTZAL); REC_SYS(BLTZALL); REC_SYS(BLEZL); REC_SYS(BGEZL); REC_SYS(BGEZAL); REC_SYS(BGEZALL); #else #if defined(EE_CONST_PROP) void recSetBranchEQ(int info, int bne, int process) { if( info & PROCESS_EE_MMX ) { int t0reg; SetMMXstate(); if( process & PROCESS_CONSTS ) { if( (g_pCurInstInfo->regs[_Rt_] & EEINST_LASTUSE) || !EEINST_ISLIVEMMX(_Rt_) ) { _deleteMMXreg(_Rt_, 1); mmxregs[EEREC_T].inuse = 0; t0reg = EEREC_T; } else { t0reg = _allocMMXreg(-1, MMX_TEMP, 0); MOVQRtoR(t0reg, EEREC_T); } _flushConstReg(_Rs_); PCMPEQDMtoR(t0reg, (u32)&cpuRegs.GPR.r[_Rs_].UL[0]); if( t0reg != EEREC_T ) _freeMMXreg(t0reg); } else if( process & PROCESS_CONSTT ) { if( (g_pCurInstInfo->regs[_Rs_] & EEINST_LASTUSE) || !EEINST_ISLIVEMMX(_Rs_) ) { _deleteMMXreg(_Rs_, 1); mmxregs[EEREC_S].inuse = 0; t0reg = EEREC_S; } else { t0reg = _allocMMXreg(-1, MMX_TEMP, 0); MOVQRtoR(t0reg, EEREC_S); } _flushConstReg(_Rt_); PCMPEQDMtoR(t0reg, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); if( t0reg != EEREC_S ) _freeMMXreg(t0reg); } else { if( (g_pCurInstInfo->regs[_Rs_] & EEINST_LASTUSE) || !EEINST_ISLIVEMMX(_Rs_) ) { _deleteMMXreg(_Rs_, 1); mmxregs[EEREC_S].inuse = 0; t0reg = EEREC_S; PCMPEQDRtoR(t0reg, EEREC_T); } else if( (g_pCurInstInfo->regs[_Rt_] & EEINST_LASTUSE) || !EEINST_ISLIVEMMX(_Rt_) ) { _deleteMMXreg(_Rt_, 1); mmxregs[EEREC_T].inuse = 0; t0reg = EEREC_T; PCMPEQDRtoR(t0reg, EEREC_S); } else { t0reg = _allocMMXreg(-1, MMX_TEMP, 0); MOVQRtoR(t0reg, EEREC_S); PCMPEQDRtoR(t0reg, EEREC_T); } if( t0reg != EEREC_S && t0reg != EEREC_T ) _freeMMXreg(t0reg); } PMOVMSKBMMXtoR(EAX, t0reg); _eeFlushAllUnused(); CMP8ItoR( EAX, 0xff ); if( bne ) j32Ptr[ 1 ] = JE32( 0 ); else j32Ptr[ 0 ] = j32Ptr[ 1 ] = JNE32( 0 ); } else if( info & PROCESS_EE_XMM ) { int t0reg; if( process & PROCESS_CONSTS ) { if( (g_pCurInstInfo->regs[_Rt_] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(_Rt_) ) { _deleteGPRtoXMMreg(_Rt_, 1); xmmregs[EEREC_T].inuse = 0; t0reg = EEREC_T; } else { t0reg = _allocTempXMMreg(XMMT_INT, -1); SSE2_MOVQ_XMM_to_XMM(t0reg, EEREC_T); } _flushConstReg(_Rs_); SSE2_PCMPEQD_M128_to_XMM(t0reg, (u32)&cpuRegs.GPR.r[_Rs_].UL[0]); if( t0reg != EEREC_T ) _freeXMMreg(t0reg); } else if( process & PROCESS_CONSTT ) { if( (g_pCurInstInfo->regs[_Rs_] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(_Rs_) ) { _deleteGPRtoXMMreg(_Rs_, 1); xmmregs[EEREC_S].inuse = 0; t0reg = EEREC_S; } else { t0reg = _allocTempXMMreg(XMMT_INT, -1); SSE2_MOVQ_XMM_to_XMM(t0reg, EEREC_S); } _flushConstReg(_Rt_); SSE2_PCMPEQD_M128_to_XMM(t0reg, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); if( t0reg != EEREC_S ) _freeXMMreg(t0reg); } else { if( (g_pCurInstInfo->regs[_Rs_] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(_Rs_) ) { _deleteGPRtoXMMreg(_Rs_, 1); xmmregs[EEREC_S].inuse = 0; t0reg = EEREC_S; SSE2_PCMPEQD_XMM_to_XMM(t0reg, EEREC_T); } else if( (g_pCurInstInfo->regs[_Rt_] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(_Rt_) ) { _deleteGPRtoXMMreg(_Rt_, 1); xmmregs[EEREC_T].inuse = 0; t0reg = EEREC_T; SSE2_PCMPEQD_XMM_to_XMM(t0reg, EEREC_S); } else { t0reg = _allocTempXMMreg(XMMT_INT, -1); SSE2_MOVQ_XMM_to_XMM(t0reg, EEREC_S); SSE2_PCMPEQD_XMM_to_XMM(t0reg, EEREC_T); } if( t0reg != EEREC_S && t0reg != EEREC_T ) _freeXMMreg(t0reg); } SSE_MOVMSKPS_XMM_to_R32(EAX, t0reg); _eeFlushAllUnused(); AND8ItoR(EAX, 3); CMP8ItoR( EAX, 0x3 ); if( bne ) j32Ptr[ 1 ] = JE32( 0 ); else j32Ptr[ 0 ] = j32Ptr[ 1 ] = JNE32( 0 ); } else { _eeFlushAllUnused(); if( bne ) { if( process & PROCESS_CONSTS ) { CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], g_cpuConstRegs[_Rs_].UL[0] ); j8Ptr[ 0 ] = JNE8( 0 ); CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], g_cpuConstRegs[_Rs_].UL[1] ); j32Ptr[ 1 ] = JE32( 0 ); } else if( process & PROCESS_CONSTT ) { CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], g_cpuConstRegs[_Rt_].UL[0] ); j8Ptr[ 0 ] = JNE8( 0 ); CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], g_cpuConstRegs[_Rt_].UL[1] ); j32Ptr[ 1 ] = JE32( 0 ); } else { MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); CMP32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); j8Ptr[ 0 ] = JNE8( 0 ); MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); CMP32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); j32Ptr[ 1 ] = JE32( 0 ); } x86SetJ8( j8Ptr[0] ); } else { // beq if( process & PROCESS_CONSTS ) { CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], g_cpuConstRegs[_Rs_].UL[0] ); j32Ptr[ 0 ] = JNE32( 0 ); CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], g_cpuConstRegs[_Rs_].UL[1] ); j32Ptr[ 1 ] = JNE32( 0 ); } else if( process & PROCESS_CONSTT ) { CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], g_cpuConstRegs[_Rt_].UL[0] ); j32Ptr[ 0 ] = JNE32( 0 ); CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], g_cpuConstRegs[_Rt_].UL[1] ); j32Ptr[ 1 ] = JNE32( 0 ); } else { MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); CMP32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); j32Ptr[ 0 ] = JNE32( 0 ); MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); CMP32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); j32Ptr[ 1 ] = JNE32( 0 ); } } } _clearNeededMMXregs(); _clearNeededXMMregs(); } void recSetBranchL(int ltz) { int regs = _checkMMXreg(MMX_GPR+_Rs_, MODE_READ); if( regs >= 0 ) { int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); SetMMXstate(); PXORRtoR(t0reg, t0reg); PCMPGTDRtoR(t0reg, regs); PMOVMSKBMMXtoR(EAX, t0reg); _freeMMXreg(t0reg); _eeFlushAllUnused(); TEST8ItoR( EAX, 0x80 ); if( ltz ) j32Ptr[ 0 ] = JZ32( 0 ); else j32Ptr[ 0 ] = JNZ32( 0 ); return; } regs = _checkXMMreg(XMMTYPE_GPRREG, _Rs_, MODE_READ); if( regs >= 0 ) { int t0reg = _allocTempXMMreg(XMMT_INT, -1); SSE_XORPS_XMM_to_XMM(t0reg, t0reg); SSE2_PCMPGTD_XMM_to_XMM(t0reg, regs); SSE_MOVMSKPS_XMM_to_R32(EAX, t0reg); _freeXMMreg(t0reg); _eeFlushAllUnused(); TEST8ItoR( EAX, 2 ); if( ltz ) j32Ptr[ 0 ] = JZ32( 0 ); else j32Ptr[ 0 ] = JNZ32( 0 ); return; } CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], 0 ); if( ltz ) j32Ptr[ 0 ] = JGE32( 0 ); else j32Ptr[ 0 ] = JL32( 0 ); _clearNeededMMXregs(); _clearNeededXMMregs(); } //// BEQ void recBEQ_const() { u32 branchTo; if( g_cpuConstRegs[_Rs_].SD[0] == g_cpuConstRegs[_Rt_].SD[0] ) branchTo = ((s32)_Imm_ * 4) + pc; else branchTo = pc+4; recompileNextInstruction(1); SetBranchImm( branchTo ); } void recBEQ_process(int info, int process) { u32 branchTo = ((s32)_Imm_ * 4) + pc; if ( _Rs_ == _Rt_ ) { recompileNextInstruction(1); SetBranchImm( branchTo ); } else { recSetBranchEQ(info, 0, process); SaveBranchState(); recompileNextInstruction(1); SetBranchImm(branchTo); x86SetJ32( j32Ptr[ 0 ] ); x86SetJ32( j32Ptr[ 1 ] ); // recopy the next inst pc -= 4; LoadBranchState(); recompileNextInstruction(1); SetBranchImm(pc); } } void recBEQ_(int info) { recBEQ_process(info, 0); } void recBEQ_consts(int info) { recBEQ_process(info, PROCESS_CONSTS); } void recBEQ_constt(int info) { recBEQ_process(info, PROCESS_CONSTT); } EERECOMPILE_CODE0(BEQ, XMMINFO_READS|XMMINFO_READT); //// BNE void recBNE_const() { u32 branchTo; if( g_cpuConstRegs[_Rs_].SD[0] != g_cpuConstRegs[_Rt_].SD[0] ) branchTo = ((s32)_Imm_ * 4) + pc; else branchTo = pc+4; recompileNextInstruction(1); SetBranchImm( branchTo ); } void recBNE_process(int info, int process) { u32 branchTo = ((s32)_Imm_ * 4) + pc; if ( _Rs_ == _Rt_ ) { recompileNextInstruction(1); SetBranchImm(pc); return; } recSetBranchEQ(info, 1, process); SaveBranchState(); recompileNextInstruction(1); SetBranchImm(branchTo); x86SetJ32( j32Ptr[ 1 ] ); // recopy the next inst pc -= 4; LoadBranchState(); recompileNextInstruction(1); SetBranchImm(pc); } void recBNE_(int info) { recBNE_process(info, 0); } void recBNE_consts(int info) { recBNE_process(info, PROCESS_CONSTS); } void recBNE_constt(int info) { recBNE_process(info, PROCESS_CONSTT); } EERECOMPILE_CODE0(BNE, XMMINFO_READS|XMMINFO_READT); //// BEQL void recBEQL_const() { if( g_cpuConstRegs[_Rs_].SD[0] == g_cpuConstRegs[_Rt_].SD[0] ) { u32 branchTo = ((s32)_Imm_ * 4) + pc; recompileNextInstruction(1); SetBranchImm( branchTo ); } else { SetBranchImm( pc+4 ); } } void recBEQL_process(int info, int process) { u32 branchTo = ((s32)_Imm_ * 4) + pc; recSetBranchEQ(info, 0, process); SaveBranchState(); recompileNextInstruction(1); SetBranchImm(branchTo); x86SetJ32( j32Ptr[ 0 ] ); x86SetJ32( j32Ptr[ 1 ] ); LoadBranchState(); SetBranchImm(pc); } void recBEQL_(int info) { recBEQL_process(info, 0); } void recBEQL_consts(int info) { recBEQL_process(info, PROCESS_CONSTS); } void recBEQL_constt(int info) { recBEQL_process(info, PROCESS_CONSTT); } EERECOMPILE_CODE0(BEQL, XMMINFO_READS|XMMINFO_READT); //// BNEL void recBNEL_const() { if( g_cpuConstRegs[_Rs_].SD[0] != g_cpuConstRegs[_Rt_].SD[0] ) { u32 branchTo = ((s32)_Imm_ * 4) + pc; recompileNextInstruction(1); SetBranchImm(branchTo); } else { SetBranchImm( pc+4 ); } } void recBNEL_process(int info, int process) { u32 branchTo = ((s32)_Imm_ * 4) + pc; recSetBranchEQ(info, 0, process); SaveBranchState(); SetBranchImm(pc+4); x86SetJ32( j32Ptr[ 0 ] ); x86SetJ32( j32Ptr[ 1 ] ); // recopy the next inst LoadBranchState(); recompileNextInstruction(1); SetBranchImm(branchTo); } void recBNEL_(int info) { recBNEL_process(info, 0); } void recBNEL_consts(int info) { recBNEL_process(info, PROCESS_CONSTS); } void recBNEL_constt(int info) { recBNEL_process(info, PROCESS_CONSTT); } EERECOMPILE_CODE0(BNEL, XMMINFO_READS|XMMINFO_READT); /********************************************************* * Register branch logic * * Format: OP rs, offset * *********************************************************/ //////////////////////////////////////////////////// //void recBLTZAL( void ) //{ // SysPrintf("BLTZAL\n"); // _eeFlushAllUnused(); // MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); // MOV32ItoM( (int)&cpuRegs.pc, pc ); // iFlushCall(FLUSH_EVERYTHING); // CALLFunc( (int)BLTZAL ); // branch = 2; //} //////////////////////////////////////////////////// void recBLTZAL(int info) { u32 branchTo = ((s32)_Imm_ * 4) + pc; SysPrintf("BLTZAL\n"); _eeOnWriteReg(31, 0); _eeFlushAllUnused(); _deleteEEreg(31, 0); MOV32ItoM((u32)&cpuRegs.GPR.r[31].UL[0], pc+4); MOV32ItoM((u32)&cpuRegs.GPR.r[31].UL[1], 0); if( GPR_IS_CONST1(_Rs_) ) { if( !(g_cpuConstRegs[_Rs_].SD[0] < 0) ) branchTo = pc+4; recompileNextInstruction(1); SetBranchImm( branchTo ); return; } recSetBranchL(1); SaveBranchState(); recompileNextInstruction(1); SetBranchImm(branchTo); x86SetJ32( j32Ptr[ 0 ] ); // recopy the next inst pc -= 4; LoadBranchState(); recompileNextInstruction(1); SetBranchImm(pc); } //////////////////////////////////////////////////// void recBGEZAL( void ) { SysPrintf("BGEZAL\n"); _eeFlushAllUnused(); MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); MOV32ItoM( (int)&cpuRegs.pc, pc ); iFlushCall(FLUSH_EVERYTHING); CALLFunc( (int)BGEZAL ); branch = 2; } //////////////////////////////////////////////////// void recBLTZALL( void ) { SysPrintf("BLTZALL\n"); _eeFlushAllUnused(); MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); MOV32ItoM( (int)&cpuRegs.pc, pc ); iFlushCall(FLUSH_EVERYTHING); CALLFunc( (int)BLTZALL ); branch = 2; } //////////////////////////////////////////////////// void recBGEZALL( void ) { SysPrintf("BGEZALL\n"); _eeFlushAllUnused(); MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); MOV32ItoM( (int)&cpuRegs.pc, pc ); iFlushCall(FLUSH_EVERYTHING); CALLFunc( (int)BGEZALL ); branch = 2; } #else //////////////////////////////////////////////////// void recBEQ( void ) { u32 branchTo = ((s32)_Imm_ * 4) + pc; if ( _Rs_ == _Rt_ ) { _clearNeededMMXregs(); _clearNeededXMMregs(); recompileNextInstruction(1); SetBranchImm( branchTo ); } else { MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); CMP32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); j32Ptr[ 0 ] = JNE32( 0 ); MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); CMP32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); j32Ptr[ 1 ] = JNE32( 0 ); _clearNeededMMXregs(); _clearNeededXMMregs(); SaveBranchState(); recompileNextInstruction(1); SetBranchImm(branchTo); x86SetJ32( j32Ptr[ 0 ] ); x86SetJ32( j32Ptr[ 1 ] ); // recopy the next inst pc -= 4; LoadBranchState(); recompileNextInstruction(1); SetBranchImm(pc); } } //////////////////////////////////////////////////// void recBNE( void ) { u32 branchTo = ((s32)_Imm_ * 4) + pc; if ( _Rs_ == _Rt_ ) { _clearNeededMMXregs(); _clearNeededXMMregs(); recompileNextInstruction(1); SetBranchImm(pc); return; } MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); CMP32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); j32Ptr[ 0 ] = JNE32( 0 ); MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); CMP32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); j32Ptr[ 1 ] = JE32( 0 ); x86SetJ32( j32Ptr[ 0 ] ); _clearNeededMMXregs(); _clearNeededXMMregs(); SaveBranchState(); recompileNextInstruction(1); SetBranchImm(branchTo); x86SetJ32( j32Ptr[ 1 ] ); // recopy the next inst pc -= 4; LoadBranchState(); recompileNextInstruction(1); SetBranchImm(pc); } //////////////////////////////////////////////////// void recBEQL( void ) { u32 branchTo = ((s32)_Imm_ * 4) + pc; MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); CMP32RtoR( ECX, EDX ); j32Ptr[ 0 ] = JNE32( 0 ); MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); CMP32RtoR( ECX, EDX ); j32Ptr[ 1 ] = JNE32( 0 ); _clearNeededMMXregs(); _clearNeededXMMregs(); SaveBranchState(); recompileNextInstruction(1); SetBranchImm(branchTo); x86SetJ32( j32Ptr[ 0 ] ); x86SetJ32( j32Ptr[ 1 ] ); LoadBranchState(); SetBranchImm(pc); } //////////////////////////////////////////////////// void recBNEL( void ) { u32 branchTo = ((s32)_Imm_ * 4) + pc; MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); CMP32RtoR( ECX, EDX ); j32Ptr[ 0 ] = JNE32( 0 ); MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); CMP32RtoR( ECX, EDX ); j32Ptr[ 1 ] = JNE32( 0 ); _clearNeededMMXregs(); _clearNeededXMMregs(); SaveBranchState(); SetBranchImm(pc+4); x86SetJ32( j32Ptr[ 0 ] ); x86SetJ32( j32Ptr[ 1 ] ); // recopy the next inst LoadBranchState(); recompileNextInstruction(1); SetBranchImm(branchTo); } /********************************************************* * Register branch logic * * Format: OP rs, offset * *********************************************************/ //////////////////////////////////////////////////// void recBLTZAL( void ) { MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); MOV32ItoM( (int)&cpuRegs.pc, pc ); iFlushCall(FLUSH_EVERYTHING); CALLFunc( (int)BLTZAL ); branch = 2; } //////////////////////////////////////////////////// void recBGEZAL( void ) { MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); MOV32ItoM( (int)&cpuRegs.pc, pc ); iFlushCall(FLUSH_EVERYTHING); CALLFunc( (int)BGEZAL ); branch = 2; } //////////////////////////////////////////////////// void recBLTZALL( void ) { SysPrintf("BLTZALL\n"); MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); MOV32ItoM( (int)&cpuRegs.pc, pc ); iFlushCall(FLUSH_EVERYTHING); CALLFunc( (int)BLTZALL ); branch = 2; } //////////////////////////////////////////////////// void recBGEZALL( void ) { SysPrintf("BGEZALL\n"); MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); MOV32ItoM( (int)&cpuRegs.pc, pc ); iFlushCall(FLUSH_EVERYTHING); CALLFunc( (int)BGEZALL ); branch = 2; } #endif //// BLEZ void recBLEZ( void ) { u32 branchTo = ((s32)_Imm_ * 4) + pc; _eeFlushAllUnused(); if( GPR_IS_CONST1(_Rs_) ) { if( !(g_cpuConstRegs[_Rs_].SD[0] <= 0) ) branchTo = pc+4; recompileNextInstruction(1); SetBranchImm( branchTo ); return; } _deleteEEreg(_Rs_, 1); CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], 0 ); j8Ptr[ 0 ] = JL8( 0 ); j32Ptr[ 1 ] = JG32( 0 ); CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], 0 ); j32Ptr[ 2 ] = JNZ32( 0 ); x86SetJ8( j8Ptr[ 0 ] ); _clearNeededMMXregs(); _clearNeededXMMregs(); SaveBranchState(); recompileNextInstruction(1); SetBranchImm(branchTo); x86SetJ32( j32Ptr[ 1 ] ); x86SetJ32( j32Ptr[ 2 ] ); // recopy the next inst pc -= 4; LoadBranchState(); recompileNextInstruction(1); SetBranchImm(pc); } //// BGTZ void recBGTZ( void ) { u32 branchTo = ((s32)_Imm_ * 4) + pc; _eeFlushAllUnused(); if( GPR_IS_CONST1(_Rs_) ) { if( !(g_cpuConstRegs[_Rs_].SD[0] > 0) ) branchTo = pc+4; recompileNextInstruction(1); SetBranchImm( branchTo ); return; } _deleteEEreg(_Rs_, 1); CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], 0 ); j8Ptr[ 0 ] = JG8( 0 ); j32Ptr[ 1 ] = JL32( 0 ); CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], 0 ); j32Ptr[ 2 ] = JZ32( 0 ); x86SetJ8( j8Ptr[ 0 ] ); _clearNeededMMXregs(); _clearNeededXMMregs(); SaveBranchState(); recompileNextInstruction(1); SetBranchImm(branchTo); x86SetJ32( j32Ptr[ 1 ] ); x86SetJ32( j32Ptr[ 2 ] ); // recopy the next inst pc -= 4; LoadBranchState(); recompileNextInstruction(1); SetBranchImm(pc); } //////////////////////////////////////////////////// void recBLTZ() { u32 branchTo = ((s32)_Imm_ * 4) + pc; _eeFlushAllUnused(); if( GPR_IS_CONST1(_Rs_) ) { if( !(g_cpuConstRegs[_Rs_].SD[0] < 0) ) branchTo = pc+4; recompileNextInstruction(1); SetBranchImm( branchTo ); return; } recSetBranchL(1); SaveBranchState(); recompileNextInstruction(1); SetBranchImm(branchTo); x86SetJ32( j32Ptr[ 0 ] ); // recopy the next inst pc -= 4; LoadBranchState(); recompileNextInstruction(1); SetBranchImm(pc); } //////////////////////////////////////////////////// void recBGEZ( void ) { u32 branchTo = ((s32)_Imm_ * 4) + pc; _eeFlushAllUnused(); if( GPR_IS_CONST1(_Rs_) ) { if( !(g_cpuConstRegs[_Rs_].SD[0] >= 0) ) branchTo = pc+4; recompileNextInstruction(1); SetBranchImm( branchTo ); return; } recSetBranchL(0); SaveBranchState(); recompileNextInstruction(1); SetBranchImm(branchTo); x86SetJ32( j32Ptr[ 0 ] ); // recopy the next inst pc -= 4; LoadBranchState(); recompileNextInstruction(1); SetBranchImm(pc); } /********************************************************* * Register branch logic Likely * * Format: OP rs, offset * *********************************************************/ //////////////////////////////////////////////////// void recBLEZL( void ) { u32 branchTo = ((s32)_Imm_ * 4) + pc; _eeFlushAllUnused(); if( GPR_IS_CONST1(_Rs_) ) { if( !(g_cpuConstRegs[_Rs_].SD[0] <= 0) ) SetBranchImm( pc + 4); else { _clearNeededMMXregs(); _clearNeededXMMregs(); recompileNextInstruction(1); SetBranchImm( branchTo ); } return; } _deleteEEreg(_Rs_, 1); CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], 0 ); j32Ptr[ 0 ] = JL32( 0 ); j32Ptr[ 1 ] = JG32( 0 ); CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], 0 ); j32Ptr[ 2 ] = JNZ32( 0 ); x86SetJ32( j32Ptr[ 0 ] ); _clearNeededMMXregs(); _clearNeededXMMregs(); SaveBranchState(); recompileNextInstruction(1); SetBranchImm(branchTo); x86SetJ32( j32Ptr[ 1 ] ); x86SetJ32( j32Ptr[ 2 ] ); LoadBranchState(); SetBranchImm(pc); } //////////////////////////////////////////////////// void recBGTZL( void ) { u32 branchTo = ((s32)_Imm_ * 4) + pc; _eeFlushAllUnused(); if( GPR_IS_CONST1(_Rs_) ) { if( !(g_cpuConstRegs[_Rs_].SD[0] > 0) ) SetBranchImm( pc + 4); else { _clearNeededMMXregs(); _clearNeededXMMregs(); recompileNextInstruction(1); SetBranchImm( branchTo ); } return; } _deleteEEreg(_Rs_, 1); CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], 0 ); j32Ptr[ 0 ] = JG32( 0 ); j32Ptr[ 1 ] = JL32( 0 ); CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], 0 ); j32Ptr[ 2 ] = JZ32( 0 ); x86SetJ32( j32Ptr[ 0 ] ); _clearNeededMMXregs(); _clearNeededXMMregs(); SaveBranchState(); recompileNextInstruction(1); SetBranchImm(branchTo); x86SetJ32( j32Ptr[ 1 ] ); x86SetJ32( j32Ptr[ 2 ] ); LoadBranchState(); SetBranchImm(pc); } //////////////////////////////////////////////////// void recBLTZL( void ) { u32 branchTo = ((s32)_Imm_ * 4) + pc; _eeFlushAllUnused(); if( GPR_IS_CONST1(_Rs_) ) { if( !(g_cpuConstRegs[_Rs_].SD[0] < 0) ) SetBranchImm( pc + 4); else { recompileNextInstruction(1); SetBranchImm( branchTo ); } return; } recSetBranchL(1); SaveBranchState(); recompileNextInstruction(1); SetBranchImm(branchTo); x86SetJ32( j32Ptr[ 0 ] ); LoadBranchState(); SetBranchImm(pc); } //////////////////////////////////////////////////// void recBGEZL( void ) { u32 branchTo = ((s32)_Imm_ * 4) + pc; _eeFlushAllUnused(); if( GPR_IS_CONST1(_Rs_) ) { if( !(g_cpuConstRegs[_Rs_].SD[0] >= 0) ) SetBranchImm( pc + 4); else { recompileNextInstruction(1); SetBranchImm( branchTo ); } return; } recSetBranchL(0); SaveBranchState(); recompileNextInstruction(1); SetBranchImm(branchTo); x86SetJ32( j32Ptr[ 0 ] ); LoadBranchState(); SetBranchImm(pc); } #endif