Started rewriting arithmetic instructions because of the disgusting state of the code, went mad and stripped the main case for the liveness optimisation from the recompiler. It would be very nice if it worked and wasn't such a mess but it hasn't for a long time or never did. Didn't revert the one function I rewrote, next commit will likely be the rest of the file.

While doing this, spotted and fixed a couple of bugs with doubleword add/sub when one operand is a constant propagated from earlier in the block and has 0 in the upper word; the instructions weren't performing the carry/borrow in this case.  Likely doesn't fix any game.

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@2690 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
sudonim1 2010-03-10 14:56:30 +00:00
parent d8ef7a4171
commit d846c8709f
16 changed files with 207 additions and 1605 deletions

View File

@ -224,8 +224,8 @@ void iDumpBlock( int startpc, u8 * ptr )
// write the instruction info
eff.Printf( "\n\nlive0 - %x, live1 - %x, live2 - %x, lastuse - %x\nxmm - %x, used - %x\n",
EEINST_LIVE0, EEINST_LIVE1, EEINST_LIVE2, EEINST_LASTUSE, EEINST_XMM, EEINST_USED
eff.Printf( "\n\nlive0 - %x, live2 - %x, lastuse - %x\nxmm - %x, used - %x\n",
EEINST_LIVE0, EEINST_LIVE2, EEINST_LASTUSE, EEINST_XMM, EEINST_USED
);
memzero(used);

View File

@ -135,8 +135,6 @@ REC_SYS( MTC0 );
void recMFC0( void )
{
int mmreg;
if( _Rd_ == 9 )
{
// This case needs to be handled even if the write-back is ignored (_Rt_ == 0 )
@ -155,11 +153,8 @@ void recMFC0( void )
_deleteEEreg(_Rt_, 0);
MOV32RtoM((uptr)&cpuRegs.GPR.r[_Rt_].UL[0],EAX);
if(EEINST_ISLIVE1(_Rt_)) {
CDQ();
MOV32RtoM((uptr)&cpuRegs.GPR.r[_Rt_].UL[1], EDX);
}
else EEINST_RESETHASLIVE1(_Rt_);
CDQ();
MOV32RtoM((uptr)&cpuRegs.GPR.r[_Rt_].UL[1], EDX);
return;
}
@ -187,11 +182,8 @@ void recMFC0( void )
_deleteEEreg(_Rt_, 0);
MOV32RtoM((uptr)&cpuRegs.GPR.r[_Rt_].UL[0],EAX);
if(EEINST_ISLIVE1(_Rt_)) {
CDQ();
MOV32RtoM((uptr)&cpuRegs.GPR.r[_Rt_].UL[1], EDX);
}
else EEINST_RESETHASLIVE1(_Rt_);
CDQ();
MOV32RtoM((uptr)&cpuRegs.GPR.r[_Rt_].UL[1], EDX);
return;
}
@ -200,49 +192,11 @@ void recMFC0( void )
return;
}
_eeOnWriteReg(_Rt_, 1);
if( EEINST_ISLIVE1(_Rt_) ) {
_deleteEEreg(_Rt_, 0);
MOV32MtoR(EAX, (uptr)&cpuRegs.CP0.r[ _Rd_ ]);
CDQ();
MOV32RtoM((uptr)&cpuRegs.GPR.r[_Rt_].UL[0], EAX);
MOV32RtoM((uptr)&cpuRegs.GPR.r[_Rt_].UL[1], EDX);
}
else {
EEINST_RESETHASLIVE1(_Rt_);
if( (mmreg = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_WRITE)) >= 0 ) {
MOVDMtoMMX(mmreg, (uptr)&cpuRegs.CP0.r[ _Rd_ ]);
SetMMXstate();
}
else if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_READ)) >= 0) {
if( EEINST_ISLIVE2(_Rt_) ) {
if( xmmregs[mmreg].mode & MODE_WRITE ) {
SSE_MOVHPS_XMM_to_M64((uptr)&cpuRegs.GPR.r[_Rt_].UL[2], mmreg);
}
xmmregs[mmreg].inuse = 0;
MOV32MtoR(EAX, (uptr)&cpuRegs.CP0.r[ _Rd_ ]);
MOV32RtoM((uptr)&cpuRegs.GPR.r[_Rt_].UL[0],EAX);
}
else {
SSE_MOVLPS_M64_to_XMM(mmreg, (uptr)&cpuRegs.CP0.r[ _Rd_ ]);
}
}
else {
MOV32MtoR(EAX, (uptr)&cpuRegs.CP0.r[ _Rd_ ]);
if(_Rd_ == 12) AND32ItoR(EAX, 0xf0c79c1f);
MOV32RtoM((uptr)&cpuRegs.GPR.r[_Rt_].UL[0],EAX);
if(EEINST_ISLIVE1(_Rt_)) {
CDQ();
MOV32RtoM((uptr)&cpuRegs.GPR.r[_Rt_].UL[1], EDX);
}
else {
EEINST_RESETHASLIVE1(_Rt_);
}
}
}
_deleteEEreg(_Rt_, 0);
MOV32MtoR(EAX, (uptr)&cpuRegs.CP0.r[ _Rd_ ]);
CDQ();
MOV32RtoM((uptr)&cpuRegs.GPR.r[_Rt_].UL[0], EAX);
MOV32RtoM((uptr)&cpuRegs.GPR.r[_Rt_].UL[1], EDX);
}
void recMTC0()

View File

@ -30,9 +30,6 @@ u16 g_xmmAllocCounter = 0;
EEINST* g_pCurInstInfo = NULL;
u32 g_cpuRegHasLive1 = 0, g_cpuPrevRegHasLive1 = 0; // set if upper 32 bits are live
u32 g_cpuRegHasSignExt = 0, g_cpuPrevRegHasSignExt = 0; // set if upper 32 bits are the sign extension of the lower integer
// used to make sure regs don't get changed while in recompiler
// use FreezeMMXRegs, FreezeXMMRegs
u32 g_recWriteback = 0;
@ -1028,7 +1025,7 @@ int _allocCheckGPRtoX86(EEINST* pinst, int gprreg, int mode)
void _recClearInst(EEINST* pinst)
{
memzero( *pinst );
memset8<EEINST_LIVE0|EEINST_LIVE1|EEINST_LIVE2>( pinst->regs );
memset8<EEINST_LIVE0|EEINST_LIVE2>( pinst->regs );
memset8<EEINST_LIVE0>( pinst->fpuregs );
}

View File

@ -198,7 +198,6 @@ static const int MEM_XMMTAG = 0x8000; // mmreg is xmmreg
// Instruction Info //
//////////////////////
#define EEINST_LIVE0 1 // if var is ever used (read or write)
#define EEINST_LIVE1 2 // if cur var's next 32 bits are needed
#define EEINST_LIVE2 4 // if cur var's next 64 bits are needed
#define EEINST_LASTUSE 8 // if var isn't written/read anymore
//#define EEINST_MMX 0x10 // removed
@ -234,22 +233,14 @@ extern u32 _recIsRegWritten(EEINST* pinst, int size, u8 xmmtype, u8 reg);
extern u32 _recIsRegUsed(EEINST* pinst, int size, u8 xmmtype, u8 reg);
extern void _recFillRegister(EEINST& pinst, int type, int reg, int write);
static __forceinline bool EEINST_ISLIVE64(u32 reg) { return !!(g_pCurInstInfo->regs[reg] & (EEINST_LIVE0|EEINST_LIVE1)); }
static __forceinline bool EEINST_ISLIVEXMM(u32 reg) { return !!(g_pCurInstInfo->regs[reg] & (EEINST_LIVE0|EEINST_LIVE1|EEINST_LIVE2)); }
static __forceinline bool EEINST_ISLIVE1(u32 reg) { return !!(g_pCurInstInfo->regs[reg] & EEINST_LIVE1); }
static __forceinline bool EEINST_ISLIVE64(u32 reg) { return !!(g_pCurInstInfo->regs[reg] & (EEINST_LIVE0)); }
static __forceinline bool EEINST_ISLIVEXMM(u32 reg) { return !!(g_pCurInstInfo->regs[reg] & (EEINST_LIVE0|EEINST_LIVE2)); }
static __forceinline bool EEINST_ISLIVE2(u32 reg) { return !!(g_pCurInstInfo->regs[reg] & EEINST_LIVE2); }
static __forceinline bool FPUINST_ISLIVE(u32 reg) { return !!(g_pCurInstInfo->fpuregs[reg] & EEINST_LIVE0); }
static __forceinline bool FPUINST_LASTUSE(u32 reg) { return !!(g_pCurInstInfo->fpuregs[reg] & EEINST_LASTUSE); }
// if set, then the variable at this inst really has its upper 32 bits valid
// The difference between EEINST_LIVE1 is that the latter is used in back propagation
// The former is set at recompile time.
#define EEINST_RESETHASLIVE1(reg) { if( (reg) < 32 ) g_cpuRegHasLive1 &= ~(1<<(reg)); }
#define EEINST_HASLIVE1(reg) (g_cpuPrevRegHasLive1&(1<<(reg)))
extern u32 g_recWriteback; // used for jumps (VUrec mess!)
extern u32 g_cpuRegHasLive1, g_cpuPrevRegHasLive1;
extern _xmmregs xmmregs[iREGCNT_XMM], s_saveXMMregs[iREGCNT_XMM];

