mirror of https://github.com/PCSX2/pcsx2.git
1997 lines
52 KiB
C
1997 lines
52 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
|
|
*/
|
|
|
|
#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 arithmetic *
|
|
* Format: OP rd, rs, rt *
|
|
*********************************************************/
|
|
|
|
// NOTE: The reason ADD/SUB/etc are so large is because they are very commonly
|
|
// used and recompiler needs to cover ALL possible usages to minimize code size (zerofrog)
|
|
|
|
#ifndef ARITHMETIC_RECOMPILE
|
|
|
|
REC_FUNC(ADD);
|
|
REC_FUNC(ADDU);
|
|
REC_FUNC(DADD);
|
|
REC_FUNC(DADDU);
|
|
REC_FUNC(SUB);
|
|
REC_FUNC(SUBU);
|
|
REC_FUNC(DSUB);
|
|
REC_FUNC(DSUBU);
|
|
REC_FUNC(AND);
|
|
REC_FUNC(OR);
|
|
REC_FUNC(XOR);
|
|
REC_FUNC(NOR);
|
|
REC_FUNC(SLT);
|
|
REC_FUNC(SLTU);
|
|
|
|
#elif defined(EE_CONST_PROP)
|
|
|
|
//// ADD
|
|
void recADD_const()
|
|
{
|
|
g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].SL[0] + g_cpuConstRegs[_Rt_].SL[0];
|
|
}
|
|
|
|
void recADD_constv(int info, int creg, int vreg)
|
|
{
|
|
assert( !(info&PROCESS_EE_XMM) );
|
|
|
|
if( info & PROCESS_EE_MMX ) {
|
|
int mmreg = vreg == _Rt_ ? EEREC_T : EEREC_S;
|
|
|
|
if( g_cpuConstRegs[ creg ].UL[0] ) {
|
|
u32* ptempmem;
|
|
|
|
ptempmem = _eeGetConstReg(creg);
|
|
if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg);
|
|
PADDDMtoR(EEREC_D, (u32)ptempmem);
|
|
|
|
_signExtendGPRtoMMX(EEREC_D, _Rd_, 0);
|
|
}
|
|
else {
|
|
// just move and sign extend
|
|
if( EEINST_HASLIVE1(vreg) ) {
|
|
if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg);
|
|
}
|
|
else {
|
|
_signExtendGPRMMXtoMMX(EEREC_D, _Rd_, mmreg, vreg);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
|
|
if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) && (!EEINST_ISLIVE1(_Rd_) || !g_cpuConstRegs[ creg ].UL[0]) ) {
|
|
int mmreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE);
|
|
SetMMXstate();
|
|
|
|
if( EEINST_HASLIVE1(vreg) && EEINST_ISLIVE1(_Rd_) ) {
|
|
MOVQMtoR(mmreg, (int)&cpuRegs.GPR.r[ vreg ].UL[ 0 ]);
|
|
}
|
|
else {
|
|
if( g_cpuConstRegs[creg].UL[0] ) {
|
|
MOVDMtoMMX(mmreg, (u32)_eeGetConstReg(creg));
|
|
PADDDMtoR(mmreg, (u32)&cpuRegs.GPR.r[ vreg ].UL[ 0 ]);
|
|
}
|
|
else {
|
|
if( EEINST_ISLIVE1(_Rd_) ) {
|
|
_signExtendMtoMMX(mmreg, (u32)&cpuRegs.GPR.r[ vreg ].UL[ 0 ]);
|
|
}
|
|
else {
|
|
MOVDMtoMMX(mmreg, (u32)&cpuRegs.GPR.r[ vreg ].UL[ 0 ]);
|
|
EEINST_RESETHASLIVE1(_Rd_);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
if( _Rd_ == vreg ) {
|
|
ADD32ItoM((int)&cpuRegs.GPR.r[_Rd_].UL[ 0 ], g_cpuConstRegs[creg].UL[0]);
|
|
if( EEINST_ISLIVE1(_Rd_) ) _signExtendSFtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ]);
|
|
else EEINST_RESETHASLIVE1(_Rd_);
|
|
}
|
|
else {
|
|
MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ vreg ].UL[ 0 ] );
|
|
if( g_cpuConstRegs[ creg ].UL[0] )
|
|
ADD32ItoR( EAX, g_cpuConstRegs[ creg ].UL[0] );
|
|
|
|
if( EEINST_ISLIVE1(_Rd_) ) {
|
|
CDQ( );
|
|
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX );
|
|
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX );
|
|
}
|
|
else {
|
|
EEINST_RESETHASLIVE1(_Rd_);
|
|
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// s is constant
|
|
void recADD_consts(int info)
|
|
{
|
|
recADD_constv(info, _Rs_, _Rt_);
|
|
EEINST_SETSIGNEXT(_Rd_);
|
|
EEINST_SETSIGNEXT(_Rt_);
|
|
}
|
|
|
|
// t is constant
|
|
void recADD_constt(int info)
|
|
{
|
|
recADD_constv(info, _Rt_, _Rs_);
|
|
EEINST_SETSIGNEXT(_Rd_);
|
|
EEINST_SETSIGNEXT(_Rs_);
|
|
}
|
|
|
|
// nothing is constant
|
|
void recADD_(int info)
|
|
{
|
|
assert( !(info&PROCESS_EE_XMM) );
|
|
EEINST_SETSIGNEXT(_Rd_);
|
|
EEINST_SETSIGNEXT(_Rs_);
|
|
EEINST_SETSIGNEXT(_Rt_);
|
|
|
|
if( info & PROCESS_EE_MMX ) {
|
|
|
|
if( EEREC_D == EEREC_S ) PADDDRtoR(EEREC_D, EEREC_T);
|
|
else if( EEREC_D == EEREC_T ) PADDDRtoR(EEREC_D, EEREC_S);
|
|
else {
|
|
MOVQRtoR(EEREC_D, EEREC_T);
|
|
PADDDRtoR(EEREC_D, EEREC_S);
|
|
}
|
|
|
|
if( EEINST_ISLIVE1(_Rd_) ) {
|
|
// sign extend
|
|
_signExtendGPRtoMMX(EEREC_D, _Rd_, 0);
|
|
}
|
|
else {
|
|
EEINST_RESETHASLIVE1(_Rd_);
|
|
}
|
|
}
|
|
else {
|
|
|
|
if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) && !EEINST_ISLIVE1(_Rd_) ) {
|
|
int mmreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE);
|
|
SetMMXstate();
|
|
|
|
EEINST_RESETHASLIVE1(_Rd_);
|
|
MOVDMtoMMX(mmreg, (int)&cpuRegs.GPR.r[_Rs_].UL[0] );
|
|
PADDDMtoR(mmreg, (int)&cpuRegs.GPR.r[_Rt_].UL[0] );
|
|
}
|
|
else {
|
|
if( _Rd_ == _Rs_ ) {
|
|
if( _Rd_ == _Rt_ ) SHL32ItoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], 1); // mult by 2
|
|
else {
|
|
MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]);
|
|
ADD32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], ECX);
|
|
}
|
|
|
|
if( EEINST_ISLIVE1(_Rd_) ) _signExtendSFtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ]);
|
|
else EEINST_RESETHASLIVE1(_Rd_);
|
|
|
|
return;
|
|
}
|
|
else if( _Rd_ == _Rt_ ) {
|
|
EEINST_RESETHASLIVE1(_Rd_);
|
|
MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]);
|
|
ADD32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], ECX);
|
|
|
|
if( EEINST_ISLIVE1(_Rd_) ) _signExtendSFtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ]);
|
|
else EEINST_RESETHASLIVE1(_Rd_);
|
|
}
|
|
else {
|
|
MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] );
|
|
if( _Rs_ != _Rt_ ) ADD32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] );
|
|
else SHL32ItoR(EAX, 1); // mult by 2
|
|
|
|
if( EEINST_ISLIVE1(_Rd_) ) {
|
|
CDQ( );
|
|
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX );
|
|
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX );
|
|
}
|
|
else {
|
|
EEINST_RESETHASLIVE1(_Rd_);
|
|
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
EERECOMPILE_CODE0(ADD, XMMINFO_WRITED|XMMINFO_READS|XMMINFO_READT);
|
|
|
|
//// ADDU
|
|
void recADDU( void )
|
|
{
|
|
recADD( );
|
|
}
|
|
|
|
//// DADD
|
|
void recDADD_const( void )
|
|
{
|
|
g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].SD[0] + g_cpuConstRegs[_Rt_].SD[0];
|
|
}
|
|
|
|
void recDADD_constv(int info, int creg, int vreg)
|
|
{
|
|
assert( !(info&PROCESS_EE_XMM) );
|
|
|
|
if( info & PROCESS_EE_MMX ) {
|
|
int mmreg = vreg == _Rt_ ? EEREC_T : EEREC_S;
|
|
assert( cpucaps.hasStreamingSIMD2Extensions );
|
|
|
|
if( g_cpuConstRegs[ creg ].UD[0] ) {
|
|
|
|
if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg);
|
|
PADDQMtoR(EEREC_D, (u32)_eeGetConstReg(creg));
|
|
}
|
|
else {
|
|
if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg);
|
|
}
|
|
}
|
|
else {
|
|
|
|
if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) && cpucaps.hasStreamingSIMD2Extensions ) {
|
|
int mmreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE);
|
|
SetMMXstate();
|
|
|
|
MOVQMtoR(mmreg, (int)&cpuRegs.GPR.r[ vreg ].UL[ 0 ]);
|
|
if( g_cpuConstRegs[ creg ].UD[0] ) PADDQMtoR(mmreg, (u32)_eeGetConstReg(creg));
|
|
}
|
|
else {
|
|
|
|
if( g_cpuConstRegs[ creg ].UL[0] == 0 && g_cpuConstRegs[ creg ].UL[1] == 0 && _hasFreeMMXreg() ) {
|
|
// copy
|
|
int mmreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE);
|
|
if( EEINST_ISLIVE1(_Rd_) ) MOVQMtoR(mmreg, (int)&cpuRegs.GPR.r[ vreg ].UL[ 0 ]);
|
|
else {
|
|
MOVDMtoMMX(mmreg, (int)&cpuRegs.GPR.r[ vreg ].UL[ 0 ]);
|
|
EEINST_RESETHASLIVE1(_Rd_);
|
|
}
|
|
}
|
|
else {
|
|
if( _Rd_ == vreg ) {
|
|
|
|
if( EEINST_ISLIVE1(_Rd_) && (g_cpuConstRegs[ creg ].UL[ 0 ] || g_cpuConstRegs[ creg ].UL[ 1 ]) ) {
|
|
ADD32ItoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[0], g_cpuConstRegs[ creg ].UL[ 0 ] );
|
|
ADC32ItoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[1], g_cpuConstRegs[ creg ].UL[ 1 ] );
|
|
}
|
|
else if( g_cpuConstRegs[ creg ].UL[ 0 ] ) {
|
|
EEINST_RESETHASLIVE1(_Rd_);
|
|
ADD32ItoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[0], g_cpuConstRegs[ creg ].UL[ 0 ] );
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ vreg ].UL[ 0 ] );
|
|
|
|
if( EEINST_ISLIVE1(_Rd_) )
|
|
MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ vreg ].UL[ 1 ] );
|
|
|
|
if( g_cpuConstRegs[ creg ].UL[0] || g_cpuConstRegs[ creg ].UL[1] ) {
|
|
ADD32ItoR( EAX, g_cpuConstRegs[ creg ].UL[ 0 ] );
|
|
if( EEINST_ISLIVE1(_Rd_) )
|
|
ADC32ItoR( EDX, g_cpuConstRegs[ creg ].UL[ 1 ] );
|
|
}
|
|
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX );
|
|
|
|
if( EEINST_ISLIVE1(_Rd_) )
|
|
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX );
|
|
|
|
if( !EEINST_ISLIVE1(_Rd_) )
|
|
EEINST_RESETHASLIVE1(_Rd_);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void recDADD_consts(int info)
|
|
{
|
|
recDADD_constv(info, _Rs_, _Rt_);
|
|
}
|
|
|
|
void recDADD_constt(int info)
|
|
{
|
|
recDADD_constv(info, _Rt_, _Rs_);
|
|
}
|
|
|
|
void recDADD_(int info)
|
|
{
|
|
assert( !(info&PROCESS_EE_XMM) );
|
|
|
|
if( info & PROCESS_EE_MMX ) {
|
|
assert( cpucaps.hasStreamingSIMD2Extensions );
|
|
|
|
if( EEREC_D == EEREC_S ) PADDQRtoR(EEREC_D, EEREC_T);
|
|
else if( EEREC_D == EEREC_T ) PADDQRtoR(EEREC_D, EEREC_S);
|
|
else {
|
|
MOVQRtoR(EEREC_D, EEREC_T);
|
|
PADDQRtoR(EEREC_D, EEREC_S);
|
|
}
|
|
}
|
|
else {
|
|
if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) && cpucaps.hasStreamingSIMD2Extensions ) {
|
|
int mmreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE);
|
|
|
|
MOVQMtoR(mmreg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]);
|
|
if( _Rs_ != _Rt_ ) PADDQMtoR(mmreg, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]);
|
|
else PSLLQItoR(mmreg, 1); // mult by 2
|
|
}
|
|
else {
|
|
if( _Rd_ == _Rs_ || _Rd_ == _Rt_ ) {
|
|
int vreg = _Rd_ == _Rs_ ? _Rt_ : _Rs_;
|
|
MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ vreg ].UL[ 0 ] );
|
|
if( EEINST_ISLIVE1(_Rd_) )
|
|
MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ vreg ].UL[ 1 ] );
|
|
ADD32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX);
|
|
if( EEINST_ISLIVE1(_Rd_) )
|
|
ADC32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX);
|
|
else
|
|
EEINST_RESETHASLIVE1(_Rd_);
|
|
}
|
|
else {
|
|
MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] );
|
|
if( EEINST_ISLIVE1(_Rd_) )
|
|
MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] );
|
|
ADD32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] );
|
|
if( EEINST_ISLIVE1(_Rd_) )
|
|
ADC32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] );
|
|
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX );
|
|
if( EEINST_ISLIVE1(_Rd_) )
|
|
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX );
|
|
|
|
if( !EEINST_ISLIVE1(_Rd_) )
|
|
EEINST_RESETHASLIVE1(_Rd_);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
EERECOMPILE_CODE0(DADD, XMMINFO_WRITED|XMMINFO_READS|XMMINFO_READT);
|
|
|
|
//// DADDU
|
|
void recDADDU( void )
|
|
{
|
|
recDADD( );
|
|
}
|
|
|
|
//// SUB
|
|
|
|
void recSUB_const()
|
|
{
|
|
g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].SL[0] - g_cpuConstRegs[_Rt_].SL[0];
|
|
}
|
|
|
|
void recSUB_consts(int info)
|
|
{
|
|
assert( !(info&PROCESS_EE_XMM) );
|
|
EEINST_SETSIGNEXT(_Rt_);
|
|
EEINST_SETSIGNEXT(_Rd_);
|
|
|
|
if( info & PROCESS_EE_MMX ) {
|
|
if( g_cpuConstRegs[ _Rs_ ].UL[0] ) {
|
|
|
|
if( EEREC_D != EEREC_T ) {
|
|
MOVQMtoR(EEREC_D, (u32)_eeGetConstReg(_Rs_));
|
|
PSUBDRtoR(EEREC_D, EEREC_T);
|
|
|
|
if( EEINST_ISLIVE1(_Rd_) ) _signExtendGPRtoMMX(EEREC_D, _Rd_, 0);
|
|
else EEINST_RESETHASLIVE1(_Rd_);
|
|
}
|
|
else {
|
|
int t0reg = _allocMMXreg(-1, MMX_TEMP, 0);
|
|
MOVDMtoMMX(t0reg, (u32)_eeGetConstReg(_Rs_));
|
|
PSUBDRtoR(t0reg, EEREC_T);
|
|
|
|
// swap mmx regs
|
|
mmxregs[t0reg] = mmxregs[EEREC_D];
|
|
mmxregs[EEREC_D].inuse = 0;
|
|
|
|
if( EEINST_ISLIVE1(_Rd_) ) _signExtendGPRtoMMX(t0reg, _Rd_, 0);
|
|
else EEINST_RESETHASLIVE1(_Rd_);
|
|
}
|
|
}
|
|
else {
|
|
// just move and sign extend
|
|
if( EEREC_D != EEREC_T ) {
|
|
PXORRtoR(EEREC_D, EEREC_D);
|
|
PSUBDRtoR(EEREC_D, EEREC_T);
|
|
|
|
if( EEINST_ISLIVE1(_Rd_) ) _signExtendGPRtoMMX(EEREC_D, _Rd_, 0);
|
|
else EEINST_RESETHASLIVE1(_Rd_);
|
|
}
|
|
else {
|
|
int t0reg = _allocMMXreg(-1, MMX_TEMP, 0);
|
|
PXORRtoR(t0reg, t0reg);
|
|
PSUBDRtoR(t0reg, EEREC_T);
|
|
|
|
// swap mmx regs.. don't ask
|
|
mmxregs[t0reg] = mmxregs[EEREC_D];
|
|
mmxregs[EEREC_D].inuse = 0;
|
|
|
|
if( EEINST_ISLIVE1(_Rd_) ) _signExtendGPRtoMMX(t0reg, _Rd_, 0);
|
|
else EEINST_RESETHASLIVE1(_Rd_);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
if( _Rd_ == _Rt_ ) {
|
|
if( g_cpuConstRegs[ _Rs_ ].UL[ 0 ] ) SUB32ItoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], g_cpuConstRegs[ _Rs_ ].UL[ 0 ]);
|
|
NEG32M((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ]);
|
|
|
|
if( EEINST_ISLIVE1(_Rd_) ) _signExtendSFtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ]);
|
|
else EEINST_RESETHASLIVE1(_Rd_);
|
|
}
|
|
else {
|
|
if( g_cpuConstRegs[ _Rs_ ].UL[ 0 ] ) {
|
|
MOV32ItoR( EAX, g_cpuConstRegs[ _Rs_ ].UL[ 0 ] );
|
|
SUB32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] );
|
|
}
|
|
else {
|
|
MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] );
|
|
NEG32R(EAX);
|
|
}
|
|
|
|
if( EEINST_ISLIVE1(_Rd_) ) {
|
|
CDQ( );
|
|
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX );
|
|
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX );
|
|
}
|
|
else {
|
|
EEINST_RESETHASLIVE1(_Rd_);
|
|
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void recSUB_constt(int info)
|
|
{
|
|
assert( !(info&PROCESS_EE_XMM) );
|
|
EEINST_SETSIGNEXT(_Rs_);
|
|
EEINST_SETSIGNEXT(_Rd_);
|
|
|
|
if( info & PROCESS_EE_MMX ) {
|
|
if( g_cpuConstRegs[ _Rt_ ].UL[0] ) {
|
|
|
|
u32* ptempmem = _eeGetConstReg(_Rt_);
|
|
if( EEREC_D != EEREC_S ) MOVQRtoR(EEREC_D, EEREC_S);
|
|
PSUBDMtoR(EEREC_D, (u32)ptempmem);
|
|
|
|
_signExtendGPRtoMMX(EEREC_D, _Rd_, 0);
|
|
}
|
|
else {
|
|
// just move and sign extend
|
|
if( EEINST_HASLIVE1(_Rs_) ) {
|
|
if( EEREC_D != EEREC_S ) MOVQRtoR(EEREC_D, EEREC_S);
|
|
}
|
|
else {
|
|
_signExtendGPRMMXtoMMX(EEREC_D, _Rd_, EEREC_S, _Rs_);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
|
|
if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) && (!EEINST_ISLIVE1(_Rd_) || !g_cpuConstRegs[_Rt_].UL[0]) ) {
|
|
int mmreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE);
|
|
SetMMXstate();
|
|
|
|
if( EEINST_HASLIVE1(_Rs_) && EEINST_ISLIVE1(_Rd_) ) {
|
|
MOVQMtoR(mmreg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]);
|
|
}
|
|
else {
|
|
if( g_cpuConstRegs[_Rt_].UL[0] ) {
|
|
MOVDMtoMMX(mmreg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]);
|
|
PSUBDMtoR(mmreg, (u32)_eeGetConstReg(_Rt_));
|
|
}
|
|
else {
|
|
if( EEINST_ISLIVE1(_Rd_) ) {
|
|
_signExtendMtoMMX(mmreg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]);
|
|
}
|
|
else {
|
|
MOVDMtoMMX(mmreg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]);
|
|
EEINST_RESETHASLIVE1(_Rd_);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
if( _Rd_ == _Rs_ ) {
|
|
if( g_cpuConstRegs[ _Rt_ ].UL[ 0 ] ) {
|
|
SUB32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], g_cpuConstRegs[ _Rt_ ].UL[ 0 ]);
|
|
|
|
if( EEINST_ISLIVE1(_Rd_) ) _signExtendSFtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ]);
|
|
else EEINST_RESETHASLIVE1(_Rd_);
|
|
}
|
|
}
|
|
else {
|
|
MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] );
|
|
if( g_cpuConstRegs[ _Rt_ ].UL[ 0 ] )
|
|
SUB32ItoR( EAX, g_cpuConstRegs[ _Rt_ ].UL[ 0 ] );
|
|
|
|
if( EEINST_ISLIVE1(_Rd_) ) {
|
|
CDQ( );
|
|
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX );
|
|
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX );
|
|
}
|
|
else {
|
|
EEINST_RESETHASLIVE1(_Rd_);
|
|
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void recSUB_(int info)
|
|
{
|
|
assert( !(info&PROCESS_EE_XMM) );
|
|
EEINST_SETSIGNEXT(_Rs_);
|
|
EEINST_SETSIGNEXT(_Rt_);
|
|
EEINST_SETSIGNEXT(_Rd_);
|
|
|
|
if( info & PROCESS_EE_MMX ) {
|
|
|
|
if( EEREC_D == EEREC_S ) PSUBDRtoR(EEREC_D, EEREC_T);
|
|
else if( EEREC_D == EEREC_T ) {
|
|
int t0reg = _allocMMXreg(-1, MMX_TEMP, 0);
|
|
MOVQRtoR(t0reg, EEREC_S);
|
|
PSUBDRtoR(t0reg, EEREC_T);
|
|
|
|
// swap mmx regs.. don't ask
|
|
mmxregs[t0reg] = mmxregs[EEREC_D];
|
|
mmxregs[EEREC_D].inuse = 0;
|
|
info = (info&~PROCESS_EE_SET_D(0xf))|PROCESS_EE_SET_D(t0reg);
|
|
}
|
|
else {
|
|
MOVQRtoR(EEREC_D, EEREC_S);
|
|
PSUBDRtoR(EEREC_D, EEREC_T);
|
|
}
|
|
|
|
if( EEINST_ISLIVE1(_Rd_) ) {
|
|
// sign extend
|
|
_signExtendGPRtoMMX(EEREC_D, _Rd_, 0);
|
|
}
|
|
else {
|
|
EEINST_RESETHASLIVE1(_Rd_);
|
|
}
|
|
}
|
|
else {
|
|
|
|
if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) && !EEINST_ISLIVE1(_Rd_)) {
|
|
int mmreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE);
|
|
SetMMXstate();
|
|
|
|
EEINST_RESETHASLIVE1(_Rd_);
|
|
MOVDMtoMMX(mmreg, (int)&cpuRegs.GPR.r[_Rs_].UL[0] );
|
|
PSUBDMtoR(mmreg, (int)&cpuRegs.GPR.r[_Rt_].UL[0] );
|
|
}
|
|
else {
|
|
if( !EEINST_ISLIVE1(_Rd_) ) {
|
|
if( _Rd_ == _Rs_) {
|
|
EEINST_RESETHASLIVE1(_Rd_);
|
|
MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] );
|
|
SUB32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX );
|
|
return;
|
|
}
|
|
}
|
|
|
|
MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] );
|
|
SUB32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] );
|
|
|
|
if( EEINST_ISLIVE1(_Rd_) ) {
|
|
CDQ( );
|
|
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX );
|
|
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX );
|
|
}
|
|
else {
|
|
EEINST_RESETHASLIVE1(_Rd_);
|
|
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
EERECOMPILE_CODE0(SUB, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED);
|
|
|
|
//// SUBU
|
|
void recSUBU( void )
|
|
{
|
|
recSUB( );
|
|
}
|
|
|
|
//// DSUB
|
|
void recDSUB_const()
|
|
{
|
|
g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].SD[0] - g_cpuConstRegs[_Rt_].SD[0];
|
|
}
|
|
|
|
void recDSUB_consts(int info)
|
|
{
|
|
assert( !(info&PROCESS_EE_XMM) );
|
|
|
|
if( info & PROCESS_EE_MMX ) {
|
|
assert( cpucaps.hasStreamingSIMD2Extensions );
|
|
|
|
if( g_cpuConstRegs[ _Rs_ ].UD[0] ) {
|
|
|
|
// flush
|
|
if( EEREC_D != EEREC_T ) {
|
|
MOVQMtoR(EEREC_D, (u32)_eeGetConstReg(_Rs_));
|
|
PSUBQRtoR(EEREC_D, EEREC_T);
|
|
}
|
|
else {
|
|
int t0reg = _allocMMXreg(-1, MMX_TEMP, 0);
|
|
MOVQMtoR(t0reg, (u32)_eeGetConstReg(_Rs_));
|
|
PSUBQRtoR(t0reg, EEREC_T);
|
|
|
|
// swap mmx regs.. don't ask
|
|
mmxregs[t0reg] = mmxregs[EEREC_D];
|
|
mmxregs[EEREC_D].inuse = 0;
|
|
}
|
|
}
|
|
else {
|
|
// just move and sign extend
|
|
if( EEREC_D != EEREC_T ) {
|
|
PXORRtoR(EEREC_D, EEREC_D);
|
|
PSUBQRtoR(EEREC_D, EEREC_T);
|
|
}
|
|
else {
|
|
int t0reg = _allocMMXreg(-1, MMX_TEMP, 0);
|
|
PXORRtoR(t0reg, t0reg);
|
|
PSUBQRtoR(t0reg, EEREC_T);
|
|
|
|
// swap mmx regs.. don't ask
|
|
mmxregs[t0reg] = mmxregs[EEREC_D];
|
|
mmxregs[EEREC_D].inuse = 0;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) && cpucaps.hasStreamingSIMD2Extensions ) {
|
|
int mmreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE);
|
|
SetMMXstate();
|
|
MOVQMtoR(mmreg, (u32)_eeGetConstReg(_Rs_));
|
|
PSUBQMtoR(mmreg, (u32)&cpuRegs.GPR.r[_Rt_].UL[ 0 ]);
|
|
}
|
|
else {
|
|
if( g_cpuConstRegs[ _Rs_ ].UL[ 0 ] || g_cpuConstRegs[ _Rs_ ].UL[ 1 ] ) {
|
|
MOV32ItoR( EAX, g_cpuConstRegs[ _Rs_ ].UL[ 0 ] );
|
|
if( EEINST_ISLIVE1(_Rd_) )
|
|
MOV32ItoR( EDX, g_cpuConstRegs[ _Rs_ ].UL[ 1 ] );
|
|
SUB32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] );
|
|
if( EEINST_ISLIVE1(_Rd_) )
|
|
SBB32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] );
|
|
|
|
if( !EEINST_ISLIVE1(_Rd_) )
|
|
EEINST_RESETHASLIVE1(_Rd_);
|
|
}
|
|
else {
|
|
|
|
if( _Rd_ == _Rt_ ) {
|
|
// negate _Rt_ all in memory
|
|
if( EEINST_ISLIVE1(_Rd_) ) {
|
|
MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] );
|
|
NEG32M((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]);
|
|
ADC32ItoR(EDX, 0);
|
|
NEG32R(EDX);
|
|
MOV32RtoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX);
|
|
}
|
|
else {
|
|
EEINST_RESETHASLIVE1(_Rd_);
|
|
NEG32M((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ]);
|
|
}
|
|
return;
|
|
}
|
|
|
|
MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] );
|
|
if( EEINST_ISLIVE1(_Rd_) )
|
|
MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] );
|
|
// take negative of 64bit number
|
|
NEG32R(EAX);
|
|
|
|
if( EEINST_ISLIVE1(_Rd_) ) {
|
|
ADC32ItoR(EDX, 0);
|
|
NEG32R(EDX);
|
|
}
|
|
else {
|
|
EEINST_RESETHASLIVE1(_Rd_);
|
|
}
|
|
}
|
|
|
|
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX );
|
|
if( EEINST_ISLIVE1(_Rd_) )
|
|
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX );
|
|
else {
|
|
EEINST_RESETHASLIVE1(_Rd_);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void recDSUB_constt(int info)
|
|
{
|
|
assert( !(info&PROCESS_EE_XMM) );
|
|
|
|
if( info & PROCESS_EE_MMX ) {
|
|
assert( cpucaps.hasStreamingSIMD2Extensions );
|
|
|
|
if( g_cpuConstRegs[ _Rt_ ].UD[0] ) {
|
|
|
|
if( EEREC_D != EEREC_S ) MOVQRtoR(EEREC_D, EEREC_S);
|
|
PSUBQMtoR(EEREC_D, (u32)_eeGetConstReg(_Rt_));
|
|
}
|
|
else {
|
|
if( EEREC_D != EEREC_S ) MOVQRtoR(EEREC_D, EEREC_S);
|
|
}
|
|
}
|
|
else {
|
|
if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) && cpucaps.hasStreamingSIMD2Extensions ) {
|
|
int mmreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE);
|
|
SetMMXstate();
|
|
MOVQMtoR(mmreg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]);
|
|
if( g_cpuConstRegs[_Rt_].UD[0] ) PSUBQMtoR(mmreg, (u32)_eeGetConstReg(_Rt_));
|
|
}
|
|
else {
|
|
|
|
if( _Rd_ == _Rs_ ) {
|
|
if( EEINST_ISLIVE1(_Rd_) && (g_cpuConstRegs[ _Rt_ ].UL[ 0 ] || g_cpuConstRegs[ _Rt_ ].UL[ 1 ]) ) {
|
|
SUB32ItoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[0], g_cpuConstRegs[ _Rt_ ].UL[ 0 ] );
|
|
SBB32ItoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[1], g_cpuConstRegs[ _Rt_ ].UL[ 1 ] );
|
|
}
|
|
else if( g_cpuConstRegs[ _Rt_ ].UL[ 0 ] ) {
|
|
EEINST_RESETHASLIVE1(_Rd_);
|
|
SUB32ItoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[0], g_cpuConstRegs[ _Rt_ ].UL[ 0 ] );
|
|
}
|
|
}
|
|
else {
|
|
MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] );
|
|
if( EEINST_ISLIVE1(_Rd_) )
|
|
MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] );
|
|
|
|
if( g_cpuConstRegs[ _Rt_ ].UL[ 0 ] || g_cpuConstRegs[ _Rt_ ].UL[ 1 ] ) {
|
|
SUB32ItoR( EAX, g_cpuConstRegs[ _Rt_ ].UL[ 0 ] );
|
|
if( EEINST_ISLIVE1(_Rd_) )
|
|
SBB32ItoR( EDX, g_cpuConstRegs[ _Rt_ ].UL[ 1 ] );
|
|
}
|
|
|
|
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX );
|
|
if( EEINST_ISLIVE1(_Rd_) )
|
|
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX );
|
|
else
|
|
EEINST_RESETHASLIVE1(_Rd_);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void recDSUB_(int info)
|
|
{
|
|
assert( !(info&PROCESS_EE_XMM) );
|
|
|
|
if( info & PROCESS_EE_MMX ) {
|
|
assert( cpucaps.hasStreamingSIMD2Extensions );
|
|
|
|
if( EEREC_D == EEREC_S ) PSUBQRtoR(EEREC_D, EEREC_T);
|
|
else if( EEREC_D == EEREC_T ) {
|
|
int t0reg = _allocMMXreg(-1, MMX_TEMP, 0);
|
|
MOVQRtoR(t0reg, EEREC_S);
|
|
PSUBQRtoR(t0reg, EEREC_T);
|
|
|
|
// swap mmx regs.. don't ask
|
|
mmxregs[t0reg] = mmxregs[EEREC_D];
|
|
mmxregs[EEREC_D].inuse = 0;
|
|
}
|
|
else {
|
|
MOVQRtoR(EEREC_D, EEREC_S);
|
|
PSUBQRtoR(EEREC_D, EEREC_T);
|
|
}
|
|
}
|
|
else {
|
|
if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) && cpucaps.hasStreamingSIMD2Extensions ) {
|
|
int mmreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE);
|
|
SetMMXstate();
|
|
MOVQMtoR(mmreg, (int)&cpuRegs.GPR.r[_Rs_].UL[ 0 ]);
|
|
PSUBQMtoR(mmreg, (int)&cpuRegs.GPR.r[_Rt_].UL[ 0 ]);
|
|
}
|
|
else {
|
|
if( _Rd_ == _Rs_ ) {
|
|
MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] );
|
|
if( EEINST_ISLIVE1(_Rd_) )
|
|
MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] );
|
|
SUB32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX );
|
|
if( EEINST_ISLIVE1(_Rd_) )
|
|
SBB32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX );
|
|
else
|
|
EEINST_RESETHASLIVE1(_Rd_);
|
|
}
|
|
else {
|
|
MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] );
|
|
if( EEINST_ISLIVE1(_Rd_) )
|
|
MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] );
|
|
SUB32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] );
|
|
if( EEINST_ISLIVE1(_Rd_) )
|
|
SBB32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] );
|
|
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX );
|
|
if( EEINST_ISLIVE1(_Rd_) )
|
|
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX );
|
|
else
|
|
EEINST_RESETHASLIVE1(_Rd_);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
EERECOMPILE_CODE0(DSUB, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED);
|
|
|
|
//// DSUBU
|
|
void recDSUBU( void )
|
|
{
|
|
recDSUB( );
|
|
}
|
|
|
|
//// AND
|
|
void recAND_const()
|
|
{
|
|
g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].UD[0] & g_cpuConstRegs[_Rt_].UD[0];
|
|
}
|
|
|
|
void recAND_constv(int info, int creg, int vreg)
|
|
{
|
|
assert( !(info & PROCESS_EE_XMM) );
|
|
|
|
if( info & PROCESS_EE_MMX ) {
|
|
int mmreg = vreg == _Rt_ ? EEREC_T : EEREC_S;
|
|
|
|
if( g_cpuConstRegs[ creg ].UL[0] || g_cpuConstRegs[ creg ].UL[1] ) {
|
|
_flushConstReg(creg);
|
|
if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg);
|
|
PANDMtoR(EEREC_D, (u32)&cpuRegs.GPR.r[creg].UL[0] );
|
|
}
|
|
else {
|
|
PXORRtoR(EEREC_D, EEREC_D);
|
|
}
|
|
}
|
|
else {
|
|
|
|
if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) || (_Rd_ != vreg && _hasFreeMMXreg()) ) {
|
|
int rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE);
|
|
SetMMXstate();
|
|
|
|
MOVQMtoR(rdreg, (u32)&cpuRegs.GPR.r[vreg].UL[0] );
|
|
PANDMtoR(rdreg, (u32)_eeGetConstReg(creg) );
|
|
}
|
|
else {
|
|
if( g_cpuConstRegs[ creg ].UL[0] || g_cpuConstRegs[ creg ].UL[1] ) {
|
|
|
|
if( _Rd_ == vreg ) {
|
|
AND32ItoM((int)&cpuRegs.GPR.r[ vreg ].UL[0], g_cpuConstRegs[creg].UL[0]);
|
|
if( EEINST_ISLIVE1(_Rd_) ) {
|
|
if( g_cpuConstRegs[creg].UL[1] != 0xffffffff ) AND32ItoM((int)&cpuRegs.GPR.r[ vreg ].UL[1], g_cpuConstRegs[creg].UL[1]);
|
|
}
|
|
else
|
|
EEINST_RESETHASLIVE1(_Rd_);
|
|
}
|
|
else {
|
|
MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ vreg ]);
|
|
if( EEINST_ISLIVE1(_Rd_) )
|
|
MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ vreg ] + 4 );
|
|
AND32ItoR(EAX, g_cpuConstRegs[ creg ].UL[0]);
|
|
if( EEINST_ISLIVE1(_Rd_) )
|
|
AND32ItoR(ECX, g_cpuConstRegs[ creg ].UL[1]);
|
|
MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ], EAX);
|
|
if( EEINST_ISLIVE1(_Rd_) )
|
|
MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ]+4, ECX);
|
|
else
|
|
EEINST_RESETHASLIVE1(_Rd_);
|
|
}
|
|
}
|
|
else {
|
|
MOV32ItoM((int)&cpuRegs.GPR.r[ _Rd_ ], 0);
|
|
if( EEINST_ISLIVE1(_Rd_) )
|
|
MOV32ItoM((int)&cpuRegs.GPR.r[ _Rd_ ]+4, 0);
|
|
else
|
|
EEINST_RESETHASLIVE1(_Rd_);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void recAND_consts(int info)
|
|
{
|
|
recAND_constv(info, _Rs_, _Rt_);
|
|
}
|
|
|
|
void recAND_constt(int info)
|
|
{
|
|
recAND_constv(info, _Rt_, _Rs_);
|
|
}
|
|
|
|
void recLogicalOp(int info, int op)
|
|
{
|
|
assert( !(info & PROCESS_EE_XMM) );
|
|
|
|
if( info & PROCESS_EE_MMX ) {
|
|
if( EEREC_D == EEREC_S ) LogicalOpRtoR(EEREC_D, EEREC_T, op);
|
|
else if( EEREC_D == EEREC_T ) LogicalOpRtoR(EEREC_D, EEREC_S, op);
|
|
else {
|
|
MOVQRtoR(EEREC_D, EEREC_S);
|
|
LogicalOpRtoR(EEREC_D, EEREC_T, op);
|
|
}
|
|
}
|
|
else if( (g_pCurInstInfo->regs[_Rs_]&EEINST_MMX) || (g_pCurInstInfo->regs[_Rt_]&EEINST_MMX) || (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) ) {
|
|
int rsreg, rtreg, rdreg;
|
|
_addNeededMMXreg(MMX_GPR+_Rs_);
|
|
_addNeededMMXreg(MMX_GPR+_Rt_);
|
|
_addNeededMMXreg(MMX_GPR+_Rd_);
|
|
|
|
rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE);
|
|
rsreg = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rs_, MODE_READ);
|
|
rtreg = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_READ);
|
|
SetMMXstate();
|
|
|
|
if( rdreg == rsreg ) {
|
|
if( rtreg >= 0 ) LogicalOpRtoR(rdreg, rtreg, op);
|
|
else LogicalOpMtoR(rdreg, (int)&cpuRegs.GPR.r[ _Rt_ ], op);
|
|
}
|
|
else {
|
|
if( rdreg != rtreg ) {
|
|
if( rtreg >= 0 ) MOVQRtoR(rdreg, rtreg);
|
|
else MOVQMtoR(rdreg, (int)&cpuRegs.GPR.r[ _Rt_ ]);
|
|
}
|
|
|
|
if( rsreg >= 0 ) LogicalOpRtoR(rdreg, rsreg, op);
|
|
else LogicalOpMtoR(rdreg, (int)&cpuRegs.GPR.r[ _Rs_ ], op);
|
|
}
|
|
}
|
|
else {
|
|
if( _Rd_ == _Rs_ || _Rd_ == _Rt_ ) {
|
|
int vreg = _Rd_ == _Rs_ ? _Rt_ : _Rs_;
|
|
MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ vreg ]);
|
|
if( EEINST_ISLIVE1(_Rd_) )
|
|
MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ vreg ] + 4 );
|
|
LogicalOp32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ], EAX, op );
|
|
if( EEINST_ISLIVE1(_Rd_) )
|
|
LogicalOp32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ] + 4, EDX, op );
|
|
if( op == 3 ) {
|
|
NOT32M((int)&cpuRegs.GPR.r[ _Rd_ ]);
|
|
if( EEINST_ISLIVE1(_Rd_) )
|
|
NOT32M((int)&cpuRegs.GPR.r[ _Rd_ ]+4);
|
|
}
|
|
|
|
if( !EEINST_ISLIVE1(_Rd_) ) EEINST_RESETHASLIVE1(_Rd_);
|
|
}
|
|
else {
|
|
MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ _Rs_ ]);
|
|
if( EEINST_ISLIVE1(_Rd_) )
|
|
MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ _Rs_ ] + 4 );
|
|
LogicalOp32MtoR(EAX, (int)&cpuRegs.GPR.r[ _Rt_ ], op );
|
|
if( EEINST_ISLIVE1(_Rd_) )
|
|
LogicalOp32MtoR(ECX, (int)&cpuRegs.GPR.r[ _Rt_ ] + 4, op );
|
|
|
|
if( op == 3 ) {
|
|
NOT32R(EAX);
|
|
if( EEINST_ISLIVE1(_Rd_) )
|
|
NOT32R(ECX);
|
|
}
|
|
|
|
MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ], EAX);
|
|
if( EEINST_ISLIVE1(_Rd_) )
|
|
MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ]+4, ECX);
|
|
else
|
|
EEINST_RESETHASLIVE1(_Rd_);
|
|
}
|
|
}
|
|
}
|
|
|
|
void recAND_(int info)
|
|
{
|
|
recLogicalOp(info, 0);
|
|
}
|
|
|
|
EERECOMPILE_CODE0(AND, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED);
|
|
|
|
//// OR
|
|
void recOR_const()
|
|
{
|
|
g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].UD[0] | g_cpuConstRegs[_Rt_].UD[0];
|
|
}
|
|
|
|
void recOR_constv(int info, int creg, int vreg)
|
|
{
|
|
assert( !(info & PROCESS_EE_XMM) );
|
|
|
|
if( info & PROCESS_EE_MMX ) {
|
|
int mmreg = vreg == _Rt_ ? EEREC_T : EEREC_S;
|
|
|
|
if( g_cpuConstRegs[ creg ].UL[0] || g_cpuConstRegs[ creg ].UL[1] ) {
|
|
_flushConstReg(creg);
|
|
if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg);
|
|
PORMtoR(EEREC_D, (u32)&cpuRegs.GPR.r[creg].UL[0] );
|
|
}
|
|
else {
|
|
if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg);
|
|
}
|
|
}
|
|
else {
|
|
|
|
if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) || (_Rd_ != vreg && _hasFreeMMXreg()) ) {
|
|
int rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE);
|
|
SetMMXstate();
|
|
|
|
MOVQMtoR(rdreg, (u32)&cpuRegs.GPR.r[vreg].UL[0] );
|
|
|
|
if( g_cpuConstRegs[ creg ].UL[0] || g_cpuConstRegs[ creg ].UL[1] ) {
|
|
PORMtoR(rdreg, (u32)_eeGetConstReg(creg) );
|
|
}
|
|
}
|
|
else {
|
|
if( _Rd_ == vreg ) {
|
|
OR32ItoM((int)&cpuRegs.GPR.r[ vreg ].UL[0], g_cpuConstRegs[creg].UL[0]);
|
|
if( EEINST_ISLIVE1(_Rd_) ) {
|
|
if( g_cpuConstRegs[creg].UL[1] ) OR32ItoM((int)&cpuRegs.GPR.r[ vreg ].UL[1], g_cpuConstRegs[creg].UL[1]);
|
|
}
|
|
else
|
|
EEINST_RESETHASLIVE1(_Rd_);
|
|
}
|
|
else {
|
|
MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ vreg ]);
|
|
if( EEINST_ISLIVE1(_Rd_) )
|
|
MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ vreg ] + 4 );
|
|
|
|
if( g_cpuConstRegs[ creg ].UL[0] ) OR32ItoR(EAX, g_cpuConstRegs[ creg ].UL[0]);
|
|
if( g_cpuConstRegs[ creg ].UL[1] && EEINST_ISLIVE1(_Rd_) ) OR32ItoR(ECX, g_cpuConstRegs[ creg ].UL[1]);
|
|
|
|
MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ], EAX);
|
|
if( EEINST_ISLIVE1(_Rd_) )
|
|
MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ]+4, ECX);
|
|
else
|
|
EEINST_RESETHASLIVE1(_Rd_);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void recOR_consts(int info)
|
|
{
|
|
recOR_constv(info, _Rs_, _Rt_);
|
|
}
|
|
|
|
void recOR_constt(int info)
|
|
{
|
|
recOR_constv(info, _Rt_, _Rs_);
|
|
}
|
|
|
|
void recOR_(int info)
|
|
{
|
|
recLogicalOp(info, 1);
|
|
}
|
|
|
|
EERECOMPILE_CODE0(OR, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED);
|
|
|
|
//// XOR
|
|
void recXOR_const()
|
|
{
|
|
g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].UD[0] ^ g_cpuConstRegs[_Rt_].UD[0];
|
|
}
|
|
|
|
void recXOR_constv(int info, int creg, int vreg)
|
|
{
|
|
assert( !(info & PROCESS_EE_XMM) );
|
|
|
|
if( info & PROCESS_EE_MMX ) {
|
|
int mmreg = vreg == _Rt_ ? EEREC_T : EEREC_S;
|
|
|
|
if( g_cpuConstRegs[ creg ].UL[0] || g_cpuConstRegs[ creg ].UL[1] ) {
|
|
_flushConstReg(creg);
|
|
if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg);
|
|
PXORMtoR(EEREC_D, (u32)&cpuRegs.GPR.r[creg].UL[0] );
|
|
}
|
|
else {
|
|
if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg);
|
|
}
|
|
}
|
|
else {
|
|
|
|
if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) || (_Rd_ != vreg && _hasFreeMMXreg()) ) {
|
|
int rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE);
|
|
SetMMXstate();
|
|
MOVQMtoR(rdreg, (u32)&cpuRegs.GPR.r[vreg].UL[0] );
|
|
|
|
if( g_cpuConstRegs[ creg ].UL[0] || g_cpuConstRegs[ creg ].UL[1] ) {
|
|
PXORMtoR(rdreg, (u32)_eeGetConstReg(creg) );
|
|
}
|
|
}
|
|
else {
|
|
if( _Rd_ == vreg ) {
|
|
XOR32ItoM((int)&cpuRegs.GPR.r[ vreg ].UL[0], g_cpuConstRegs[creg].UL[0]);
|
|
if( EEINST_ISLIVE1(_Rd_) ) {
|
|
if( g_cpuConstRegs[creg].UL[1] ) XOR32ItoM((int)&cpuRegs.GPR.r[ vreg ].UL[1], g_cpuConstRegs[creg].UL[1]);
|
|
}
|
|
else
|
|
EEINST_RESETHASLIVE1(_Rd_);
|
|
}
|
|
else {
|
|
MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ vreg ]);
|
|
if( EEINST_ISLIVE1(_Rd_) )
|
|
MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ vreg ] + 4 );
|
|
|
|
if( g_cpuConstRegs[ creg ].UL[0] ) XOR32ItoR(EAX, g_cpuConstRegs[ creg ].UL[0]);
|
|
if( g_cpuConstRegs[ creg ].UL[1] && EEINST_ISLIVE1(_Rd_) ) XOR32ItoR(ECX, g_cpuConstRegs[ creg ].UL[1]);
|
|
|
|
MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ], EAX);
|
|
if( EEINST_ISLIVE1(_Rd_) )
|
|
MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ]+4, ECX);
|
|
else
|
|
EEINST_RESETHASLIVE1(_Rd_);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void recXOR_consts(int info)
|
|
{
|
|
recXOR_constv(info, _Rs_, _Rt_);
|
|
}
|
|
|
|
void recXOR_constt(int info)
|
|
{
|
|
recXOR_constv(info, _Rt_, _Rs_);
|
|
}
|
|
|
|
void recXOR_(int info)
|
|
{
|
|
recLogicalOp(info, 2);
|
|
}
|
|
|
|
EERECOMPILE_CODE0(XOR, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED);
|
|
|
|
//// NOR
|
|
void recNOR_const()
|
|
{
|
|
g_cpuConstRegs[_Rd_].UD[0] =~(g_cpuConstRegs[_Rs_].UD[0] | g_cpuConstRegs[_Rt_].UD[0]);
|
|
}
|
|
|
|
void recNOR_constv(int info, int creg, int vreg)
|
|
{
|
|
assert( !(info & PROCESS_EE_XMM) );
|
|
|
|
if( info & PROCESS_EE_MMX ) {
|
|
int mmreg = vreg == _Rt_ ? EEREC_T : EEREC_S;
|
|
int t0reg = _allocMMXreg(-1, MMX_TEMP, 0);
|
|
|
|
if( g_cpuConstRegs[ creg ].UL[0] || g_cpuConstRegs[ creg ].UL[1] ) {
|
|
if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg);
|
|
PORMtoR(EEREC_D, (u32)_eeGetConstReg(creg));
|
|
}
|
|
else {
|
|
if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg);
|
|
}
|
|
|
|
// take the NOT
|
|
PCMPEQDRtoR( t0reg,t0reg);
|
|
PXORRtoR( EEREC_D,t0reg);
|
|
_freeMMXreg(t0reg);
|
|
}
|
|
else {
|
|
|
|
if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) || (_Rd_ != vreg && _hasFreeMMXreg()) ) {
|
|
int rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE);
|
|
int t0reg = _allocMMXreg(-1, MMX_TEMP, 0);
|
|
|
|
SetMMXstate();
|
|
|
|
MOVQMtoR(rdreg, (u32)&cpuRegs.GPR.r[vreg].UL[0] );
|
|
PCMPEQDRtoR( t0reg,t0reg);
|
|
if( g_cpuConstRegs[ creg ].UD[0] ) PORMtoR(rdreg, (u32)_eeGetConstReg(creg) );
|
|
|
|
// take the NOT
|
|
PXORRtoR( rdreg,t0reg);
|
|
|
|
_freeMMXreg(t0reg);
|
|
}
|
|
else {
|
|
if( _Rd_ == vreg ) {
|
|
NOT32M((int)&cpuRegs.GPR.r[ vreg ].UL[0]);
|
|
if( EEINST_ISLIVE1(_Rd_) ) NOT32M((int)&cpuRegs.GPR.r[ vreg ].UL[1]);
|
|
|
|
if( g_cpuConstRegs[creg].UL[0] ) AND32ItoM((int)&cpuRegs.GPR.r[ vreg ].UL[0], ~g_cpuConstRegs[creg].UL[0]);
|
|
if( EEINST_ISLIVE1(_Rd_) ) {
|
|
if( g_cpuConstRegs[creg].UL[1] ) AND32ItoM((int)&cpuRegs.GPR.r[ vreg ].UL[1], ~g_cpuConstRegs[creg].UL[1]);
|
|
}
|
|
else
|
|
EEINST_RESETHASLIVE1(_Rd_);
|
|
}
|
|
else {
|
|
MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ vreg ]);
|
|
if( EEINST_ISLIVE1(_Rd_) )
|
|
MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ vreg ] + 4 );
|
|
if( g_cpuConstRegs[ creg ].UL[0] ) OR32ItoR(EAX, g_cpuConstRegs[ creg ].UL[0]);
|
|
if( g_cpuConstRegs[ creg ].UL[1] && EEINST_ISLIVE1(_Rd_) ) OR32ItoR(ECX, g_cpuConstRegs[ creg ].UL[1]);
|
|
NOT32R(EAX);
|
|
if( EEINST_ISLIVE1(_Rd_) )
|
|
NOT32R(ECX);
|
|
MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ], EAX);
|
|
if( EEINST_ISLIVE1(_Rd_) )
|
|
MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ]+4, ECX);
|
|
else
|
|
EEINST_RESETHASLIVE1(_Rd_);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void recNOR_consts(int info)
|
|
{
|
|
recNOR_constv(info, _Rs_, _Rt_);
|
|
}
|
|
|
|
void recNOR_constt(int info)
|
|
{
|
|
recNOR_constv(info, _Rt_, _Rs_);
|
|
}
|
|
|
|
void recNOR_(int info)
|
|
{
|
|
recLogicalOp(info, 3);
|
|
}
|
|
|
|
EERECOMPILE_CODE0(NOR, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED);
|
|
|
|
//// SLT - test with silent hill, lemans
|
|
void recSLT_const()
|
|
{
|
|
g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].SD[0] < g_cpuConstRegs[_Rt_].SD[0];
|
|
}
|
|
|
|
static u32 s_sltconst = 0x80000000;
|
|
static u32 s_sltconst64[2] = {0, 0x80000000};
|
|
u32 s_sltone = 1;
|
|
|
|
void recSLTs_consts(int info, int sign)
|
|
{
|
|
assert( !(info & PROCESS_EE_XMM) );
|
|
|
|
if( info & PROCESS_EE_MMX ) {
|
|
|
|
if( _Rs_ == _Rt_ ) {
|
|
PXORRtoR(EEREC_D, EEREC_D);
|
|
return;
|
|
}
|
|
|
|
if( g_cpuConstRegs[_Rs_].UL[1] == (g_cpuConstRegs[_Rs_].SL[0]<0?0xffffffff:0) && EEINST_ISSIGNEXT(_Rt_) ) {
|
|
// just compare the lower values
|
|
if( sign ) {
|
|
if( EEREC_D != EEREC_T ) MOVQRtoR(EEREC_D, EEREC_T);
|
|
PCMPGTDMtoR(EEREC_D, (u32)_eeGetConstReg(_Rs_));
|
|
|
|
PUNPCKLDQRtoR(EEREC_D, EEREC_D);
|
|
PSRLQItoR(EEREC_D, 63);
|
|
}
|
|
else {
|
|
u32* ptempmem = recAllocStackMem(8,4);
|
|
ptempmem[0] = g_cpuConstRegs[_Rs_].UL[0]^0x80000000;
|
|
ptempmem[1] = 0;
|
|
|
|
if( EEREC_D != EEREC_T ) {
|
|
MOVDMtoMMX(EEREC_D, (u32)&s_sltconst);
|
|
PXORRtoR(EEREC_D, EEREC_T);
|
|
}
|
|
else {
|
|
PXORMtoR(EEREC_D, (u32)&s_sltconst);
|
|
}
|
|
|
|
PCMPGTDMtoR(EEREC_D, (u32)ptempmem);
|
|
|
|
PUNPCKLDQRtoR(EEREC_D, EEREC_D);
|
|
PSRLQItoR(EEREC_D, 63);
|
|
}
|
|
|
|
return;
|
|
}
|
|
else {
|
|
// need to compare total 64 bit value
|
|
if( info & PROCESS_EE_MODEWRITET ) {
|
|
MOVQRtoM((u32)&cpuRegs.GPR.r[_Rt_], EEREC_T);
|
|
if( mmxregs[EEREC_T].reg == MMX_GPR+_Rt_ ) mmxregs[EEREC_T].mode &= ~MODE_WRITE;
|
|
}
|
|
|
|
// fall through
|
|
mmxregs[EEREC_D].mode |= MODE_WRITE; // in case EEREC_D was just flushed
|
|
}
|
|
}
|
|
|
|
if( info & PROCESS_EE_MMX ) PXORRtoR(EEREC_D, EEREC_D);
|
|
else XOR32RtoR(EAX, EAX);
|
|
|
|
CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], g_cpuConstRegs[_Rs_].UL[1]);
|
|
if( sign ) {
|
|
j8Ptr[0] = JL8( 0 );
|
|
j8Ptr[2] = JG8( 0 );
|
|
}
|
|
else {
|
|
j8Ptr[0] = JB8( 0 );
|
|
j8Ptr[2] = JA8( 0 );
|
|
}
|
|
|
|
CMP32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], g_cpuConstRegs[_Rs_].UL[0]);
|
|
j8Ptr[1] = JBE8(0);
|
|
|
|
x86SetJ8(j8Ptr[2]);
|
|
if( info & PROCESS_EE_MMX ) MOVDMtoMMX(EEREC_D, (u32)&s_sltone);
|
|
else MOV32ItoR(EAX, 1);
|
|
|
|
x86SetJ8(j8Ptr[0]);
|
|
x86SetJ8(j8Ptr[1]);
|
|
|
|
if( !(info & PROCESS_EE_MMX) ) {
|
|
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX );
|
|
if( EEINST_ISLIVE1(_Rd_) ) MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], 0 );
|
|
else EEINST_RESETHASLIVE1(_Rd_);
|
|
}
|
|
}
|
|
|
|
// SLT with one operand coming from mem (compares only low 32 bits)
|
|
void recSLTmemconstt(int regd, int regs, u32 mem, int sign)
|
|
{
|
|
// just compare the lower values
|
|
int t0reg;
|
|
|
|
if( sign ) {
|
|
if( regd == regs ) {
|
|
t0reg = _allocMMXreg(-1, MMX_TEMP, 0);
|
|
MOVQMtoR(t0reg, mem);
|
|
PCMPGTDRtoR(t0reg, regs);
|
|
|
|
PUNPCKLDQRtoR(t0reg, t0reg);
|
|
PSRLQItoR(t0reg, 63);
|
|
|
|
// swap regs
|
|
mmxregs[t0reg] = mmxregs[regd];
|
|
mmxregs[regd].inuse = 0;
|
|
}
|
|
else {
|
|
MOVQMtoR(regd, mem);
|
|
PCMPGTDRtoR(regd, regs);
|
|
|
|
PUNPCKLDQRtoR(regd, regd);
|
|
PSRLQItoR(regd, 63);
|
|
}
|
|
}
|
|
else {
|
|
t0reg = _allocMMXreg(-1, MMX_TEMP, 0);
|
|
|
|
if( regd == regs ) {
|
|
MOVQMtoR(t0reg, mem);
|
|
PXORMtoR(regs, (u32)&s_sltconst);
|
|
PCMPGTDRtoR(t0reg, regs);
|
|
|
|
PUNPCKLDQRtoR(t0reg, t0reg);
|
|
PSRLQItoR(t0reg, 63);
|
|
|
|
// swap regs
|
|
mmxregs[t0reg] = mmxregs[regd];
|
|
mmxregs[regd].inuse = 0;
|
|
}
|
|
else {
|
|
MOVQRtoR(t0reg, regs);
|
|
MOVQMtoR(regd, mem);
|
|
PXORMtoR(t0reg, (u32)&s_sltconst);
|
|
PCMPGTDRtoR(regd, t0reg);
|
|
|
|
PUNPCKLDQRtoR(regd, regd);
|
|
PSRLQItoR(regd, 63);
|
|
_freeMMXreg(t0reg);
|
|
}
|
|
}
|
|
}
|
|
|
|
void recSLTs_constt(int info, int sign)
|
|
{
|
|
assert( !(info & PROCESS_EE_XMM) );
|
|
|
|
if( info & PROCESS_EE_MMX ) {
|
|
if( _Rs_ == _Rt_ ) {
|
|
PXORRtoR(EEREC_D, EEREC_D);
|
|
return;
|
|
}
|
|
|
|
if( EEINST_ISSIGNEXT(_Rs_) && g_cpuConstRegs[_Rt_].UL[1] == (g_cpuConstRegs[_Rt_].SL[0]<0?0xffffffff:0) ) {
|
|
// just compare the lower values
|
|
if( sign ) {
|
|
recSLTmemconstt(EEREC_D, EEREC_S, (u32)_eeGetConstReg(_Rt_), 1);
|
|
}
|
|
else {
|
|
u32* ptempmem = recAllocStackMem(8,4);
|
|
ptempmem[0] = g_cpuConstRegs[_Rt_].UL[0]^0x80000000;
|
|
ptempmem[1] = 0;
|
|
|
|
recSLTmemconstt(EEREC_D, EEREC_S, (u32)ptempmem, 0);
|
|
}
|
|
|
|
return;
|
|
}
|
|
else {
|
|
// need to compare total 64 bit value
|
|
if( info & PROCESS_EE_MODEWRITES ) {
|
|
MOVQRtoM((u32)&cpuRegs.GPR.r[_Rs_], EEREC_S);
|
|
if( mmxregs[EEREC_S].reg == MMX_GPR+_Rs_ ) mmxregs[EEREC_S].mode &= ~MODE_WRITE;
|
|
}
|
|
mmxregs[EEREC_D].mode |= MODE_WRITE; // in case EEREC_D was just flushed
|
|
|
|
// fall through
|
|
}
|
|
}
|
|
|
|
if( info & PROCESS_EE_MMX ) MOVDMtoMMX(EEREC_D, (u32)&s_sltone);
|
|
else MOV32ItoR(EAX, 1);
|
|
|
|
CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], g_cpuConstRegs[_Rt_].UL[1]);
|
|
if( sign ) {
|
|
j8Ptr[0] = JL8( 0 );
|
|
j8Ptr[2] = JG8( 0 );
|
|
}
|
|
else {
|
|
j8Ptr[0] = JB8( 0 );
|
|
j8Ptr[2] = JA8( 0 );
|
|
}
|
|
|
|
CMP32ItoM((int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], g_cpuConstRegs[_Rt_].UL[0]);
|
|
j8Ptr[1] = JB8(0);
|
|
|
|
x86SetJ8(j8Ptr[2]);
|
|
if( info & PROCESS_EE_MMX ) PXORRtoR(EEREC_D, EEREC_D);
|
|
else XOR32RtoR(EAX, EAX);
|
|
|
|
x86SetJ8(j8Ptr[0]);
|
|
x86SetJ8(j8Ptr[1]);
|
|
|
|
if( !(info & PROCESS_EE_MMX) ) {
|
|
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX );
|
|
if( EEINST_ISLIVE1(_Rd_) ) MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], 0 );
|
|
else EEINST_RESETHASLIVE1(_Rd_);
|
|
}
|
|
}
|
|
|
|
void recSLTs_(int info, int sign)
|
|
{
|
|
if( info & PROCESS_EE_MMX ) MOVDMtoMMX(EEREC_D, (u32)&s_sltone);
|
|
else MOV32ItoR(EAX, 1);
|
|
|
|
MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ]);
|
|
CMP32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ]);
|
|
|
|
if( sign ) {
|
|
j8Ptr[0] = JL8( 0 );
|
|
j8Ptr[2] = JG8( 0 );
|
|
}
|
|
else {
|
|
j8Ptr[0] = JB8( 0 );
|
|
j8Ptr[2] = JA8( 0 );
|
|
}
|
|
|
|
MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]);
|
|
CMP32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]);
|
|
j8Ptr[1] = JB8(0);
|
|
|
|
x86SetJ8(j8Ptr[2]);
|
|
if( info & PROCESS_EE_MMX ) PXORRtoR(EEREC_D, EEREC_D);
|
|
else XOR32RtoR(EAX, EAX);
|
|
|
|
x86SetJ8(j8Ptr[0]);
|
|
x86SetJ8(j8Ptr[1]);
|
|
|
|
if( !(info & PROCESS_EE_MMX) ) {
|
|
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX );
|
|
if( EEINST_ISLIVE1(_Rd_) ) MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], 0 );
|
|
else EEINST_RESETHASLIVE1(_Rd_);
|
|
}
|
|
}
|
|
|
|
void recSLT_consts(int info)
|
|
{
|
|
recSLTs_consts(info, 1);
|
|
}
|
|
|
|
void recSLT_constt(int info)
|
|
{
|
|
recSLTs_constt(info, 1);
|
|
}
|
|
|
|
void recSLT_(int info)
|
|
{
|
|
int t0reg;
|
|
assert( !(info & PROCESS_EE_XMM) );
|
|
|
|
if( !(info & PROCESS_EE_MMX) ) {
|
|
recSLTs_(info, 1);
|
|
return;
|
|
}
|
|
|
|
if( !EEINST_ISSIGNEXT(_Rs_) || !EEINST_ISSIGNEXT(_Rt_) ) {
|
|
// need to compare total 64 bit value
|
|
if( info & PROCESS_EE_MODEWRITES ) {
|
|
MOVQRtoM((u32)&cpuRegs.GPR.r[_Rs_], EEREC_S);
|
|
if( mmxregs[EEREC_S].reg == MMX_GPR+_Rs_ ) mmxregs[EEREC_S].mode &= ~MODE_WRITE;
|
|
}
|
|
if( info & PROCESS_EE_MODEWRITET ) {
|
|
MOVQRtoM((u32)&cpuRegs.GPR.r[_Rt_], EEREC_T);
|
|
if( mmxregs[EEREC_T].reg == MMX_GPR+_Rt_ ) mmxregs[EEREC_T].mode &= ~MODE_WRITE;
|
|
}
|
|
mmxregs[EEREC_D].mode |= MODE_WRITE; // in case EEREC_D was just flushed
|
|
recSLTs_(info, 1);
|
|
return;
|
|
}
|
|
|
|
if( EEREC_S == EEREC_T ) {
|
|
PXORRtoR(EEREC_D, EEREC_D);
|
|
return;
|
|
}
|
|
|
|
// just compare the lower values
|
|
if( EEREC_D == EEREC_S ) {
|
|
t0reg = _allocMMXreg(-1, MMX_TEMP, 0);
|
|
MOVQRtoR(t0reg, EEREC_T);
|
|
PCMPGTDRtoR(t0reg, EEREC_S);
|
|
|
|
PUNPCKLDQRtoR(t0reg, t0reg);
|
|
PSRLQItoR(t0reg, 63);
|
|
|
|
// swap regs
|
|
mmxregs[t0reg] = mmxregs[EEREC_D];
|
|
mmxregs[EEREC_D].inuse = 0;
|
|
}
|
|
else {
|
|
if( EEREC_D != EEREC_T ) MOVQRtoR(EEREC_D, EEREC_T);
|
|
PCMPGTDRtoR(EEREC_D, EEREC_S);
|
|
|
|
PUNPCKLDQRtoR(EEREC_D, EEREC_D);
|
|
PSRLQItoR(EEREC_D, 63);
|
|
}
|
|
}
|
|
|
|
EERECOMPILE_CODE0(SLT, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED);
|
|
|
|
// SLTU - test with silent hill, lemans
|
|
void recSLTU_const()
|
|
{
|
|
g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].UD[0] < g_cpuConstRegs[_Rt_].UD[0];
|
|
}
|
|
|
|
void recSLTU_consts(int info)
|
|
{
|
|
recSLTs_consts(info, 0);
|
|
EEINST_SETSIGNEXT(_Rd_);
|
|
}
|
|
|
|
void recSLTU_constt(int info)
|
|
{
|
|
recSLTs_constt(info, 0);
|
|
EEINST_SETSIGNEXT(_Rd_);
|
|
}
|
|
|
|
void recSLTU_(int info)
|
|
{
|
|
int t1reg;
|
|
|
|
assert( !(info & PROCESS_EE_XMM) );
|
|
EEINST_SETSIGNEXT(_Rd_);
|
|
|
|
if( !(info & PROCESS_EE_MMX) ) {
|
|
recSLTs_(info, 0);
|
|
return;
|
|
}
|
|
|
|
if( EEREC_S == EEREC_T ) {
|
|
PXORRtoR(EEREC_D, EEREC_D);
|
|
return;
|
|
}
|
|
|
|
if( !EEINST_ISSIGNEXT(_Rs_) || !EEINST_ISSIGNEXT(_Rt_) ) {
|
|
// need to compare total 64 bit value
|
|
if( info & PROCESS_EE_MODEWRITES ) {
|
|
MOVQRtoM((u32)&cpuRegs.GPR.r[_Rs_], EEREC_S);
|
|
if( mmxregs[EEREC_S].reg == MMX_GPR+_Rs_ ) mmxregs[EEREC_S].mode &= ~MODE_WRITE;
|
|
}
|
|
if( info & PROCESS_EE_MODEWRITET ) {
|
|
MOVQRtoM((u32)&cpuRegs.GPR.r[_Rt_], EEREC_T);
|
|
if( mmxregs[EEREC_T].reg == MMX_GPR+_Rt_ ) mmxregs[EEREC_T].mode &= ~MODE_WRITE;
|
|
}
|
|
mmxregs[EEREC_D].mode |= MODE_WRITE; // in case EEREC_D was just flushed
|
|
recSLTs_(info, 0);
|
|
return;
|
|
}
|
|
|
|
t1reg = _allocMMXreg(-1, MMX_TEMP, 0);
|
|
|
|
MOVDMtoMMX(t1reg, (u32)&s_sltconst);
|
|
|
|
if( EEREC_D == EEREC_S ) {
|
|
PXORRtoR(EEREC_S, t1reg);
|
|
PXORRtoR(t1reg, EEREC_T);
|
|
PCMPGTDRtoR(t1reg, EEREC_S);
|
|
|
|
PUNPCKLDQRtoR(t1reg, t1reg);
|
|
PSRLQItoR(t1reg, 63);
|
|
|
|
// swap regs
|
|
mmxregs[t1reg] = mmxregs[EEREC_D];
|
|
mmxregs[EEREC_D].inuse = 0;
|
|
}
|
|
else {
|
|
if( EEREC_D != EEREC_T ) {
|
|
MOVDMtoMMX(EEREC_D, (u32)&s_sltconst);
|
|
PXORRtoR(t1reg, EEREC_S);
|
|
PXORRtoR(EEREC_D, EEREC_T);
|
|
}
|
|
else {
|
|
PXORRtoR(EEREC_D, t1reg);
|
|
PXORRtoR(t1reg, EEREC_S);
|
|
}
|
|
|
|
PCMPGTDRtoR(EEREC_D, t1reg);
|
|
|
|
PUNPCKLDQRtoR(EEREC_D, EEREC_D);
|
|
PSRLQItoR(EEREC_D, 63);
|
|
|
|
_freeMMXreg(t1reg);
|
|
}
|
|
}
|
|
|
|
EERECOMPILE_CODE0(SLTU, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED);
|
|
|
|
#else
|
|
|
|
////////////////////////////////////////////////////
|
|
void recADD( void )
|
|
{
|
|
if ( ! _Rd_ )
|
|
{
|
|
return;
|
|
}
|
|
|
|
MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] );
|
|
ADD32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] );
|
|
CDQ( );
|
|
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX );
|
|
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX );
|
|
}
|
|
|
|
////////////////////////////////////////////////////
|
|
void recADDU( void )
|
|
{
|
|
recADD( );
|
|
}
|
|
|
|
////////////////////////////////////////////////////
|
|
void recDADD( void )
|
|
{
|
|
if ( ! _Rd_ )
|
|
{
|
|
return;
|
|
}
|
|
MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] );
|
|
MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] );
|
|
ADD32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] );
|
|
ADC32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] );
|
|
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX );
|
|
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX );
|
|
}
|
|
|
|
////////////////////////////////////////////////////
|
|
void recDADDU( void )
|
|
{
|
|
recDADD( );
|
|
}
|
|
|
|
////////////////////////////////////////////////////
|
|
void recSUB( void )
|
|
{
|
|
if ( ! _Rd_ ) return;
|
|
MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] );
|
|
SUB32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] );
|
|
CDQ( );
|
|
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX );
|
|
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX );
|
|
|
|
}
|
|
|
|
////////////////////////////////////////////////////
|
|
void recSUBU( void )
|
|
{
|
|
recSUB( );
|
|
}
|
|
|
|
////////////////////////////////////////////////////
|
|
void recDSUB( void )
|
|
{
|
|
if ( ! _Rd_ ) return;
|
|
|
|
MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] );
|
|
MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] );
|
|
SUB32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] );
|
|
SBB32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] );
|
|
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX );
|
|
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX );
|
|
|
|
}
|
|
|
|
////////////////////////////////////////////////////
|
|
void recDSUBU( void )
|
|
{
|
|
recDSUB( );
|
|
}
|
|
|
|
////////////////////////////////////////////////////
|
|
void recAND( void )
|
|
{
|
|
if ( ! _Rd_ )
|
|
{
|
|
return;
|
|
}
|
|
if ( ( _Rt_ == 0 ) || ( _Rs_ == 0 ) )
|
|
{
|
|
MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], 0 );
|
|
MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], 0 );
|
|
}
|
|
else
|
|
{
|
|
MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rs_ ] );
|
|
MOVQMtoR( MM1, (int)&cpuRegs.GPR.r[ _Rt_ ] );
|
|
PANDRtoR( MM0, MM1);
|
|
MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 );
|
|
SetMMXstate();
|
|
}
|
|
|
|
}
|
|
|
|
////////////////////////////////////////////////////
|
|
void recOR( void )
|
|
{
|
|
if ( ! _Rd_ )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( ( _Rs_ == 0 ) && ( _Rt_ == 0 ) )
|
|
{
|
|
MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], 0x0 );
|
|
MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], 0x0 );
|
|
}
|
|
else if ( _Rs_ == 0 )
|
|
{
|
|
MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rt_ ] );
|
|
MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 );
|
|
SetMMXstate();
|
|
}
|
|
else if ( _Rt_ == 0 )
|
|
{
|
|
MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rs_ ] );
|
|
MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 );
|
|
SetMMXstate();
|
|
}
|
|
else
|
|
{
|
|
MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rs_ ] );
|
|
MOVQMtoR( MM1, (int)&cpuRegs.GPR.r[ _Rt_ ] );
|
|
PORRtoR( MM0, MM1 );
|
|
MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 );
|
|
SetMMXstate();
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////
|
|
void recXOR( void )
|
|
{
|
|
if ( ! _Rd_ )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( ( _Rs_ == 0 ) && ( _Rt_ == 0 ) )
|
|
{
|
|
MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ],0x0);
|
|
MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ],0x0);
|
|
return;
|
|
}
|
|
|
|
if ( _Rs_ == 0 )
|
|
{
|
|
MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rt_ ] );
|
|
MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 );
|
|
SetMMXstate();
|
|
return;
|
|
}
|
|
|
|
if ( _Rt_ == 0 )
|
|
{
|
|
MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rs_ ] );
|
|
MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 );
|
|
SetMMXstate();
|
|
return;
|
|
}
|
|
|
|
MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rs_ ] );
|
|
MOVQMtoR( MM1, (int)&cpuRegs.GPR.r[ _Rt_ ] );
|
|
PXORRtoR( MM0, MM1);
|
|
MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 );
|
|
SetMMXstate();
|
|
}
|
|
|
|
////////////////////////////////////////////////////
|
|
void recNOR( void )
|
|
{
|
|
if ( ! _Rd_ )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( ( _Rs_ == 0 ) && ( _Rt_ == 0 ) )
|
|
{
|
|
MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ],0xffffffff);
|
|
MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ],0xffffffff);
|
|
return;
|
|
}
|
|
|
|
if ( _Rs_ == 0 )
|
|
{
|
|
MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rt_ ] );
|
|
PCMPEQDRtoR( MM1,MM1);
|
|
PXORRtoR( MM0,MM1);
|
|
MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ],MM0);
|
|
SetMMXstate();
|
|
return;
|
|
}
|
|
|
|
if ( _Rt_ == 0 )
|
|
{
|
|
MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rs_ ] );
|
|
PCMPEQDRtoR( MM1,MM1);
|
|
PXORRtoR( MM0,MM1);
|
|
MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ],MM0);
|
|
SetMMXstate();
|
|
return;
|
|
}
|
|
|
|
MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rs_ ] );
|
|
PCMPEQDRtoR( MM1,MM1);
|
|
PORMtoR( MM0,(int)&cpuRegs.GPR.r[ _Rt_ ] );
|
|
PXORRtoR( MM0,MM1);
|
|
MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ],MM0);
|
|
SetMMXstate();
|
|
}
|
|
|
|
////////////////////////////////////////////////////
|
|
// test with silent hill, lemans
|
|
void recSLT( void )
|
|
{
|
|
if ( ! _Rd_ )
|
|
return;
|
|
|
|
MOV32ItoR(EAX, 1);
|
|
|
|
if( _Rs_ == 0 ) {
|
|
CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0);
|
|
j8Ptr[0] = JG8( 0 );
|
|
j8Ptr[2] = JL8( 0 );
|
|
|
|
CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], 0 );
|
|
j8Ptr[1] = JA8(0);
|
|
|
|
x86SetJ8(j8Ptr[2]);
|
|
XOR32RtoR(EAX, EAX);
|
|
}
|
|
else if( _Rt_ == 0 ) {
|
|
CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], 0);
|
|
j8Ptr[0] = JL8( 0 );
|
|
j8Ptr[2] = JG8( 0 );
|
|
|
|
CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], 0);
|
|
j8Ptr[1] = JB8(0);
|
|
|
|
x86SetJ8(j8Ptr[2]);
|
|
XOR32RtoR(EAX, EAX);
|
|
}
|
|
else {
|
|
MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ]);
|
|
CMP32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ]);
|
|
j8Ptr[0] = JL8( 0 );
|
|
j8Ptr[2] = JG8( 0 );
|
|
|
|
MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]);
|
|
CMP32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]);
|
|
j8Ptr[1] = JB8(0);
|
|
|
|
x86SetJ8(j8Ptr[2]);
|
|
XOR32RtoR(EAX, EAX);
|
|
}
|
|
|
|
x86SetJ8(j8Ptr[0]);
|
|
x86SetJ8(j8Ptr[1]);
|
|
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX );
|
|
MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], 0 );
|
|
}
|
|
|
|
////////////////////////////////////////////////////
|
|
void recSLTU( void )
|
|
{
|
|
MOV32ItoR(EAX, 1);
|
|
|
|
if( _Rs_ == 0 ) {
|
|
CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0);
|
|
j8Ptr[0] = JA8( 0 );
|
|
j8Ptr[2] = JB8( 0 );
|
|
|
|
CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], 0 );
|
|
j8Ptr[1] = JA8(0);
|
|
|
|
x86SetJ8(j8Ptr[2]);
|
|
XOR32RtoR(EAX, EAX);
|
|
}
|
|
else if( _Rt_ == 0 ) {
|
|
CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], 0);
|
|
j8Ptr[0] = JB8( 0 );
|
|
j8Ptr[2] = JA8( 0 );
|
|
|
|
CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], 0);
|
|
j8Ptr[1] = JB8(0);
|
|
|
|
x86SetJ8(j8Ptr[2]);
|
|
XOR32RtoR(EAX, EAX);
|
|
}
|
|
else {
|
|
MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ]);
|
|
CMP32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ]);
|
|
j8Ptr[0] = JB8( 0 );
|
|
j8Ptr[2] = JA8( 0 );
|
|
|
|
MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]);
|
|
CMP32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]);
|
|
j8Ptr[1] = JB8(0);
|
|
|
|
x86SetJ8(j8Ptr[2]);
|
|
XOR32RtoR(EAX, EAX);
|
|
}
|
|
|
|
x86SetJ8(j8Ptr[0]);
|
|
x86SetJ8(j8Ptr[1]);
|
|
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX );
|
|
MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], 0 );
|
|
}
|
|
|
|
#endif
|