/*  Pcsx2 - Pc Ps2 Emulator
 *  Copyright (C) 2002-2005  Pcsx2 Team
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

// Holds instruction tables for the r5900 recompiler

// stop compiling if NORECBUILD build (only for Visual Studio)
#if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD))

#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <malloc.h>

#include "Common.h"
#include "Memory.h"
#include "InterTables.h"
#include "ix86/ix86.h"
#include "iR5900.h"
#include "iR5900AritImm.h"
#include "iR5900Arit.h"
#include "iR5900MultDiv.h"
#include "iR5900Shift.h"
#include "iR5900Branch.h"
#include "iR5900Jump.h"
#include "iR5900LoadStore.h"
#include "iR5900Move.h"
#include "iMMI.h"
#include "iFPU.h"
#include "iCP0.h"

////////////////////////////////////////////////////
static void recNULL( void ) 
{
	SysPrintf("EE: Unimplemented op %x\n", cpuRegs.code);
}

////////////////////////////////////////////////////
static void recREGIMM( void ) 
{
	recREG[ _Rt_ ]( );
}

////////////////////////////////////////////////////
static void recSPECIAL( void )
{
	recSPC[ _Funct_ ]( );
}

////////////////////////////////////////////////////
static void recCOP0( void )
{
	recCP0[ _Rs_ ]( );
}

////////////////////////////////////////////////////
static void recCOP0BC0( void )
{
	recCP0BC0[ ( cpuRegs.code >> 16 ) & 0x03 ]( );
}

////////////////////////////////////////////////////
static void recCOP0C0( void ) 
{
	recCP0C0[ _Funct_ ]( );
}

////////////////////////////////////////////////////
static void recCOP1( void ) {
	recCP1[ _Rs_ ]( );
}

////////////////////////////////////////////////////
static void recMMI( void ) 
{
	recMMIt[ _Funct_ ]( );
}


/**********************************************************
*    UNHANDLED YET OPCODES
*
**********************************************************/

////////////////////////////////////////////////////
//REC_SYS(PREF);
////////////////////////////////////////////////////
//REC_SYS(MFSA);
////////////////////////////////////////////////////
//REC_SYS(MTSA);
////////////////////////////////////////////////////
REC_SYS(TGE);
////////////////////////////////////////////////////
REC_SYS(TGEU);
////////////////////////////////////////////////////
REC_SYS(TLT);
////////////////////////////////////////////////////
REC_SYS(TLTU);
////////////////////////////////////////////////////
REC_SYS(TEQ);
////////////////////////////////////////////////////
REC_SYS(TNE);
////////////////////////////////////////////////////
REC_SYS(TGEI);
////////////////////////////////////////////////////
REC_SYS(TGEIU);
////////////////////////////////////////////////////
REC_SYS(TLTI);
////////////////////////////////////////////////////
REC_SYS(TLTIU);
////////////////////////////////////////////////////
REC_SYS(TEQI);
////////////////////////////////////////////////////
REC_SYS(TNEI);
////////////////////////////////////////////////////
//REC_SYS(MTSAB);
////////////////////////////////////////////////////
//REC_SYS(MTSAH);
////////////////////////////////////////////////////
REC_SYS(CACHE);

/*
void recTGE( void ) 
{
}

void recTGEU( void ) 
{
}

void recTLT( void ) 
{
}

void recTLTU( void ) 
{
}

void recTEQ( void ) 
{
}

void recTNE( void ) 
{
}

void recTGEI( void )
{
}

void recTGEIU( void ) 
{
}

void recTLTI( void ) 
{
}

void recTLTIU( void ) 
{
}

void recTEQI( void ) 
{
}

void recTNEI( void ) 
{
}

*/

/////////////////////////////////
// Foward-Prob Function Tables //
/////////////////////////////////
extern void recCOP2( void );
extern void recSYSCALL( void );
extern void recBREAK( void );
extern void recPREF( void );
extern void recSYNC( void );
extern void recMFSA( void );
extern void recMTSA( void );
extern void recMTSAB( void );
extern void recMTSAH( void );