View File

@ -124,17 +124,9 @@ void recCFC1(void)
OR32ItoR(EAX, 0x01000001); //set always-one bits
}
if(EEINST_ISLIVE1(_Rt_))
{
CDQ( );
MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX );
MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX );
}
else
{
EEINST_RESETHASLIVE1(_Rt_);
MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX );
}
CDQ( );
MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX );
MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX );
}
void recCTC1( void )
@ -198,23 +190,11 @@ void recMFC1(void)
if( regt >= 0 )
{
SSE2_MOVDQ2Q_XMM_to_MM(regt, regs);
if(EEINST_ISLIVE1(_Rt_))
_signExtendGPRtoMMX(regt, _Rt_, 0);
else
EEINST_RESETHASLIVE1(_Rt_);
_signExtendGPRtoMMX(regt, _Rt_, 0);
}
else
{
if(EEINST_ISLIVE1(_Rt_))
{
_signExtendXMMtoM((uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], regs, 0);
}
else
{
EEINST_RESETHASLIVE1(_Rt_);
SSE_MOVSS_XMM_to_M32((uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], regs);
}
_signExtendXMMtoM((uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], regs, 0);
}
}
else
@ -244,17 +224,9 @@ void recMFC1(void)
_deleteEEreg(_Rt_, 0);
MOV32MtoR( EAX, (uptr)&fpuRegs.fpr[ _Fs_ ].UL );
if(EEINST_ISLIVE1(_Rt_))
{
CDQ( );
MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX );
MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX );
}
else
{
EEINST_RESETHASLIVE1(_Rt_);
MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX );
}
CDQ( );
MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX );
MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX );
}
}
}

View File

@ -100,12 +100,7 @@ void recPLZCW()
regs = 0;
}
if( EEINST_ISLIVE1(_Rd_) )
_deleteEEreg(_Rd_, 0);
else {
if( (regd = _checkMMXreg(MMX_GPR+_Rd_, MODE_WRITE)) < 0 )
_deleteEEreg(_Rd_, 0);
}
_deleteEEreg(_Rd_, 0);
// Count the number of leading bits (MSB) that match the sign bit, excluding the sign
// bit itself.
@ -129,47 +124,36 @@ void recPLZCW()
DEC32R(ECX); // PS2 doesn't count the first bit
x86SetJ8(label_Zeroed);
if( EEINST_ISLIVE1(_Rd_) || regd < 0 ) {
MOV32RtoM((uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], ECX);
}
else {
SetMMXstate();
MOVD32RtoMMX(regd, ECX);
}
MOV32RtoM((uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], ECX);
// second word
if( EEINST_ISLIVE1(_Rd_) ) {
if( regs >= 0 && (regs & MEM_XMMTAG) ) {
SSE2_PSHUFD_XMM_to_XMM(regs&0xf, regs&0xf, 0x4e);
SSE2_MOVD_XMM_to_R(EAX, regs&0xf);
SSE2_PSHUFD_XMM_to_XMM(regs&0xf, regs&0xf, 0x4e);
}
else if( regs >= 0 && (regs & MEM_MMXTAG) ) {
PSHUFWRtoR(regs&0xf, regs&0xf, 0x4e);
MOVD32MMXtoR(EAX, regs&0xf);
PSHUFWRtoR(regs&0xf, regs&0xf, 0x4e);
SetMMXstate();
}
else MOV32MtoR(EAX, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ]);
MOV32ItoR(ECX, 31);
TEST32RtoR(EAX, EAX); // TEST sets the sign flag accordingly.
label_notSigned = JNS8(0);
NOT32R(EAX);
x86SetJ8(label_notSigned);
BSRRtoR(EAX, EAX);
u8* label_Zeroed = JZ8(0); // If BSR sets the ZF, eax is "trash"
SUB32RtoR(ECX, EAX);
DEC32R(ECX); // PS2 doesn't count the first bit
x86SetJ8(label_Zeroed);
MOV32RtoM((uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], ECX);
if( regs >= 0 && (regs & MEM_XMMTAG) ) {
SSE2_PSHUFD_XMM_to_XMM(regs&0xf, regs&0xf, 0x4e);
SSE2_MOVD_XMM_to_R(EAX, regs&0xf);
SSE2_PSHUFD_XMM_to_XMM(regs&0xf, regs&0xf, 0x4e);
}
else {
EEINST_RESETHASLIVE1(_Rd_);
else if( regs >= 0 && (regs & MEM_MMXTAG) ) {
PSHUFWRtoR(regs&0xf, regs&0xf, 0x4e);
MOVD32MMXtoR(EAX, regs&0xf);
PSHUFWRtoR(regs&0xf, regs&0xf, 0x4e);
SetMMXstate();
}
else MOV32MtoR(EAX, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ]);
MOV32ItoR(ECX, 31);
TEST32RtoR(EAX, EAX); // TEST sets the sign flag accordingly.
label_notSigned = JNS8(0);
NOT32R(EAX);
x86SetJ8(label_notSigned);
BSRRtoR(EAX, EAX);
label_Zeroed = JZ8(0); // If BSR sets the ZF, eax is "trash"
SUB32RtoR(ECX, EAX);
DEC32R(ECX); // PS2 doesn't count the first bit
x86SetJ8(label_Zeroed);
MOV32RtoM((uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], ECX);
GPR_DEL_CONST(_Rd_);
}

View File

@ -235,51 +235,4 @@ void rec##fn(void) \
int eeRecompileCodeXMM(int xmminfo);
void eeFPURecompileCode(R5900FNPTR_INFO xmmcode, R5900FNPTR fpucode, int xmminfo);
// For propagation of BSC stuff.
// Code implementations in ir5900tables.c
class BSCPropagate
{
protected:
EEINST& prev;
EEINST& pinst;
public:
BSCPropagate( EEINST& previous, EEINST& pinstance );
void rprop();
protected:
void rpropSPECIAL();
void rpropREGIMM();
void rpropCP0();
void rpropCP1();
void rpropCP2();
void rpropMMI();
void rpropMMI0();
void rpropMMI1();
void rpropMMI2();
void rpropMMI3();
void rpropSetRead( int reg, int mask );
void rpropSetFPURead( int reg, int mask );
void rpropSetWrite( int reg, int mask );
void rpropSetFPUWrite( int reg, int mask );
template< int mask >
void rpropSetRead( int reg );
template< int live >
void rpropSetWrite0( int reg, int mask );
void rpropSetFast( int write1, int read1, int read2, int mask );
template< int low, int hi >
void rpropSetLOHI( int write1, int read1, int read2, int mask );
template< int live >
void rpropSetFPUWrite0( int reg, int mask );
};
#endif // __IR5900_H__

View File

