mirror of
https://github.com/PCSX2/pcsx2.git
synced 2025-04-02 10:52:54 -04:00
git-svn-id: http://pcsx2.googlecode.com/svn/branches/pcsx2_0.9.4@186 96395faa-99c1-11dd-bbfe-3dabce05a288
1285 lines
39 KiB
C
1285 lines
39 KiB
C
/* 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
|