void (*recBSC[64] )() = {
    recSPECIAL, recREGIMM, recJ,    recJAL,   recBEQ,  recBNE,  recBLEZ,  recBGTZ,
    recADDI,    recADDIU,  recSLTI, recSLTIU, recANDI, recORI,  recXORI,  recLUI,
    recCOP0,    recCOP1,   recCOP2, recNULL,  recBEQL, recBNEL, recBLEZL, recBGTZL,
    recDADDI,   recDADDIU, recLDL,  recLDR,   recMMI,  recNULL, recLQ,    recSQ,
    recLB,      recLH,     recLWL,  recLW,    recLBU,  recLHU,  recLWR,   recLWU,
    recSB,      recSH,     recSWL,  recSW,    recSDL,  recSDR,  recSWR,   recCACHE,
    recNULL,    recLWC1,   recNULL, recPREF,  recNULL, recNULL, recLQC2,  recLD,
    recNULL,    recSWC1,   recNULL, recNULL,  recNULL, recNULL, recSQC2,  recSD
};

#ifdef PCSX2_VIRTUAL_MEM
// coissued insts
void (*recBSC_co[64] )() = {
    recNULL,	recNULL,   recNULL, recNULL,  recNULL, recNULL, recNULL,  recNULL,
    recNULL,	recNULL,   recNULL, recNULL,  recNULL, recNULL, recNULL,  recNULL,
    recNULL,	recNULL,   recNULL, recNULL,  recNULL, recNULL, recNULL,  recNULL,
    recNULL,    recNULL,   recLDL_co,  recLDR_co,   recNULL, recNULL, recLQ_co,    recSQ_co,
    recLB_co,      recLH_co,     recLWL_co,  recLW_co,    recLBU_co,  recLHU_co,  recLWR_co,   recLWU_co,
    recSB_co,      recSH_co,     recSWL_co,  recSW_co,    recSDL_co,  recSDR_co,  recSWR_co,   recNULL,
    recNULL,    recLWC1_co,   recNULL, recNULL,  recNULL, recNULL, recLQC2_co,  recLD_co,
    recNULL,    recSWC1_co,   recNULL, recNULL,  recNULL, recNULL, recSQC2_co,  recSD_co
};
#endif

void (*recSPC[64] )() = {
    recSLL,  recNULL,  recSRL,  recSRA,  recSLLV,    recNULL,  recSRLV,   recSRAV,
    recJR,   recJALR,  recMOVZ, recMOVN, recSYSCALL, recBREAK, recNULL,   recSYNC,
    recMFHI, recMTHI,  recMFLO, recMTLO, recDSLLV,   recNULL,  recDSRLV,  recDSRAV,
    recMULT, recMULTU, recDIV,  recDIVU, recNULL,    recNULL,  recNULL,   recNULL,
    recADD,  recADDU,  recSUB,  recSUBU, recAND,     recOR,    recXOR,    recNOR,
    recMFSA, recMTSA,  recSLT,  recSLTU, recDADD,    recDADDU, recDSUB,   recDSUBU,
    recTGE,  recTGEU,  recTLT,  recTLTU, recTEQ,     recNULL,  recTNE,    recNULL,
    recDSLL, recNULL,  recDSRL, recDSRA, recDSLL32,  recNULL,  recDSRL32, recDSRA32
};

void (*recREG[32] )() = {
    recBLTZ,   recBGEZ,   recBLTZL,   recBGEZL,   recNULL, recNULL, recNULL, recNULL,
    recTGEI,   recTGEIU,  recTLTI,    recTLTIU,   recTEQI, recNULL, recTNEI, recNULL,
    recBLTZAL, recBGEZAL, recBLTZALL, recBGEZALL, recNULL, recNULL, recNULL, recNULL,
    recMTSAB,  recMTSAH,  recNULL,    recNULL,    recNULL, recNULL, recNULL, recNULL,
};

void (*recCP0[32] )() = {
    recMFC0,    recNULL, recNULL, recNULL, recMTC0, recNULL, recNULL, recNULL,
    recCOP0BC0, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL,
    recCOP0C0,  recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL,
    recNULL,    recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL,
};

void (*recCP0BC0[32] )() = {
    recBC0F, recBC0T, recBC0FL, recBC0TL, recNULL, recNULL, recNULL, recNULL,
    recNULL, recNULL, recNULL,  recNULL,  recNULL, recNULL, recNULL, recNULL,
    recNULL, recNULL, recNULL,  recNULL,  recNULL, recNULL, recNULL, recNULL,
    recNULL, recNULL, recNULL,  recNULL,  recNULL, recNULL, recNULL, recNULL,
};