@ -34,942 +34,3 @@
#include "iFPU.h"
#include "iCOP0.h"
// Use this to call into interpreter functions that require an immediate branchtest
// to be done afterward (anything that throws an exception or enables interrupts, etc).
void recBranchCall( void (*func)() )
{
// In order to make sure a branch test is performed, the nextBranchCycle is set
// to the current cpu cycle.
MOV32ItoM( (uptr)&cpuRegs.code, cpuRegs.code );
MOV32MtoR( EAX, (uptr)&cpuRegs.cycle );
MOV32ItoM( (uptr)&cpuRegs.pc, pc );
MOV32RtoM( (uptr)&g_nextBranchCycle, EAX );
// Might as well flush everything -- it'll all get flushed when the
// recompiler inserts the branchtest anyway.
iFlushCall(FLUSH_EVERYTHING);
CALLFunc( (uptr)func );
branch = 2;
}
void recCall( void (*func)(), int delreg )
{
MOV32ItoM( (uptr)&cpuRegs.code, cpuRegs.code );
MOV32ItoM( (uptr)&cpuRegs.pc, pc );
iFlushCall(FLUSH_EVERYTHING);
if( delreg > 0 ) _deleteEEreg(delreg, 0);
CALLFunc( (uptr)func );
}
using namespace R5900::Dynarec::OpcodeImpl;
////////////////////////////////////////////////
// Back-Prob Function Tables - Gathering Info //
////////////////////////////////////////////////
BSCPropagate::BSCPropagate( EEINST& previous, EEINST& pinstance ) :
prev( previous )
, pinst( pinstance )
{
}
void BSCPropagate::rpropSetRead( int reg, int mask )
{
if( !(pinst.regs[reg] & EEINST_USED) )
pinst.regs[reg] |= EEINST_LASTUSE;
prev.regs[reg] |= EEINST_LIVE0|(mask)|EEINST_USED;
pinst.regs[reg] |= EEINST_USED;
if( reg ) pinst.info = ((mask)&EEINST_XMM);
_recFillRegister(pinst, XMMTYPE_GPRREG, reg, 0);
}
template< int live >
void BSCPropagate::rpropSetWrite0( int reg, int mask )
{
prev.regs[reg] &= ~((mask)|live|EEINST_XMM);
if( !(pinst.regs[reg] & EEINST_USED) )
pinst.regs[reg] |= EEINST_LASTUSE;
pinst.regs[reg] |= EEINST_USED;
prev.regs[reg] |= EEINST_USED;
_recFillRegister(pinst, XMMTYPE_GPRREG, reg, 1);
}
__forceinline void BSCPropagate::rpropSetWrite( int reg, int mask )
{
rpropSetWrite0<EEINST_LIVE0>( reg, mask );
}
__forceinline void BSCPropagate::rpropSetFast( int write1, int read1, int read2, int mask )
{
if( write1 ) { rpropSetWrite(write1,mask); }
if( read1 ) { rpropSetRead(read1,mask); }
if( read2 ) { rpropSetRead(read2,mask); }
}
template< int lo, int hi >
void BSCPropagate::rpropSetLOHI( int write1, int read1, int read2, int mask )
{
if( write1 ) { rpropSetWrite(write1,mask); }
if( lo & MODE_WRITE ) { rpropSetWrite(XMMGPR_LO,mask); }
if( hi & MODE_WRITE ) { rpropSetWrite(XMMGPR_HI,mask); }
if( read1 ) { rpropSetRead(read1,mask); }
if( read2 ) { rpropSetRead(read2,mask); }
if( lo & MODE_READ ) { rpropSetRead(XMMGPR_LO,mask); }
if( hi & MODE_READ ) { rpropSetRead(XMMGPR_HI,mask); }
}
// FPU regs
void BSCPropagate::rpropSetFPURead( int reg, int mask )
{
if( !(pinst.fpuregs[reg] & EEINST_USED) )
pinst.fpuregs[reg] |= EEINST_LASTUSE;
prev.fpuregs[reg] |= EEINST_LIVE0|(mask)|EEINST_USED;
pinst.fpuregs[reg] |= EEINST_USED;
if( reg ) pinst.info = ((mask)&EEINST_XMM);
if( reg == XMMFPU_ACC ) _recFillRegister(pinst, XMMTYPE_FPACC, 0, 0);
else _recFillRegister(pinst, XMMTYPE_FPREG, reg, 0);
}
template< int live >
void BSCPropagate::rpropSetFPUWrite0( int reg, int mask )
{
prev.fpuregs[reg] &= ~((mask)|live|EEINST_XMM);
if( !(pinst.fpuregs[reg] & EEINST_USED) )
pinst.fpuregs[reg] |= EEINST_LASTUSE;
pinst.fpuregs[reg] |= EEINST_USED;
prev.fpuregs[reg] |= EEINST_USED;
if( reg == XMMFPU_ACC ) _recFillRegister(pinst, XMMTYPE_FPACC, 0, 1);
else _recFillRegister(pinst, XMMTYPE_FPREG, reg, 1);
}
__forceinline void BSCPropagate::rpropSetFPUWrite( int reg, int mask )
{
rpropSetFPUWrite0<EEINST_LIVE0>( reg, mask );
}
#define EEINST_REALXMM EEINST_XMM
//SLL, NULL, SRL, SRA, SLLV, NULL, SRLV, SRAV,
//JR, JALR, MOVZ, MOVN, SYSCALL, BREAK, NULL, SYNC,
//MFHI, MTHI, MFLO, MTLO, DSLLV, NULL, DSRLV, DSRAV,
//MULT, MULTU, DIV, DIVU, NULL, NULL, NULL, NULL,
//ADD, ADDU, SUB, SUBU, AND, OR, XOR, NOR,
//MFSA, MTSA, SLT, SLTU, DADD, DADDU, DSUB, DSUBU,
//TGE, TGEU, TLT, TLTU, TEQ, NULL, TNE, NULL,
//DSLL, NULL, DSRL, DSRA, DSLL32, NULL, DSRL32, DSRA32
__forceinline void BSCPropagate::rpropSPECIAL()
{
switch(_Funct_) {
case 0: // SLL
case 2: // SRL
case 3: // SRA
rpropSetWrite(_Rd_, EEINST_LIVE1);
rpropSetRead(_Rt_, 0);
break;
case 4: // sllv
case 6: // srlv
case 7: // srav
rpropSetWrite(_Rd_, EEINST_LIVE1);
rpropSetRead(_Rs_, 0);
rpropSetRead(_Rt_, 0);
break;
case 8: // JR
rpropSetRead(_Rs_, 0);
break;
case 9: // JALR
rpropSetWrite(_Rd_, EEINST_LIVE1);
rpropSetRead(_Rs_, 0);
break;
case 10: // movz
case 11: // movn
// do not write _Rd_!
rpropSetRead(_Rs_, EEINST_LIVE1);
rpropSetRead(_Rt_, EEINST_LIVE1);
rpropSetRead(_Rd_, EEINST_LIVE1);
_recFillRegister(pinst, XMMTYPE_GPRREG, _Rd_, 1);
break;
case 12: // syscall
case 13: // break
_recClearInst(&prev);
prev.info = 0;
break;
case 15: // sync
break;
case 16: // mfhi
rpropSetWrite(_Rd_, EEINST_LIVE1);
rpropSetRead(XMMGPR_HI, (pinst.regs[_Rd_]&EEINST_REALXMM)|EEINST_LIVE1);
break;
case 17: // mthi
rpropSetWrite(XMMGPR_HI, EEINST_LIVE1);
rpropSetRead(_Rs_, EEINST_LIVE1);
break;
case 18: // mflo
rpropSetWrite(_Rd_, EEINST_LIVE1);
rpropSetRead(XMMGPR_LO, (pinst.regs[_Rd_]&EEINST_REALXMM)|EEINST_LIVE1);
break;
case 19: // mtlo
rpropSetWrite(XMMGPR_LO, EEINST_LIVE1);
rpropSetRead(_Rs_, EEINST_LIVE1);
break;
case 20: // dsllv
case 22: // dsrlv
case 23: // dsrav
rpropSetWrite(_Rd_, EEINST_LIVE1);
rpropSetRead(_Rs_, 0);
rpropSetRead(_Rt_, EEINST_LIVE1);
break;
case 24: // mult
case 25: // multu
rpropSetWrite(XMMGPR_LO, EEINST_LIVE1);
rpropSetWrite(XMMGPR_HI, EEINST_LIVE1);
rpropSetWrite(_Rd_, EEINST_LIVE1);
rpropSetRead(_Rs_, EEINST_USED); //EEINST_MMX crashes on init, EEINST_XMM fails on Tales of Abyss, so EEINST_USED (rama)
rpropSetRead(_Rt_, EEINST_USED);
// did we ever try EEINST_LIVE1 or 0 in the place of EEINST_USED? I think of those might be more correct here (Air)
pinst.info |= EEINST_USED;
break;
case 26: // div
case 27: // divu
rpropSetWrite(XMMGPR_LO, EEINST_LIVE1);
rpropSetWrite(XMMGPR_HI, EEINST_LIVE1);
rpropSetRead(_Rs_, 0);
rpropSetRead(_Rt_, 0);
//pinst.info |= EEINST_REALXMM;
break;
case 32: // add
case 33: // addu
case 34: // sub
case 35: // subu
rpropSetWrite(_Rd_, EEINST_LIVE1);
if( _Rs_ ) rpropSetRead(_Rs_, EEINST_LIVE1);
if( _Rt_ ) rpropSetRead(_Rt_, EEINST_LIVE1);
break;
case 36: // and
case 37: // or
case 38: // xor
case 39: // nor
// if rd == rs or rt, keep live1
rpropSetWrite(_Rd_, EEINST_LIVE1);
rpropSetRead(_Rs_, (pinst.regs[_Rd_]&EEINST_LIVE1));
rpropSetRead(_Rt_, (pinst.regs[_Rd_]&EEINST_LIVE1));
break;
case 40: // mfsa
rpropSetWrite(_Rd_, EEINST_LIVE1);
break;
case 41: // mtsa
rpropSetRead(_Rs_, EEINST_LIVE1);
break;
case 42: // slt
rpropSetWrite(_Rd_, EEINST_LIVE1);
rpropSetRead(_Rs_, EEINST_LIVE1);
rpropSetRead(_Rt_, EEINST_LIVE1);
break;
case 43: // sltu
rpropSetWrite(_Rd_, EEINST_LIVE1);
rpropSetRead(_Rs_, EEINST_LIVE1);
rpropSetRead(_Rt_, EEINST_LIVE1);
break;
case 44: // dadd
case 45: // daddu
case 46: // dsub
case 47: // dsubu
rpropSetWrite(_Rd_, EEINST_LIVE1);
rpropSetRead(_Rs_, (pinst.regs[_Rd_]&EEINST_LIVE1));
rpropSetRead(_Rt_, (pinst.regs[_Rd_]&EEINST_LIVE1));
break;
// traps
case 48: case 49: case 50: case 51: case 52: case 54:
rpropSetRead(_Rs_, EEINST_LIVE1);
rpropSetRead(_Rt_, EEINST_LIVE1);
break;
case 56: // dsll
case 58: // dsrl
case 59: // dsra
case 62: // dsrl32
case 63: // dsra32
rpropSetWrite(_Rd_, EEINST_LIVE1);
rpropSetRead(_Rt_, EEINST_LIVE1);
break;
case 60: // dsll32
rpropSetWrite(_Rd_, EEINST_LIVE1);
rpropSetRead(_Rt_, 0);
break;
default:
rpropSetWrite(_Rd_, EEINST_LIVE1);
rpropSetRead(_Rs_, EEINST_LIVE1);
rpropSetRead(_Rt_, EEINST_LIVE1);
break;
}
}
//BLTZ, BGEZ, BLTZL, BGEZL, NULL, NULL, NULL, NULL,
//TGEI, TGEIU, TLTI, TLTIU, TEQI, NULL, TNEI, NULL,
//BLTZAL, BGEZAL, BLTZALL, BGEZALL, NULL, NULL, NULL, NULL,
//MTSAB, MTSAH, NULL, NULL, NULL, NULL, NULL, NULL,
__forceinline void BSCPropagate::rpropREGIMM()
{
switch(_Rt_) {
case 0: // bltz
case 1: // bgez
rpropSetRead(_Rs_, EEINST_LIVE1);
pinst.info |= EEINST_REALXMM;
break;
case 2: // bltzl
case 3: // bgezl
// reset since don't know which path to go
_recClearInst(&prev);
prev.info = 0;
rpropSetRead(_Rs_, EEINST_LIVE1);
pinst.info |= EEINST_REALXMM;
break;
// traps
case 8:
case 9:
case 10:
case 11:
case 12:
case 14:
rpropSetRead(_Rs_, EEINST_LIVE1);
break;
case 16: // bltzal
case 17: // bgezal
// do not write 31
rpropSetRead(_Rs_, EEINST_LIVE1);
break;
case 18: // bltzall
case 19: // bgezall
// reset since don't know which path to go
_recClearInst(&prev);
prev.info = 0;
// do not write 31
rpropSetRead(_Rs_, EEINST_LIVE1);
break;
case 24: // mtsab
case 25: // mtsah
rpropSetRead(_Rs_, 0);
break;
jNO_DEFAULT;
}
}
//MFC0, NULL, NULL, NULL, MTC0, NULL, NULL, NULL,
//COP0BC0, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
//COP0C0, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
//NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
__forceinline void BSCPropagate::rpropCP0()
{
switch(_Rs_) {
case 0: // mfc0
rpropSetWrite(_Rt_, EEINST_LIVE1|EEINST_REALXMM);
break;
case 4:
rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_REALXMM);
break;
case 8: // cop0bc0
_recClearInst(&prev);
prev.info = 0;
break;
case 16: // cop0c0
_recClearInst(&prev);
prev.info = 0;
break;
}
}
#define _Ft_ _Rt_
#define _Fs_ _Rd_
#define _Fd_ _Sa_
//ADD_S, SUB_S, MUL_S, DIV_S, SQRT_S, ABS_S, MOV_S, NEG_S,
//NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
//NULL, NULL, NULL, NULL, NULL, NULL, RSQRT_S, NULL,
//ADDA_S, SUBA_S, MULA_S, NULL, MADD_S, MSUB_S, MADDA_S, MSUBA_S,
//NULL, NULL, NULL, NULL, CVT_W, NULL, NULL, NULL,
//MAX_S, MIN_S, NULL, NULL, NULL, NULL, NULL, NULL,
//C_F, NULL, C_EQ, NULL, C_LT, NULL, C_LE, NULL,
//NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
__forceinline void BSCPropagate::rpropCP1()
{
switch(_Rs_) {
case 0: // mfc1
rpropSetWrite(_Rt_, EEINST_LIVE1|EEINST_REALXMM);
rpropSetFPURead(_Fs_, EEINST_REALXMM);
break;
case 2: // cfc1
rpropSetWrite(_Rt_, EEINST_LIVE1|EEINST_REALXMM);
break;
case 4: // mtc1
rpropSetFPUWrite(_Fs_, EEINST_REALXMM);
rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_REALXMM);
break;
case 6: // ctc1
rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_REALXMM);
break;
case 8: // bc1
// reset since don't know which path to go
_recClearInst(&prev);
prev.info = 0;
break;
case 16:
// floating point ops
pinst.info |= EEINST_REALXMM;
switch( _Funct_ ) {
case 0: // add.s
case 1: // sub.s
case 2: // mul.s
case 3: // div.s
case 22: // rsqrt.s
case 40: // max.s
case 41: // min.s
rpropSetFPUWrite(_Fd_, EEINST_REALXMM);
rpropSetFPURead(_Fs_, EEINST_REALXMM);
rpropSetFPURead(_Ft_, EEINST_REALXMM);
break;
case 4: // sqrt.s
rpropSetFPUWrite(_Fd_, EEINST_REALXMM);
rpropSetFPURead(_Ft_, EEINST_REALXMM);
break;
case 5: // abs.s
case 6: // mov.s
case 7: // neg.s
case 36: // cvt.w
rpropSetFPUWrite(_Fd_, EEINST_REALXMM);
rpropSetFPURead(_Fs_, EEINST_REALXMM);
break;
case 24: // adda.s
case 25: // suba.s
case 26: // mula.s
rpropSetFPUWrite(XMMFPU_ACC, EEINST_REALXMM);
rpropSetFPURead(_Fs_, EEINST_REALXMM);
rpropSetFPURead(_Ft_, EEINST_REALXMM);
break;
case 28: // madd.s
case 29: // msub.s
rpropSetFPUWrite(_Fd_, EEINST_REALXMM);
rpropSetFPURead(XMMFPU_ACC, EEINST_REALXMM);
rpropSetFPURead(_Fs_, EEINST_REALXMM);
rpropSetFPURead(_Ft_, EEINST_REALXMM);
break;
case 30: // madda.s
case 31: // msuba.s
rpropSetFPUWrite(XMMFPU_ACC, EEINST_REALXMM);
rpropSetFPURead(XMMFPU_ACC, EEINST_REALXMM);
rpropSetFPURead(_Fs_, EEINST_REALXMM);
rpropSetFPURead(_Ft_, EEINST_REALXMM);
break;
case 48: // c.f
case 50: // c.eq
case 52: // c.lt
case 54: // c.le
rpropSetFPURead(_Fs_, EEINST_REALXMM);
rpropSetFPURead(_Ft_, EEINST_REALXMM);
break;
default: assert(0);
}
break;
case 20:
pxAssert( _Funct_ == 32 ); // CVT.S.W
rpropSetFPUWrite(_Fd_, EEINST_REALXMM);
rpropSetFPURead(_Fs_, EEINST_REALXMM);
break;
jNO_DEFAULT;
}
}
#undef _Ft_
#undef _Fs_
#undef _Fd_
__forceinline void BSCPropagate::rpropCP2()
{
switch(_Rs_) {
case 1: // qmfc2
rpropSetWrite(_Rt_, EEINST_LIVE2|EEINST_LIVE1);
break;
case 2: // cfc2
rpropSetWrite(_Rt_, EEINST_LIVE1);
break;
case 5: // qmtc2
rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_LIVE2);
break;
case 6: // ctc2
rpropSetRead(_Rt_, 0);
break;
case 8: // bc2
break;
default:
// vu macro mode insts
pinst.info |= EEINSTINFO_COP2;
break;
}
}
//MADD, MADDU, NULL, NULL, PLZCW, NULL, NULL, NULL,
//MMI0, MMI2, NULL, NULL, NULL, NULL, NULL, NULL,
//MFHI1, MTHI1, MFLO1, MTLO1, NULL, NULL, NULL, NULL,
//MULT1, MULTU1, DIV1, DIVU1, NULL, NULL, NULL, NULL,
//MADD1, MADDU1, NULL, NULL, NULL, NULL, NULL, NULL,
//MMI1 , MMI3, NULL, NULL, NULL, NULL, NULL, NULL,
//PMFHL, PMTHL, NULL, NULL, PSLLH, NULL, PSRLH, PSRAH,
//NULL, NULL, NULL, NULL, PSLLW, NULL, PSRLW, PSRAW,
__forceinline void BSCPropagate::rpropMMI()
{
switch(cpuRegs.code&0x3f) {
case 0: // madd
case 1: // maddu
rpropSetLOHI<MODE_READ|MODE_WRITE, MODE_READ|MODE_WRITE>(_Rd_, _Rs_, _Rt_, EEINST_LIVE1);
break;
case 4: // plzcw
rpropSetFast(_Rd_, _Rs_, 0, EEINST_LIVE1);
break;
case 8: rpropMMI0(); break;
case 9: rpropMMI2(); break;
case 16: // mfhi1
{
rpropSetWrite(_Rd_, EEINST_LIVE1);
int temp = ((pinst.regs[_Rd_]&(EEINST_REALXMM))?0:EEINST_REALXMM);
rpropSetRead(XMMGPR_HI, temp|EEINST_LIVE2);
break;
}
case 17: // mthi1
rpropSetWrite0<0>(XMMGPR_HI, EEINST_LIVE2);
rpropSetRead(_Rs_, EEINST_LIVE1);
break;
case 18: // mflo1
{
rpropSetWrite(_Rd_, EEINST_LIVE1);
int temp = ((pinst.regs[_Rd_]&(EEINST_REALXMM))?0:EEINST_REALXMM);
rpropSetRead(XMMGPR_LO, temp|EEINST_LIVE2);
break;
}
case 19: // mtlo1
rpropSetWrite0<0>(XMMGPR_LO, EEINST_LIVE2);
rpropSetRead(_Rs_, EEINST_LIVE1);
break;
case 24: // mult1
{
rpropSetWrite0<0>(XMMGPR_LO, EEINST_LIVE2);
rpropSetWrite0<0>(XMMGPR_HI, EEINST_LIVE2);
rpropSetWrite(_Rd_, EEINST_LIVE1);
rpropSetRead(_Rs_, 0);
rpropSetRead(_Rt_, 0);
break;
}
case 25: // multu1
rpropSetWrite0<0>(XMMGPR_LO, EEINST_LIVE2);
rpropSetWrite0<0>(XMMGPR_HI, EEINST_LIVE2);
rpropSetWrite(_Rd_, EEINST_LIVE1);
rpropSetRead(_Rs_, 0);
rpropSetRead(_Rt_, 0);
break;
case 26: // div1
case 27: // divu1
rpropSetWrite0<0>(XMMGPR_LO, EEINST_LIVE2);
rpropSetWrite0<0>(XMMGPR_HI, EEINST_LIVE2);
rpropSetRead(_Rs_, 0);
rpropSetRead(_Rt_, 0);
//pinst.info |= EEINST_REALXMM;
break;
case 32: // madd1
case 33: // maddu1
rpropSetWrite0<0>(XMMGPR_LO, EEINST_LIVE2);
rpropSetWrite0<0>(XMMGPR_HI, EEINST_LIVE2);
rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE1);
rpropSetRead(XMMGPR_LO, EEINST_LIVE2);
rpropSetRead(XMMGPR_HI, EEINST_LIVE2);
break;
case 40: rpropMMI1(); break;
case 41: rpropMMI3(); break;
case 48: // pmfhl
rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1);
rpropSetRead(XMMGPR_LO, EEINST_LIVE2|EEINST_LIVE1|EEINST_REALXMM);
rpropSetRead(XMMGPR_HI, EEINST_LIVE2|EEINST_LIVE1|EEINST_REALXMM);
break;
case 49: // pmthl
rpropSetWrite(XMMGPR_LO, EEINST_LIVE2|EEINST_LIVE1);
rpropSetWrite(XMMGPR_HI, EEINST_LIVE2|EEINST_LIVE1);
rpropSetRead(_Rs_, EEINST_LIVE2|EEINST_LIVE1|EEINST_REALXMM);
break;
default:
rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE1|EEINST_LIVE2|EEINST_REALXMM);
break;
}
}
//recPADDW, PSUBW, PCGTW, PMAXW,
//PADDH, PSUBH, PCGTH, PMAXH,
//PADDB, PSUBB, PCGTB, NULL,
//NULL, NULL, NULL, NULL,
//PADDSW, PSUBSW, PEXTLW, PPACW,
//PADDSH, PSUBSH, PEXTLH, PPACH,
//PADDSB, PSUBSB, PEXTLB, PPACB,
//NULL, NULL, PEXT5, PPAC5,
__forceinline void BSCPropagate::rpropMMI0()
{
switch((cpuRegs.code>>6)&0x1f) {
case 16: // paddsw
case 17: // psubsw
rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE1|EEINST_LIVE2);
break;
case 18: // pextlw
case 22: // pextlh
case 26: // pextlb
rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1);
rpropSetRead(_Rs_, EEINST_LIVE1|EEINST_REALXMM);
rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_REALXMM);
break;
case 30: // pext5
case 31: // ppac5
rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE1|EEINST_LIVE2);
break;
default:
rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE1|EEINST_LIVE2|EEINST_REALXMM);
break;
}
}
__forceinline void BSCPropagate::rpropMMI1()
{
switch((cpuRegs.code>>6)&0x1f) {
case 1: // pabsw
case 5: // pabsh
rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1);
rpropSetRead(_Rt_, EEINST_LIVE2|EEINST_LIVE1|EEINST_REALXMM);
break;
case 17: // psubuw
rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE1|EEINST_LIVE2);
break;
case 18: // pextuw
case 22: // pextuh
case 26: // pextub
rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1);
rpropSetRead(_Rs_, EEINST_LIVE2|EEINST_REALXMM);
rpropSetRead(_Rt_, EEINST_LIVE2|EEINST_REALXMM);
break;
default:
rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE1|EEINST_LIVE2|EEINST_REALXMM);
break;
}
}
__forceinline void BSCPropagate::rpropMMI2()
{
switch((cpuRegs.code>>6)&0x1f) {
case 0: // pmaddw
case 4: // pmsubw
rpropSetLOHI<MODE_READ|MODE_WRITE, MODE_READ|MODE_WRITE>
(_Rd_, _Rs_, _Rt_, EEINST_LIVE2|EEINST_LIVE1);
break;
case 2: // psllvw
case 3: // psllvw
rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE2);
break;
case 8: // pmfhi
rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1);
rpropSetRead(XMMGPR_HI, EEINST_LIVE2|EEINST_LIVE1|EEINST_REALXMM);
break;
case 9: // pmflo
rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1);
rpropSetRead(XMMGPR_HI, EEINST_LIVE2|EEINST_LIVE1|EEINST_REALXMM);
break;
case 10: // pinth
rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1);
rpropSetRead(_Rs_, EEINST_LIVE2|EEINST_REALXMM);
rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_REALXMM);
break;
case 12: // pmultw,
rpropSetLOHI<MODE_WRITE, MODE_WRITE>
(_Rd_, _Rs_, _Rt_, EEINST_LIVE2|EEINST_LIVE1);
break;
case 13: // pdivw
rpropSetLOHI<MODE_WRITE, MODE_WRITE>
(0, _Rs_, _Rt_, EEINST_LIVE2|EEINST_LIVE1);
break;
case 14: // pcpyld
rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1);
rpropSetRead(_Rs_, EEINST_LIVE1|EEINST_REALXMM);
rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_REALXMM);
break;
case 16: // pmaddh
case 17: // phmadh
case 20: // pmsubh
case 21: // phmsbh
rpropSetLOHI<MODE_READ|MODE_WRITE, MODE_READ|MODE_WRITE>
(_Rd_, _Rs_, _Rt_, EEINST_LIVE2|EEINST_LIVE1|EEINST_REALXMM);
break;
case 26: // pexeh
case 27: // prevh
case 30: // pexew
case 31: // prot3w
rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1);
rpropSetRead(_Rt_, EEINST_LIVE2|EEINST_LIVE1|EEINST_REALXMM);
break;
case 28: // pmulth
rpropSetLOHI<MODE_WRITE, MODE_WRITE>
(_Rd_, _Rs_, _Rt_, EEINST_LIVE2|EEINST_LIVE1|EEINST_REALXMM);
break;
case 29: // pdivbw
rpropSetLOHI<MODE_WRITE, MODE_WRITE>
(_Rd_, _Rs_, _Rt_, EEINST_LIVE2|EEINST_LIVE1|EEINST_REALXMM);
break;
default:
rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE1|EEINST_LIVE2|EEINST_REALXMM);
break;
}
}
__forceinline void BSCPropagate::rpropMMI3()
{
switch((cpuRegs.code>>6)&0x1f) {
case 0: // pmadduw
rpropSetLOHI<MODE_READ|MODE_WRITE, MODE_READ|MODE_WRITE>
(_Rd_, _Rs_, _Rt_, EEINST_LIVE2|EEINST_LIVE1|EEINST_REALXMM );
break;
case 3: // psravw
rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE2);
break;
case 8: // pmthi
rpropSetWrite(XMMGPR_HI, EEINST_LIVE2|EEINST_LIVE1);
rpropSetRead(_Rs_, EEINST_LIVE2|EEINST_LIVE1|EEINST_REALXMM);
break;
case 9: // pmtlo
rpropSetWrite(XMMGPR_LO, EEINST_LIVE2|EEINST_LIVE1);
rpropSetRead(_Rs_, EEINST_LIVE2|EEINST_LIVE1|EEINST_REALXMM);
break;
case 12: // pmultuw,
rpropSetLOHI<MODE_WRITE, MODE_WRITE>
(_Rd_, _Rs_, _Rt_, EEINST_LIVE2|EEINST_LIVE1|EEINST_REALXMM);
break;
case 13: // pdivuw
rpropSetLOHI<MODE_WRITE, MODE_WRITE>
(0, _Rs_, _Rt_, EEINST_LIVE2|EEINST_LIVE1);
break;
case 14: // pcpyud
rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1);
rpropSetRead(_Rs_, EEINST_LIVE2|EEINST_REALXMM);
rpropSetRead(_Rt_, EEINST_LIVE2|EEINST_REALXMM);
break;
case 26: // pexch
case 27: // pcpyh
case 30: // pexcw
rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1);
rpropSetRead(_Rt_, EEINST_LIVE2|EEINST_LIVE1|EEINST_REALXMM);
break;
default:
rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE1|EEINST_LIVE2|EEINST_REALXMM);
break;
}
}
//SPECIAL, REGIMM, J, JAL, BEQ, BNE, BLEZ, BGTZ,
//ADDI, ADDIU, SLTI, SLTIU, ANDI, ORI, XORI, LUI,
//COP0, COP1, COP2, NULL, BEQL, BNEL, BLEZL, BGTZL,
//DADDI, DADDIU, LDL, LDR, MMI, NULL, LQ, SQ,
//LB, LH, LWL, LW, LBU, LHU, LWR, LWU,
//SB, SH, SWL, SW, SDL, SDR, SWR, CACHE,
//NULL, LWC1, NULL, PREF, NULL, NULL, LQC2, LD,
//NULL, SWC1, NULL, NULL, NULL, NULL, SQC2, SD
void BSCPropagate::rprop()
{
switch(cpuRegs.code >> 26) {
case 0: rpropSPECIAL(); break;
case 1: rpropREGIMM(); break;
case 2: // j
break;
case 3: // jal
rpropSetWrite(31, EEINST_LIVE1);
break;
case 4: // beq
case 5: // bne
rpropSetRead(_Rs_, EEINST_LIVE1);
rpropSetRead(_Rt_, EEINST_LIVE1);
pinst.info |= EEINST_REALXMM;
break;
case 20: // beql
case 21: // bnel
// reset since don't know which path to go
_recClearInst(&prev);
prev.info = 0;
rpropSetRead(_Rs_, EEINST_LIVE1);
rpropSetRead(_Rt_, EEINST_LIVE1);
pinst.info |= EEINST_REALXMM;
break;
case 6: // blez
case 7: // bgtz
rpropSetRead(_Rs_, EEINST_LIVE1);
break;
case 22: // blezl
case 23: // bgtzl
// reset since don't know which path to go
_recClearInst(&prev);
prev.info = 0;
rpropSetRead(_Rs_, EEINST_LIVE1);
break;
case 24: // daddi
case 25: // daddiu
rpropSetWrite(_Rt_, EEINST_LIVE1);
rpropSetRead(_Rs_, EEINST_LIVE1);
break;
case 8: // addi
case 9: // addiu
rpropSetWrite(_Rt_, EEINST_LIVE1);
rpropSetRead(_Rs_, EEINST_LIVE1);
break;
case 10: // slti
rpropSetWrite(_Rt_, EEINST_LIVE1);
rpropSetRead(_Rs_, EEINST_LIVE1);
break;
case 11: // sltiu
rpropSetWrite(_Rt_, EEINST_LIVE1);
rpropSetRead(_Rs_, EEINST_LIVE1);
break;
case 12: // andi
rpropSetWrite(_Rt_, EEINST_LIVE1);
rpropSetRead(_Rs_, 0);
break;
case 13: // ori
rpropSetWrite(_Rt_, EEINST_LIVE1);
rpropSetRead(_Rs_, EEINST_LIVE1);
break;
case 14: // xori
rpropSetWrite(_Rt_, EEINST_LIVE1);
rpropSetRead(_Rs_, EEINST_LIVE1);
break;
case 15: // lui
rpropSetWrite(_Rt_, EEINST_LIVE1);
break;
case 16: rpropCP0(); break;
case 17: rpropCP1(); break;
case 18: rpropCP2(); break;
// loads
case 34: // lwl
case 38: // lwr
case 26: // ldl
case 27: // ldr
rpropSetWrite(_Rt_, EEINST_LIVE1);
rpropSetRead(_Rt_, EEINST_LIVE1);
rpropSetRead(_Rs_, 0);
break;
case 32: case 33: case 35: case 36: case 37: case 39:
case 55: // LD
rpropSetWrite(_Rt_, EEINST_LIVE1);
rpropSetRead(_Rs_, 0);
break;
case 28: rpropMMI(); break;
case 30: // lq
rpropSetWrite(_Rt_, EEINST_LIVE1|EEINST_LIVE2);
rpropSetRead(_Rs_, 0);
pinst.info |= EEINST_REALXMM;
break;
case 31: // sq
rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_LIVE2|EEINST_REALXMM);
rpropSetRead(_Rs_, 0);
pinst.info |= EEINST_REALXMM;
break;
// 4 byte stores
case 40: case 41: case 42: case 43: case 46:
rpropSetRead(_Rt_, 0);
rpropSetRead(_Rs_, 0);
pinst.info |= EEINST_REALXMM;
break;
case 44: // sdl
case 45: // sdr
case 63: // sd
rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_REALXMM);
rpropSetRead(_Rs_, 0);
break;
case 49: // lwc1
rpropSetFPUWrite(_Rt_, EEINST_REALXMM);
rpropSetRead(_Rs_, 0);
break;
case 57: // swc1
rpropSetFPURead(_Rt_, EEINST_REALXMM);
rpropSetRead(_Rs_, 0);
break;
case 54: // lqc2
case 62: // sqc2
rpropSetRead(_Rs_, 0);
break;
default:
rpropSetWrite(_Rt_, EEINST_LIVE1);
rpropSetRead(_Rs_, EEINST_LIVE1);
break;
}
} // End namespace OpcodeImpl

