mirror of https://github.com/PCSX2/pcsx2.git
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:
parent
d8ef7a4171
commit
d846c8709f
|
@ -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);
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
|
|
|
@ -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];
|
||||
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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_);
|
||||
}
|
||||
|
|
|
@ -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__
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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--;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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_);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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_)) ) {
|
||||
|
|
Loading…
Reference in New Issue