void (*recCP0C0[64] )() = {
    recNULL, recTLBR, recTLBWI, recNULL, recNULL, recNULL, recTLBWR, recNULL,
    recTLBP, recNULL, recNULL,  recNULL, recNULL, recNULL, recNULL,  recNULL,
    recNULL, recNULL, recNULL,  recNULL, recNULL, recNULL, recNULL,  recNULL,
    recERET, recNULL, recNULL,  recNULL, recNULL, recNULL, recNULL,  recNULL,
    recNULL, recNULL, recNULL,  recNULL, recNULL, recNULL, recNULL,  recNULL,
    recNULL, recNULL, recNULL,  recNULL, recNULL, recNULL, recNULL,  recNULL,
    recNULL, recNULL, recNULL,  recNULL, recNULL, recNULL, recNULL,  recNULL,
    recEI,   recDI,   recNULL,  recNULL, recNULL, recNULL, recNULL,  recNULL,
};

void (*recCP1[32] )() = {
    recMFC1,     recNULL, recCFC1, recNULL, recMTC1,   recNULL, recCTC1, recNULL,
    recCOP1_BC1, recNULL, recNULL, recNULL, recNULL,   recNULL, recNULL, recNULL,
    recCOP1_S,   recNULL, recNULL, recNULL, recCOP1_W, recNULL, recNULL, recNULL,
    recNULL,     recNULL, recNULL, recNULL, recNULL,   recNULL, recNULL, recNULL,
};

void (*recCP1BC1[32] )() = {
    recBC1F, recBC1T, recBC1FL, recBC1TL, recNULL, recNULL, recNULL, recNULL,
    recNULL, recNULL, recNULL,  recNULL,  recNULL, recNULL, recNULL, recNULL,
    recNULL, recNULL, recNULL,  recNULL,  recNULL, recNULL, recNULL, recNULL,
    recNULL, recNULL, recNULL,  recNULL,  recNULL, recNULL, recNULL, recNULL,
};

void (*recCP1S[64] )() = {
	recADD_S,  recSUB_S,  recMUL_S,  recDIV_S, recSQRT_S, recABS_S,  recMOV_S,   recNEG_S, 
	recNULL,   recNULL,   recNULL,   recNULL,  recNULL,   recNULL,   recNULL,    recNULL,   
	recNULL,   recNULL,   recNULL,   recNULL,  recNULL,   recNULL,   recRSQRT_S, recNULL,  
	recADDA_S, recSUBA_S, recMULA_S, recNULL,  recMADD_S, recMSUB_S, recMADDA_S, recMSUBA_S,
	recNULL,   recNULL,   recNULL,   recNULL,  recCVT_W,  recNULL,   recNULL,    recNULL, 
	recMAX_S,  recMIN_S,  recNULL,   recNULL,  recNULL,   recNULL,   recNULL,    recNULL, 
	recC_F,    recNULL,   recC_EQ,   recNULL,  recC_LT,   recNULL,   recC_LE,    recNULL, 
	recNULL,   recNULL,   recNULL,   recNULL,  recNULL,   recNULL,   recNULL,    recNULL, 
};
 
void (*recCP1W[64] )() = { 
	recNULL,  recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL,   	
	recNULL,  recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL,   
	recNULL,  recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL,   
	recNULL,  recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL,   
	recCVT_S, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL,   
	recNULL,  recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL,   
	recNULL,  recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL,   
	recNULL,  recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL,
};

void (*recMMIt[64] )() = {
	 recMADD,  recMADDU,  recNULL,  recNULL,  recPLZCW, recNULL, recNULL,  recNULL,
    recMMI0,  recMMI2,   recNULL,  recNULL,  recNULL,  recNULL, recNULL,  recNULL,
    recMFHI1, recMTHI1,  recMFLO1, recMTLO1, recNULL,  recNULL, recNULL,  recNULL,
    recMULT1, recMULTU1, recDIV1,  recDIVU1, recNULL,  recNULL, recNULL,  recNULL,
    recMADD1, recMADDU1, recNULL,  recNULL,  recNULL,  recNULL, recNULL,  recNULL,
    recMMI1 , recMMI3,   recNULL,  recNULL,  recNULL,  recNULL, recNULL,  recNULL,
    recPMFHL, recPMTHL,  recNULL,  recNULL,  recPSLLH, recNULL, recPSRLH, recPSRAH,
    recNULL,  recNULL,   recNULL,  recNULL,  recPSLLW, recNULL, recPSRLW, recPSRAW,
};