View File

@ -500,7 +500,7 @@ int _getFreeMMXreg()
for (i=0; i<iREGCNT_MMX; i++) {
if (mmxregs[i].needed) continue;
if (MMX_ISGPR(mmxregs[i].reg)) {
if( !(g_pCurInstInfo->regs[mmxregs[i].reg-MMX_GPR] & (EEINST_LIVE0|EEINST_LIVE1)) ) {
if( !(g_pCurInstInfo->regs[mmxregs[i].reg-MMX_GPR] & (EEINST_LIVE0)) ) {
_freeMMXreg(i);
return i;
}
@ -881,11 +881,6 @@ int _signExtendMtoMMX(x86MMXRegType to, u32 mem)
int _signExtendGPRMMXtoMMX(x86MMXRegType to, u32 gprreg, x86MMXRegType from, u32 gprfromreg)
{
pxAssert( to >= 0 && from >= 0 );
if( !EEINST_ISLIVE1(gprreg) ) {
EEINST_RESETHASLIVE1(gprreg);
if( to != from ) MOVQRtoR(to, from);
return to;
}
if( to == from ) return _signExtendGPRtoMMX(to, gprreg, 0);
if( !(g_pCurInstInfo->regs[gprfromreg]&EEINST_LASTUSE) ) {
@ -910,11 +905,6 @@ int _signExtendGPRMMXtoMMX(x86MMXRegType to, u32 gprreg, x86MMXRegType from, u32
int _signExtendGPRtoMMX(x86MMXRegType to, u32 gprreg, int shift)
{
pxAssert( to >= 0 && shift >= 0 );
if( !EEINST_ISLIVE1(gprreg) ) {
if( shift > 0 ) PSRADItoR(to, shift);
EEINST_RESETHASLIVE1(gprreg);
return to;
}
SetMMXstate();

View File

@ -77,7 +77,7 @@ static bool s_nBlockFF;
// save states for branches
GPR_reg64 s_saveConstRegs[32];
static u16 s_savex86FpuState;
static u32 s_saveHasConstReg = 0, s_saveFlushedConstReg = 0, s_saveRegHasLive1 = 0;
static u32 s_saveHasConstReg = 0, s_saveFlushedConstReg = 0;
static EEINST* s_psaveInstInfo = NULL;
static u32 s_savenBlockCycles = 0;
@ -293,6 +293,35 @@ u32* recGetImm64(u32 hi, u32 lo)
return imm64;
}
// Use this to call into interpreter functions that require an immediate branchtest
// to be done afterward (anything that throws an exception or enables interrupts, etc).
void recBranchCall( void (*func)() )
{
// In order to make sure a branch test is performed, the nextBranchCycle is set
// to the current cpu cycle.
MOV32ItoM( (uptr)&cpuRegs.code, cpuRegs.code );
MOV32MtoR( EAX, (uptr)&cpuRegs.cycle );
MOV32ItoM( (uptr)&cpuRegs.pc, pc );
MOV32RtoM( (uptr)&g_nextBranchCycle, EAX );
// Might as well flush everything -- it'll all get flushed when the
// recompiler inserts the branchtest anyway.
iFlushCall(FLUSH_EVERYTHING);
CALLFunc( (uptr)func );
branch = 2;
}
void recCall( void (*func)(), int delreg )
{
MOV32ItoM( (uptr)&cpuRegs.code, cpuRegs.code );
MOV32ItoM( (uptr)&cpuRegs.pc, pc );
iFlushCall(FLUSH_EVERYTHING);
if( delreg > 0 ) _deleteEEreg(delreg, 0);
CALLFunc( (uptr)func );
}
// =====================================================================================================
// R5900 Dispatchers
// =====================================================================================================
@ -961,7 +990,6 @@ void SaveBranchState()
s_saveHasConstReg = g_cpuHasConstReg;
s_saveFlushedConstReg = g_cpuFlushedConstReg;
s_psaveInstInfo = g_pCurInstInfo;
s_saveRegHasLive1 = g_cpuRegHasLive1;
// save all mmx regs
memcpy_const(s_saveMMXregs, mmxregs, sizeof(mmxregs));
@ -977,7 +1005,6 @@ void LoadBranchState()
g_cpuHasConstReg = s_saveHasConstReg;
g_cpuFlushedConstReg = s_saveFlushedConstReg;
g_pCurInstInfo = s_psaveInstInfo;
g_cpuRegHasLive1 = g_cpuPrevRegHasLive1 = s_saveRegHasLive1;
// restore all mmx regs
memcpy_const(mmxregs, s_saveMMXregs, sizeof(mmxregs));
@ -1363,7 +1390,6 @@ static void __fastcall recRecompile( const u32 startpc )
pc = startpc;
x86FpuState = FPU_STATE;
g_cpuHasConstReg = g_cpuFlushedConstReg = 1;
g_cpuPrevRegHasLive1 = g_cpuRegHasLive1 = 0xffffffff;
pxAssume( g_cpuConstRegs[0].UD[0] == 0 );
_initX86regs();
@ -1491,11 +1517,6 @@ StartRecomp:
for(i = s_nEndBlock; i > startpc; i -= 4 ) {
cpuRegs.code = *(int *)PSM(i-4);
pcur[-1] = pcur[0];
// Backward propagation entry point. Since it doesn't work right it's disabled for now
//BSCPropagate bsc( pcur[-1], pcur[0] );
//bsc.rprop();
pcur--;
}
}

View File

@ -20,6 +20,7 @@
#include "R5900OpcodeTables.h"
#include "iR5900.h"
using namespace x86Emitter;
namespace R5900 {
namespace Dynarec {
@ -31,8 +32,7 @@ namespace OpcodeImpl
* 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)
// TODO: overflow checks
#ifndef ARITHMETIC_RECOMPILE
@ -65,61 +65,15 @@ void recADD_constv(int info, int creg, int vreg)
{
pxAssert( !(info&PROCESS_EE_XMM) );
// Fixme: MMX problem
if(0/*!g_cpuConstRegs[ creg ].UL[0]*/) {
int mmreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE);
SetMMXstate();
s32 cval = g_cpuConstRegs[creg].SL[0];
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 ) {
if( EEINST_ISLIVE1(_Rd_) )
{
// must perform the ADD unconditionally, to maintain flags status:
ADD32ItoM((int)&cpuRegs.GPR.r[_Rd_].UL[ 0 ], g_cpuConstRegs[creg].UL[0]);
_signExtendSFtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ]);
}
else
{
if( g_cpuConstRegs[creg].UL[0] )
ADD32ItoM((int)&cpuRegs.GPR.r[_Rd_].UL[ 0 ], g_cpuConstRegs[creg].UL[0]);
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 );
}
}
}
xMOV(eax, ptr32[&cpuRegs.GPR.r[vreg].SL[0]]);
if (cval)
xADD(eax, cval);
if (_Rd_ != vreg || cval)
xMOV(ptr32[&cpuRegs.GPR.r[_Rd_].SL[0]], eax);
xCDQ();
xMOV(ptr32[&cpuRegs.GPR.r[_Rd_].SL[1]], edx);
}
// s is constant
@ -146,33 +100,24 @@ void recADD_(int info)
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_);
_signExtendSFtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ]);
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_);
_signExtendSFtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ]);
}
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 );
}
CDQ( );
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX );
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX );
}
}
@ -198,45 +143,26 @@ void recDADD_constv(int info, int creg, int vreg)
if(0/* 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_);
}
MOVQMtoR(mmreg, (int)&cpuRegs.GPR.r[ vreg ].UL[ 0 ]);
}
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 ] );
}
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 ] );
return;
}
MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ vreg ].UL[ 0 ] );
if( EEINST_ISLIVE1(_Rd_) )
MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ vreg ].UL[ 1 ] );
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 ] );
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_);
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX );
}
}
@ -257,27 +183,17 @@ void recDADD_(int info)
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 ] );
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_);
ADC32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX);
}
else {
MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] );
if( EEINST_ISLIVE1(_Rd_) )
MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] );
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 ] );
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_);
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX );
}
}
@ -304,8 +220,7 @@ void recSUB_consts(int info)
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_);
_signExtendSFtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ]);
}
else {
if( g_cpuConstRegs[ _Rs_ ].UL[ 0 ] ) {
@ -317,15 +232,9 @@ void recSUB_consts(int info)
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 );
}
CDQ( );
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX );
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX );
}
}
@ -333,54 +242,21 @@ void recSUB_constt(int info)
{
pxAssert( !(info&PROCESS_EE_XMM) );
// Fixme: MMX problem
if(0/*!g_cpuConstRegs[_Rt_].UL[0]*/) {
int mmreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE);
SetMMXstate();
if( _Rd_ == _Rs_ ) {
if( g_cpuConstRegs[ _Rt_ ].UL[ 0 ] ) {
SUB32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], g_cpuConstRegs[ _Rt_ ].UL[ 0 ]);
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_);
}
}
_signExtendSFtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ]);
}
}
else {
if( _Rd_ == _Rs_ ) {
if( g_cpuConstRegs[ _Rt_ ].UL[ 0 ] ) {
SUB32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], g_cpuConstRegs[ _Rt_ ].UL[ 0 ]);
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_) ) _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 );
}
}
CDQ( );
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX );
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX );
}
}
@ -388,27 +264,12 @@ void recSUB_(int info)
{
pxAssert( !(info&PROCESS_EE_XMM) );
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 );
}
CDQ( );
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX );
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX );
}
EERECOMPILE_CODE0(SUB, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED);
@ -431,54 +292,33 @@ void recDSUB_consts(int info)
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 ] );
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_);
SBB32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] );
}
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 ]);
}
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);
return;
}
MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] );
if( EEINST_ISLIVE1(_Rd_) )
MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] );
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_);
}
ADC32ItoR(EDX, 0);
NEG32R(EDX);
}
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_);
}
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX );
}
void recDSUB_constt(int info)
@ -486,31 +326,20 @@ void recDSUB_constt(int info)
pxAssert( !(info&PROCESS_EE_XMM) );
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 ] );
}
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 {
MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] );
if( EEINST_ISLIVE1(_Rd_) )
MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] );
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 ] );
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_);
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX );
}
}
@ -520,26 +349,17 @@ void recDSUB_(int info)
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 ] );
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_);
SBB32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX );
}
else {
MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] );
if( EEINST_ISLIVE1(_Rd_) )
MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] );
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 ] );
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_);
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX );
}
}
@ -566,32 +386,20 @@ void recAND_constv(int info, int creg, int vreg)
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_);
if( g_cpuConstRegs[creg].UL[1] != 0xffffffff ) AND32ItoM((int)&cpuRegs.GPR.r[ vreg ].UL[1], g_cpuConstRegs[creg].UL[1]);
}
else {
MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ vreg ]);
if( EEINST_ISLIVE1(_Rd_) )
MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ vreg ] + 4 );
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]);
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_);
MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ]+4, ECX);
}
}
else {
MOV32ItoM((int)&cpuRegs.GPR.r[ _Rd_ ], 0);
if( EEINST_ISLIVE1(_Rd_) )
MOV32ItoM((int)&cpuRegs.GPR.r[ _Rd_ ]+4, 0);
else
EEINST_RESETHASLIVE1(_Rd_);
MOV32ItoM((int)&cpuRegs.GPR.r[ _Rd_ ]+4, 0);
}
}
@ -612,38 +420,28 @@ void recLogicalOp(int info, int op)
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 );
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 );
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);
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 );
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 );
LogicalOp32MtoR(ECX, (int)&cpuRegs.GPR.r[ _Rt_ ] + 4, op );
if( op == 3 ) {
NOT32R(EAX);
if( EEINST_ISLIVE1(_Rd_) )
NOT32R(ECX);
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_);
MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ]+4, ECX);
}
}
@ -678,25 +476,17 @@ void recOR_constv(int info, int creg, int vreg)
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_);
if( g_cpuConstRegs[creg].UL[1] ) OR32ItoM((int)&cpuRegs.GPR.r[ vreg ].UL[1], g_cpuConstRegs[creg].UL[1]);
}
else {
MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ vreg ]);
if( EEINST_ISLIVE1(_Rd_) )
MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ vreg ] + 4 );
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]);
if( g_cpuConstRegs[ creg ].UL[1] ) 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_);
MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ]+4, ECX);
}
}
}
@ -741,25 +531,17 @@ void recXOR_constv(int info, int creg, int vreg)
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_);
if( g_cpuConstRegs[creg].UL[1] ) XOR32ItoM((int)&cpuRegs.GPR.r[ vreg ].UL[1], g_cpuConstRegs[creg].UL[1]);
}
else {
MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ vreg ]);
if( EEINST_ISLIVE1(_Rd_) )
MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ vreg ] + 4 );
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]);
if( g_cpuConstRegs[ creg ].UL[1] ) 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_);
MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ]+4, ECX);
}
}
}
@ -810,29 +592,20 @@ void recNOR_constv(int info, int creg, int vreg)
else {
if( _Rd_ == vreg ) {
NOT32M((int)&cpuRegs.GPR.r[ vreg ].UL[0]);
if( EEINST_ISLIVE1(_Rd_) ) NOT32M((int)&cpuRegs.GPR.r[ vreg ].UL[1]);
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_);
if( g_cpuConstRegs[creg].UL[1] ) AND32ItoM((int)&cpuRegs.GPR.r[ vreg ].UL[1], ~g_cpuConstRegs[creg].UL[1]);
}
else {
MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ vreg ]);
if( EEINST_ISLIVE1(_Rd_) )
MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ vreg ] + 4 );
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]);
if( g_cpuConstRegs[ creg ].UL[1] ) OR32ItoR(ECX, g_cpuConstRegs[ creg ].UL[1]);
NOT32R(EAX);
if( EEINST_ISLIVE1(_Rd_) )
NOT32R(ECX);
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_);
MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ]+4, ECX);
}
}
}
@ -890,9 +663,7 @@ void recSLTs_consts(int info, int sign)
x86SetJ8(j8Ptr[1]);
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_);
MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], 0 );
}
// SLT with one operand coming from mem (compares only low 32 bits)
@ -976,9 +747,7 @@ void recSLTs_constt(int info, int sign)
x86SetJ8(j8Ptr[1]);
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_);
MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], 0 );
}
void recSLTs_(int info, int sign)
@ -1008,8 +777,7 @@ void recSLTs_(int info, int sign)
x86SetJ8(j8Ptr[1]);
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_);
MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], 0 );
}
void recSLT_consts(int info)

