pcsx2/ix86-32/iR5900Branch.c
2007-04-02 01:06:17 +00:00

1087 lines
No EOL
24 KiB
C

/* 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 <stdlib.h>
#include <string.h>
#include <assert.h>
#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