void (*recMMI0t[32] )() = { 
	recPADDW,  recPSUBW,  recPCGTW,  recPMAXW,       
	recPADDH,  recPSUBH,  recPCGTH,  recPMAXH,        
	recPADDB,  recPSUBB,  recPCGTB,  recNULL,
	recNULL,   recNULL,   recNULL,   recNULL,
	recPADDSW, recPSUBSW, recPEXTLW, recPPACW,        
	recPADDSH, recPSUBSH, recPEXTLH, recPPACH,        
	recPADDSB, recPSUBSB, recPEXTLB, recPPACB,        
	recNULL,   recNULL,   recPEXT5,  recPPAC5,
};

void (*recMMI1t[32] )() = { 
	recNULL,   recPABSW,  recPCEQW,  recPMINW, 
	recPADSBH, recPABSH,  recPCEQH,  recPMINH, 
	recNULL,   recNULL,   recPCEQB,  recNULL, 
	recNULL,   recNULL,   recNULL,   recNULL, 
	recPADDUW, recPSUBUW, recPEXTUW, recNULL,  
	recPADDUH, recPSUBUH, recPEXTUH, recNULL, 
	recPADDUB, recPSUBUB, recPEXTUB, recQFSRV, 
	recNULL,   recNULL,   recNULL,   recNULL, 
};

void (*recMMI2t[32] )() = { 
	recPMADDW, recNULL,   recPSLLVW, recPSRLVW, 
	recPMSUBW, recNULL,   recNULL,   recNULL,
	recPMFHI,  recPMFLO,  recPINTH,  recNULL,
	recPMULTW, recPDIVW,  recPCPYLD, recNULL,
	recPMADDH, recPHMADH, recPAND,   recPXOR, 
	recPMSUBH, recPHMSBH, recNULL,   recNULL, 
	recNULL,   recNULL,   recPEXEH,  recPREVH, 
	recPMULTH, recPDIVBW, recPEXEW,  recPROT3W, 
};

void (*recMMI3t[32] )() = { 
	recPMADDUW, recNULL,   recNULL,   recPSRAVW, 
	recNULL,    recNULL,   recNULL,   recNULL,
	recPMTHI,   recPMTLO,  recPINTEH, recNULL,
	recPMULTUW, recPDIVUW, recPCPYUD, recNULL,
	recNULL,    recNULL,   recPOR,    recPNOR,  
	recNULL,    recNULL,   recNULL,   recNULL,
	recNULL,    recNULL,   recPEXCH,  recPCPYH, 
	recNULL,    recNULL,   recPEXCW,  recNULL,
};

////////////////////////////////////////////////
// Back-Prob Function Tables - Gathering Info //
////////////////////////////////////////////////
#define rpropSetRead(reg, 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_MMX|EEINST_XMM)); \
	_recFillRegister(pinst, XMMTYPE_GPRREG, reg, 0); \
} \

#define rpropSetWrite0(reg, mask, live) { \
	prev->regs[reg] &= ~((mask)|live|EEINST_XMM|EEINST_MMX); \
	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); \
}

#define rpropSetWrite(reg, mask) { \
	rpropSetWrite0(reg, mask, EEINST_LIVE0); \
} \

#define rpropSetFast(write1, read1, read2, mask) { \
	if( write1 ) { rpropSetWrite(write1, mask); } \
	if( read1 ) { rpropSetRead(read1, mask); } \
	if( read2 ) { rpropSetRead(read2, mask); } \
} \

#define rpropSetLOHI(write1, read1, read2, mask, lo, hi) { \
	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
#define rpropSetFPURead(reg, 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_MMX|EEINST_XMM)); \
	if( reg == XMMFPU_ACC ) _recFillRegister(pinst, XMMTYPE_FPACC, 0, 0); \
	else _recFillRegister(pinst, XMMTYPE_FPREG, reg, 0); \
} \