View File

@ -58,32 +58,18 @@ void recADDI_(int info)
pxAssert( !(info&PROCESS_EE_XMM) );
if ( _Rt_ == _Rs_ ) {
if ( EEINST_ISLIVE1(_Rt_) )
{
// must perform the ADD unconditionally, to maintain flags status:
ADD32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], _Imm_);
_signExtendSFtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ]);
}
else
{
if( _Imm_ ) ADD32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], _Imm_);
EEINST_RESETHASLIVE1(_Rt_);
}
// must perform the ADD unconditionally, to maintain flags status:
ADD32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], _Imm_);
_signExtendSFtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ]);
}
else {
MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] );
if ( _Imm_ != 0 ) ADD32ItoR( EAX, _Imm_ );
if ( EEINST_ISLIVE1(_Rt_) ) {
CDQ( );
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX );
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX );
}
else {
EEINST_RESETHASLIVE1(_Rt_);
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX );
}
CDQ( );
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX );
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX );
}
}
@ -112,24 +98,17 @@ void recDADDI_(int info)
else {
MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] );
if( EEINST_ISLIVE1(_Rt_) )
MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] );
MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] );
if ( _Imm_ != 0 )
{
ADD32ItoR( EAX, _Imm_ );
if( EEINST_ISLIVE1(_Rt_) ) {
ADC32ItoR( EDX, _Imm_ < 0?0xffffffff:0);
}
ADC32ItoR( EDX, _Imm_ < 0?0xffffffff:0);
}
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX );
if( EEINST_ISLIVE1(_Rt_) )
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX );
else
EEINST_RESETHASLIVE1(_Rt_);
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX );
}
}
@ -168,8 +147,7 @@ void recSLTIU_(int info)
x86SetJ8(j8Ptr[1]);
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX );
if( EEINST_ISLIVE1(_Rt_) ) MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 );
else EEINST_RESETHASLIVE1(_Rt_);
MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 );
}
EERECOMPILE_CODEX(eeRecompileCode1, SLTIU);
@ -199,8 +177,7 @@ void recSLTI_(int info)
x86SetJ8(j8Ptr[1]);
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX );
if( EEINST_ISLIVE1(_Rt_) ) MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 );
else EEINST_RESETHASLIVE1(_Rt_);
MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 );
}
EERECOMPILE_CODEX(eeRecompileCode1, SLTI);
@ -220,38 +197,32 @@ void recLogicalOpI(int info, int op)
}
else {
MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] );
if( op != 0 && EEINST_ISLIVE1(_Rt_) )
if( op != 0 )
MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] );
LogicalOp32ItoR( EAX, _ImmU_, op);
if( op != 0 && EEINST_ISLIVE1(_Rt_) )
if( op != 0 )
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX );
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX );
}
if( op == 0 ) {
if( EEINST_ISLIVE1(_Rt_ ) ) MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 );
else EEINST_RESETHASLIVE1(_Rt_);
MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 );
}
}
else
{
if( op == 0 ) {
MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], 0 );
if( EEINST_ISLIVE1(_Rt_ ) )
MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 );
MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 );
}
else {
if( _Rt_ != _Rs_ ) {
MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] );
if( EEINST_ISLIVE1(_Rt_ ) )
MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] );
MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] );
MOV32RtoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX );
if( EEINST_ISLIVE1(_Rt_ ) )
MOV32RtoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX );
MOV32RtoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX );
}
}
if( !EEINST_ISLIVE1(_Rt_) ) EEINST_RESETHASLIVE1(_Rt_);
}
}

View File

@ -165,13 +165,9 @@ void recMFHILO(int hi)
else {
_deleteEEreg(_Rd_, 0);
MOV32MtoR( EAX, hi ? (int)&cpuRegs.HI.UL[ 0 ] : (int)&cpuRegs.LO.UL[ 0 ]);
if( EEINST_ISLIVE1(_Rd_) )
MOV32MtoR( EDX, hi ? (int)&cpuRegs.HI.UL[ 1 ] : (int)&cpuRegs.LO.UL[ 1 ]);
MOV32MtoR( EDX, hi ? (int)&cpuRegs.HI.UL[ 1 ] : (int)&cpuRegs.LO.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_);
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX );
}
}
}

View File

@ -99,13 +99,9 @@ void recWritebackHILO(int info, int writed, int upper)
if( regd < 0 ) {
_deleteEEreg(_Rd_, 0);
if( EEINST_ISLIVE1(_Rd_) && !savedlo ) CDQ();
if( !savedlo ) CDQ();
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_);
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX );
}
}

View File

@ -69,15 +69,9 @@ void recSLLs_(int info, int sa)
SHL32ItoR( EAX, sa );
}
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 );
}
CDQ( );
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX );
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX );
}
void recSLL_(int info)
@ -100,15 +94,9 @@ void recSRLs_(int info, int sa)
MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] );
if ( sa != 0 ) SHR32ItoR( EAX, sa);
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 );
}
CDQ( );
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX );
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX );
}
void recSRL_(int info)
@ -131,15 +119,9 @@ void recSRAs_(int info, int sa)
MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] );
if ( sa != 0 ) SAR32ItoR( EAX, sa);
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 );
}
CDQ();
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX );
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX );
}
void recSRA_(int info)
@ -224,12 +206,6 @@ void recDSRAs_(int info, int sa)
if( rtreg != rdreg ) MOVQRtoR(rdreg, rtreg);
if( !EEINST_ISLIVE1(_Rd_) ) {
EEINST_RESETHASLIVE1(_Rd_);
PSRLQItoR(rdreg, sa);
return;
}
if ( sa != 0 ) {
t0reg = _allocMMXreg(-1, MMX_TEMP, 0);
MOVQRtoR(t0reg, rtreg);
@ -294,8 +270,7 @@ void recDSRL32s_(int info, int sa)
if ( sa != 0 ) SHR32ItoR( EAX, sa );
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_);
MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], 0 );
}
void recDSRL32_(int info)
@ -320,8 +295,7 @@ void recDSRA32s_(int info, int sa)
if ( sa != 0 ) SAR32ItoR( EAX, sa );
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_);
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX );
}
@ -376,15 +350,9 @@ void recSetConstShiftV(int info, int* rsreg, int* rdreg, int* rstemp, int shift6
void recMoveSignToRd(int info)
{
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 );
}
CDQ();
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX );
MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX );
}
//// SLLV