#define rpropSetFPUWrite0(reg, mask, live) { \
	prev->fpuregs[reg] &= ~((mask)|live|EEINST_XMM|EEINST_MMX); \
	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); \
}

#define rpropSetFPUWrite(reg, mask) { \
	rpropSetFPUWrite0(reg, mask, EEINST_LIVE0); \
} \


void rpropBSC(EEINST* prev, EEINST* pinst);
void rpropSPECIAL(EEINST* prev, EEINST* pinst);
void rpropREGIMM(EEINST* prev, EEINST* pinst);
void rpropCP0(EEINST* prev, EEINST* pinst);
void rpropCP1(EEINST* prev, EEINST* pinst);
void rpropCP2(EEINST* prev, EEINST* pinst);
void rpropMMI(EEINST* prev, EEINST* pinst);
void rpropMMI0(EEINST* prev, EEINST* pinst);
void rpropMMI1(EEINST* prev, EEINST* pinst);
void rpropMMI2(EEINST* prev, EEINST* pinst);
void rpropMMI3(EEINST* prev, EEINST* pinst);

#define EEINST_REALXMM (cpucaps.hasStreamingSIMDExtensions?EEINST_XMM:0)

//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 rpropBSC(EEINST* prev, EEINST* pinst)
{
	switch(cpuRegs.code >> 26) {
		case 0: rpropSPECIAL(prev, pinst); break;
		case 1: rpropREGIMM(prev, pinst); 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 |= (cpucaps.hasStreamingSIMD2Extensions?(EEINST_REALXMM|EEINST_MMX):0);
			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 |= (cpucaps.hasStreamingSIMD2Extensions?(EEINST_REALXMM|EEINST_MMX):0);
			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|((_Rs_!=0&&cpucaps.hasStreamingSIMD2Extensions)?EEINST_MMX:0));
			break;

		case 8: // addi
		case 9: // addiu
			rpropSetWrite(_Rt_, EEINST_LIVE1);
			rpropSetRead(_Rs_, 0);
			pinst->info |= EEINST_MMX;
			break;

		case 10: // slti
			rpropSetWrite(_Rt_, EEINST_LIVE1);
			rpropSetRead(_Rs_, EEINST_LIVE1);
			pinst->info |= EEINST_MMX;
			break;
		case 11: // sltiu
			rpropSetWrite(_Rt_, EEINST_LIVE1);
			rpropSetRead(_Rs_, EEINST_LIVE1);
			pinst->info |= EEINST_MMX;
			break;

		case 12: // andi
			rpropSetWrite(_Rt_, EEINST_LIVE1);
			rpropSetRead(_Rs_, (_Rs_!=_Rt_?EEINST_MMX:0));
			pinst->info |= EEINST_MMX;
			break;
		case 13: // ori
			rpropSetWrite(_Rt_, EEINST_LIVE1);
			rpropSetRead(_Rs_, EEINST_LIVE1|(_Rs_!=_Rt_?EEINST_MMX:0));
			pinst->info |= EEINST_MMX;
			break;
		case 14: // xori
			rpropSetWrite(_Rt_, EEINST_LIVE1);
			rpropSetRead(_Rs_, EEINST_LIVE1|(_Rs_!=_Rt_?EEINST_MMX:0));
			pinst->info |= EEINST_MMX;
			break;

		case 15: // lui
			rpropSetWrite(_Rt_, EEINST_LIVE1);
			break;

		case 16: rpropCP0(prev, pinst); break;
		case 17: rpropCP1(prev, pinst); break;
		case 18: rpropCP2(prev, pinst); 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(prev, pinst); break;

		case 30: // lq
			rpropSetWrite(_Rt_, EEINST_LIVE1|EEINST_LIVE2);
			rpropSetRead(_Rs_, 0);
			pinst->info |= EEINST_MMX;
			pinst->info |= EEINST_REALXMM;
			break;

		case 31: // sq
			rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_LIVE2|EEINST_REALXMM);
			rpropSetRead(_Rs_, 0);
			pinst->info |= EEINST_MMX;
			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_MMX;
			pinst->info |= EEINST_REALXMM;
			break;

		case 44: // sdl
		case 45: // sdr
		case 63: // sd
			rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_MMX|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|(_Rs_!=0?EEINST_MMX:0));
			break;
	}
}