View File

@ -34,16 +34,9 @@
// Code Templates //
////////////////////
void _eeProcessHasLive(int reg, int signext)
{
g_cpuPrevRegHasLive1 = g_cpuRegHasLive1;
g_cpuRegHasLive1 |= 1<<reg;
}
void _eeOnWriteReg(int reg, int signext)
{
GPR_DEL_CONST(reg);
_eeProcessHasLive(reg, signext);
}
void _deleteEEreg(int reg, int flush)
@ -82,10 +75,6 @@ void eeRecompileCode0(R5900FNPTR constcode, R5900FNPTR_INFO constscode, R5900FNP
if ( ! _Rd_ && (xmminfo&XMMINFO_WRITED) ) return;
if( xmminfo&XMMINFO_WRITED) {
_eeProcessHasLive(_Rd_, 0);
}
if( GPR_IS_CONST2(_Rs_, _Rt_) ) {
if( xmminfo & XMMINFO_WRITED ) {
_deleteMMXreg(MMX_GPR+_Rd_, 2);
@ -263,8 +252,6 @@ void eeRecompileCode1(R5900FNPTR constcode, R5900FNPTR_INFO noconstcode)
int mmreg1, mmreg2;
if ( ! _Rt_ ) return;
_eeProcessHasLive(_Rt_, 0);
if( GPR_IS_CONST1(_Rs_) ) {
_deleteMMXreg(MMX_GPR+_Rt_, 2);
_deleteGPRtoXMMreg(_Rt_, 2);
@ -324,8 +311,6 @@ void eeRecompileCode2(R5900FNPTR constcode, R5900FNPTR_INFO noconstcode)
int mmreg1, mmreg2;
if ( ! _Rd_ ) return;
_eeProcessHasLive(_Rd_, 0);
if( GPR_IS_CONST1(_Rt_) ) {
_deleteMMXreg(MMX_GPR+_Rd_, 2);
_deleteGPRtoXMMreg(_Rd_, 2);
@ -525,11 +510,6 @@ int eeRecompileCodeXMM(int xmminfo)
{
int info = PROCESS_EE_XMM;
// save state
if( xmminfo & XMMINFO_WRITED ) {
_eeProcessHasLive(_Rd_, 0);
}
// flush consts
if( xmminfo & XMMINFO_READT ) {
if( GPR_IS_CONST1( _Rt_ ) && !(g_cpuFlushedConstReg&(1<<_Rt_)) ) {