//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
void rpropSPECIAL(EEINST* prev, EEINST* pinst)
{
	int temp;
	switch(_Funct_) {
		case 0: // SLL
		case 2: // SRL
		case 3: // SRA
			rpropSetWrite(_Rd_, EEINST_LIVE1);
			rpropSetRead(_Rt_, EEINST_MMX);
			break;

		case 4: // sllv
		case 6: // srlv
		case 7: // srav
			rpropSetWrite(_Rd_, EEINST_LIVE1);
			rpropSetRead(_Rs_, EEINST_MMX);
			rpropSetRead(_Rt_, EEINST_MMX);
			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);
			pinst->info |= EEINST_MMX;
			_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_MMX|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_MMX|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_, EEINST_MMX);
			rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_MMX);
			break;

		case 24: // mult
			// can do unsigned mult only if HI isn't used
			//temp = (pinst->regs[XMMGPR_HI]&(EEINST_LIVE0|EEINST_LIVE1))?0:(cpucaps.hasStreamingSIMD2Extensions?EEINST_MMX:0);
			temp = 0;
			rpropSetWrite(XMMGPR_LO, EEINST_LIVE1);
			rpropSetWrite(XMMGPR_HI, EEINST_LIVE1);
			rpropSetWrite(_Rd_, EEINST_LIVE1);
			rpropSetRead(_Rs_, temp);
			rpropSetRead(_Rt_, temp);
			pinst->info |= temp;
			break;
		case 25: // multu
			rpropSetWrite(XMMGPR_LO, EEINST_LIVE1);
			rpropSetWrite(XMMGPR_HI, EEINST_LIVE1);
			rpropSetWrite(_Rd_, EEINST_LIVE1);
			rpropSetRead(_Rs_, (cpucaps.hasStreamingSIMD2Extensions?EEINST_MMX:0));
			rpropSetRead(_Rt_, (cpucaps.hasStreamingSIMD2Extensions?EEINST_MMX:0));
			if( cpucaps.hasStreamingSIMD2Extensions ) pinst->info |= EEINST_MMX;
			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|EEINST_MMX;
			break;

		case 32: // add
		case 33: // addu
		case 34: // sub
		case 35: // subu
			rpropSetWrite(_Rd_, EEINST_LIVE1);
			if( _Rs_ ) rpropSetRead(_Rs_, 0);
			if( _Rt_ ) rpropSetRead(_Rt_, 0);
			pinst->info |= EEINST_MMX;
			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)|EEINST_MMX);
			rpropSetRead(_Rt_, (pinst->regs[_Rd_]&EEINST_LIVE1)|EEINST_MMX);
			break;

		case 40: // mfsa
			rpropSetWrite(_Rd_, EEINST_LIVE1);
			break;
		case 41: // mtsa
			rpropSetRead(_Rs_, EEINST_LIVE1|EEINST_MMX);
			break;

		case 42: // slt
			rpropSetWrite(_Rd_, EEINST_LIVE1);
			rpropSetRead(_Rs_, EEINST_LIVE1);
			rpropSetRead(_Rt_, EEINST_LIVE1);
			pinst->info |= EEINST_MMX;
			break;

		case 43: // sltu
			rpropSetWrite(_Rd_, EEINST_LIVE1);
			rpropSetRead(_Rs_, EEINST_LIVE1);
			rpropSetRead(_Rt_, EEINST_LIVE1);
			pinst->info |= EEINST_MMX;
			break;

		case 44: // dadd
		case 45: // daddu
		case 46: // dsub
		case 47: // dsubu
			rpropSetWrite(_Rd_, EEINST_LIVE1);
			if( _Rs_ == 0 || _Rt_ == 0 ) {
				// just a copy, so don't force mmx
				rpropSetRead(_Rs_, (pinst->regs[_Rd_]&EEINST_LIVE1));
				rpropSetRead(_Rt_, (pinst->regs[_Rd_]&EEINST_LIVE1));
			}
			else {
				rpropSetRead(_Rs_, (pinst->regs[_Rd_]&EEINST_LIVE1)|(cpucaps.hasStreamingSIMD2Extensions?EEINST_MMX:0));
				rpropSetRead(_Rt_, (pinst->regs[_Rd_]&EEINST_LIVE1)|(cpucaps.hasStreamingSIMD2Extensions?EEINST_MMX:0));
			}
			if( cpucaps.hasStreamingSIMD2Extensions ) pinst->info |= EEINST_MMX;
			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|(cpucaps.hasStreamingSIMD2Extensions?EEINST_MMX:0));
			pinst->info |= EEINST_MMX;
			break;

		case 60: // dsll32
			rpropSetWrite(_Rd_, EEINST_LIVE1);
			rpropSetRead(_Rt_, (cpucaps.hasStreamingSIMD2Extensions?EEINST_MMX:0));
			pinst->info |= EEINST_MMX;
			break;

		default:
			rpropSetWrite(_Rd_, EEINST_LIVE1);
			rpropSetRead(_Rs_, EEINST_LIVE1|EEINST_MMX);
			rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_MMX);
			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,
void rpropREGIMM(EEINST* prev, EEINST* pinst)
{
	switch(_Rt_) {
		case 0: // bltz
		case 1: // bgez
			rpropSetRead(_Rs_, EEINST_LIVE1);
			pinst->info |= EEINST_MMX;
			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_MMX;
			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;
		default:
			assert(0);
			break;
	}
}

//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,
void rpropCP0(EEINST* prev, EEINST* pinst)
{
	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, 
void rpropCP1(EEINST* prev, EEINST* pinst)
{
	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|EEINST_MMX);
			break;
		case 4: // mtc1
			rpropSetFPUWrite(_Fs_, EEINST_REALXMM);
			rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_REALXMM);
			break;
		case 6: // ctc1
			rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_REALXMM|EEINST_MMX);
			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:
			assert( _Funct_ == 32 ); // CVT.S.W
			rpropSetFPUWrite(_Fd_, EEINST_REALXMM);
			rpropSetFPURead(_Fs_, EEINST_REALXMM);
			break;
		default:
			assert(0);
	}
}

#undef _Ft_
#undef _Fs_
#undef _Fd_

void rpropCP2(EEINST* prev, EEINST* pinst)
{
	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 |= 2;
			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,
void rpropMMI(EEINST* prev, EEINST* pinst)
{
	int temp;
	switch(cpuRegs.code&0x3f) {
		case 0: // madd
		case 1: // maddu
			rpropSetLOHI(_Rd_, _Rs_, _Rt_, EEINST_LIVE1, MODE_READ|MODE_WRITE, MODE_READ|MODE_WRITE);
			break;
		case 4: // plzcw
			rpropSetFast(_Rd_, _Rs_, 0, EEINST_LIVE1);
			break;
		case 8: rpropMMI0(prev, pinst); break;
		case 9: rpropMMI2(prev, pinst); break;

		case 16: // mfhi1
			rpropSetWrite(_Rd_, EEINST_LIVE1);
			temp = ((pinst->regs[_Rd_]&(EEINST_MMX|EEINST_REALXMM))?EEINST_MMX:EEINST_REALXMM);
			rpropSetRead(XMMGPR_HI, temp|EEINST_LIVE2);
			break;
		case 17: // mthi1
			rpropSetWrite0(XMMGPR_HI, EEINST_LIVE2, 0);
			rpropSetRead(_Rs_, EEINST_LIVE1);
			break;
		case 18: // mflo1
			rpropSetWrite(_Rd_, EEINST_LIVE1);
			temp = ((pinst->regs[_Rd_]&(EEINST_MMX|EEINST_REALXMM))?EEINST_MMX:EEINST_REALXMM);
			rpropSetRead(XMMGPR_LO, temp|EEINST_LIVE2);
			break;
		case 19: // mtlo1
			rpropSetWrite0(XMMGPR_LO, EEINST_LIVE2, 0);
			rpropSetRead(_Rs_, EEINST_LIVE1);
			break;

		case 24: // mult1
			temp = (pinst->regs[XMMGPR_HI]&(EEINST_LIVE2))?0:(cpucaps.hasStreamingSIMD2Extensions?EEINST_MMX:0);
			rpropSetWrite0(XMMGPR_LO, EEINST_LIVE2, 0);
			rpropSetWrite0(XMMGPR_HI, EEINST_LIVE2, 0);
			rpropSetWrite(_Rd_, EEINST_LIVE1);
			rpropSetRead(_Rs_, temp);
			rpropSetRead(_Rt_, temp);
			pinst->info |= temp;
			break;
		case 25: // multu1
			rpropSetWrite0(XMMGPR_LO, EEINST_LIVE2, 0);
			rpropSetWrite0(XMMGPR_HI, EEINST_LIVE2, 0);
			rpropSetWrite(_Rd_, EEINST_LIVE1);
			rpropSetRead(_Rs_, (cpucaps.hasStreamingSIMD2Extensions?EEINST_MMX:0));
			rpropSetRead(_Rt_, (cpucaps.hasStreamingSIMD2Extensions?EEINST_MMX:0));
			if( cpucaps.hasStreamingSIMD2Extensions ) pinst->info |= EEINST_MMX;
			break;

		case 26: // div1
		case 27: // divu1
			rpropSetWrite0(XMMGPR_LO, EEINST_LIVE2, 0);
			rpropSetWrite0(XMMGPR_HI, EEINST_LIVE2, 0);
			rpropSetRead(_Rs_, 0);
			rpropSetRead(_Rt_, 0);
			//pinst->info |= EEINST_REALXMM|EEINST_MMX;
			break;

		case 32: // madd1
		case 33: // maddu1
			rpropSetWrite0(XMMGPR_LO, EEINST_LIVE2, 0);
			rpropSetWrite0(XMMGPR_HI, EEINST_LIVE2, 0);
			rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE1);
			rpropSetRead(XMMGPR_LO, EEINST_LIVE2);
			rpropSetRead(XMMGPR_HI, EEINST_LIVE2);
			break;

		case 40: rpropMMI1(prev, pinst); break;
		case 41: rpropMMI3(prev, pinst); 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,
void rpropMMI0(EEINST* prev, EEINST* pinst)
{
	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;
	}
}

void rpropMMI1(EEINST* prev, EEINST* pinst)
{
	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;
	}
}

void rpropMMI2(EEINST* prev, EEINST* pinst)
{
	switch((cpuRegs.code>>6)&0x1f) {
		case 0: // pmaddw
		case 4: // pmsubw
			rpropSetLOHI(_Rd_, _Rs_, _Rt_, EEINST_LIVE2|EEINST_LIVE1, MODE_READ|MODE_WRITE, MODE_READ|MODE_WRITE);
			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(_Rd_, _Rs_, _Rt_, EEINST_LIVE2|EEINST_LIVE1, MODE_WRITE, MODE_WRITE);
			break;
		case 13: // pdivw
			rpropSetLOHI(0, _Rs_, _Rt_, EEINST_LIVE2|EEINST_LIVE1, MODE_WRITE, MODE_WRITE);
			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(_Rd_, _Rs_, _Rt_, EEINST_LIVE2|EEINST_LIVE1|EEINST_REALXMM, MODE_READ|MODE_WRITE, MODE_READ|MODE_WRITE);
			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(_Rd_, _Rs_, _Rt_, EEINST_LIVE2|EEINST_LIVE1|EEINST_REALXMM, MODE_WRITE, MODE_WRITE);
			break;
		case 29: // pdivbw
			rpropSetLOHI(_Rd_, _Rs_, _Rt_, EEINST_LIVE2|EEINST_LIVE1, MODE_WRITE, MODE_WRITE);
			break;

		default:
			rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE1|EEINST_LIVE2|EEINST_REALXMM);
			break;
	}
}

void rpropMMI3(EEINST* prev, EEINST* pinst)
{
	switch((cpuRegs.code>>6)&0x1f) {
		case 0: // pmadduw
			rpropSetLOHI(_Rd_, _Rs_, _Rt_, EEINST_LIVE2|EEINST_LIVE1|EEINST_REALXMM, MODE_READ|MODE_WRITE, MODE_READ|MODE_WRITE);
			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(_Rd_, _Rs_, _Rt_, EEINST_LIVE2|EEINST_LIVE1|EEINST_REALXMM, MODE_WRITE, MODE_WRITE);
			break;
		case 13: // pdivuw
			rpropSetLOHI(0, _Rs_, _Rt_, EEINST_LIVE2|EEINST_LIVE1, MODE_WRITE, MODE_WRITE);
			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;
	}
}

#endif // PCSX2_NORECBUILD
