#include <windows.h>
#include <types.h>
#include "rsp.h"
#include "emu.h"
#include "mmio.h"
#include "unreal.h"
#include "r4300i.h"

#include "inline.cpp"


int VectorShiftTable[12] = {  0,   1,   2,   3,   4,   4,   3,   3,   4,   4,   4,   4 };
char VectorCodeTable[12] = { 'B', 'S', 'L', 'D', 'Q', 'R', 'P', 'U', 'H', 'F', 'W', 'T' };


HANDLE hRSPRunEvent, hRSPDebugEvent;
bool RSP_running, RSP_want_to_exit;

DWORD RSPThreadFunc(LPDWORD lpdwParam)
{
    ((RSP_Processor *)lpdwParam)->DoThread();
    return 0;
}

RSP_Processor::RSP_Processor()
{
    DWORD ThreadID;

	/* Set up Opcode function pointers */
	Opcode[0] = SPECIAL;
	Opcode[1] = REGIMM;
	Opcode[2] = J;
	Opcode[3] = JAL;
	Opcode[4] = BEQ;
	Opcode[5] = BNE;
	Opcode[6] = BLEZ;
	Opcode[7] = BGTZ;
	Opcode[8] = ADDI;
	Opcode[9] = ADDIU;
	Opcode[10] = Reserved_Instruction;
	Opcode[11] = Reserved_Instruction;
	Opcode[12] = ANDI;
	Opcode[13] = ORI;
	Opcode[14] = XORI;
	Opcode[15] = LUI;
	Opcode[16] = COP0;
	Opcode[17] = Reserved_Instruction;
	Opcode[18] = COP2;
	Opcode[19] = Reserved_Instruction;
	Opcode[20] = Reserved_Instruction;
	Opcode[21] = Reserved_Instruction;
	Opcode[22] = Reserved_Instruction;
	Opcode[23] = Reserved_Instruction;
	Opcode[24] = Reserved_Instruction;
	Opcode[25] = Reserved_Instruction;
	Opcode[26] = Reserved_Instruction;
	Opcode[27] = Reserved_Instruction;
	Opcode[28] = Reserved_Instruction;
	Opcode[29] = Reserved_Instruction;
	Opcode[30] = Reserved_Instruction;
	Opcode[31] = Reserved_Instruction;
	Opcode[32] = LB;
	Opcode[33] = LH;
	Opcode[34] = Reserved_Instruction; 
	Opcode[35] = LW;
	Opcode[36] = LBU;
	Opcode[37] = LHU;
	Opcode[38] = Reserved_Instruction;
	Opcode[39] = Reserved_Instruction;
	Opcode[40] = SB;
	Opcode[41] = SH;
	Opcode[42] = Reserved_Instruction;
	Opcode[43] = SW;
	Opcode[44] = Reserved_Instruction;
	Opcode[45] = Reserved_Instruction;
	Opcode[46] = Reserved_Instruction;
	Opcode[47] = Reserved_Instruction;
	Opcode[48] = Reserved_Instruction;
	Opcode[49] = Reserved_Instruction;
	Opcode[50] = LWC2;
	Opcode[51] = Reserved_Instruction;
	Opcode[52] = Reserved_Instruction;
	Opcode[53] = Reserved_Instruction;
	Opcode[54] = Reserved_Instruction;
	Opcode[55] = Reserved_Instruction;
	Opcode[56] = Reserved_Instruction;
	Opcode[57] = Reserved_Instruction;
	Opcode[58] = SWC2;
	Opcode[59] = Reserved_Instruction;
	Opcode[60] = Reserved_Instruction;
	Opcode[61] = Reserved_Instruction;
	Opcode[62] = Reserved_Instruction;
	Opcode[63] = Reserved_Instruction;

	/* Set up Special function pointers */
    Special[0] = SLL;
    Special[1] = Reserved_Instruction;
    Special[2] = SRL;
    Special[3] = SRA;
    Special[4] = SLLV;
    Special[5] = Reserved_Instruction;
    Special[6] = SRLV;
    Special[7] = SRAV;
	Special[8] = JR;
    Special[9] = Reserved_Instruction;
    Special[10] = Reserved_Instruction;
    Special[11] = Reserved_Instruction;
    Special[12] = Reserved_Instruction;
    Special[13] = BREAK;
    Special[14] = Reserved_Instruction;
    Special[15] = Reserved_Instruction;
    Special[16] = Reserved_Instruction;
    Special[17] = Reserved_Instruction;
    Special[18] = Reserved_Instruction;
    Special[19] = Reserved_Instruction;
    Special[20] = Reserved_Instruction;
    Special[21] = Reserved_Instruction;
    Special[22] = Reserved_Instruction;
    Special[23] = Reserved_Instruction;
    Special[24] = Reserved_Instruction;
    Special[25] = Reserved_Instruction;
    Special[26] = Reserved_Instruction;
    Special[27] = Reserved_Instruction;
    Special[28] = Reserved_Instruction;
    Special[29] = Reserved_Instruction;
    Special[30] = Reserved_Instruction;
    Special[31] = Reserved_Instruction;
    Special[32] = ADD;
    Special[33] = ADDU;
    Special[34] = SUB;
    Special[35] = Reserved_Instruction;
    Special[36] = AND;
    Special[37] = OR;
    Special[38] = XOR;
    Special[39] = NOR;
    Special[40] = Reserved_Instruction;
    Special[41] = Reserved_Instruction;
    Special[42] = Reserved_Instruction;
    Special[43] = Reserved_Instruction;
    Special[44] = Reserved_Instruction;
    Special[45] = Reserved_Instruction;
    Special[46] = Reserved_Instruction;
    Special[47] = Reserved_Instruction;
    Special[48] = Reserved_Instruction;
    Special[49] = Reserved_Instruction;
    Special[50] = Reserved_Instruction;
    Special[51] = Reserved_Instruction;
    Special[52] = Reserved_Instruction;
    Special[53] = Reserved_Instruction;
    Special[54] = Reserved_Instruction;
    Special[55] = Reserved_Instruction;
    Special[56] = Reserved_Instruction;
    Special[57] = Reserved_Instruction;
    Special[58] = Reserved_Instruction;
    Special[59] = Reserved_Instruction;
    Special[60] = Reserved_Instruction;
    Special[61] = Reserved_Instruction;
    Special[62] = Reserved_Instruction;
    Special[63] = Reserved_Instruction;

	RegIMM[0] = BLTZ;
	RegIMM[1] = BGEZ;
	RegIMM[2] = Reserved_Instruction;
	RegIMM[3] = Reserved_Instruction;
	RegIMM[4] = Reserved_Instruction;
	RegIMM[5] = Reserved_Instruction;
	RegIMM[6] = Reserved_Instruction;
	RegIMM[7] = Reserved_Instruction;
	RegIMM[8] = Reserved_Instruction;
	RegIMM[9] = Reserved_Instruction;
	RegIMM[10] = Reserved_Instruction;
	RegIMM[11] = Reserved_Instruction;
	RegIMM[12] = Reserved_Instruction;
	RegIMM[13] = Reserved_Instruction;
	RegIMM[14] = Reserved_Instruction;
	RegIMM[15] = Reserved_Instruction;
	RegIMM[16] = Reserved_Instruction;
	RegIMM[17] = Reserved_Instruction;
	RegIMM[18] = Reserved_Instruction;
	RegIMM[19] = BGEZALL;
	RegIMM[20] = Reserved_Instruction;
	RegIMM[21] = Reserved_Instruction;
	RegIMM[22] = Reserved_Instruction;
	RegIMM[23] = Reserved_Instruction;
	RegIMM[24] = Reserved_Instruction;
	RegIMM[25] = Reserved_Instruction;
	RegIMM[26] = Reserved_Instruction;
	RegIMM[27] = Reserved_Instruction;
	RegIMM[28] = Reserved_Instruction;
	RegIMM[29] = Reserved_Instruction;
	RegIMM[30] = Reserved_Instruction;
	RegIMM[31] = Reserved_Instruction;

	Cop0[0] = MFC0;
	Cop0[1] = Reserved_Instruction;
	Cop0[2] = Reserved_Instruction;
	Cop0[3] = Reserved_Instruction;
	Cop0[4] = MTC0;
	Cop0[5] = Reserved_Instruction;
	Cop0[6] = Reserved_Instruction;
	Cop0[7] = Reserved_Instruction;
	Cop0[8] = Reserved_Instruction;
	Cop0[9] = Reserved_Instruction;
	Cop0[10] = Reserved_Instruction;
	Cop0[11] = Reserved_Instruction;
	Cop0[12] = Reserved_Instruction;
	Cop0[13] = Reserved_Instruction;
	Cop0[14] = Reserved_Instruction;
	Cop0[15] = Reserved_Instruction;
	Cop0[16] = Reserved_Instruction;
	Cop0[17] = Reserved_Instruction;
	Cop0[18] = Reserved_Instruction;
	Cop0[19] = Reserved_Instruction;
	Cop0[20] = Reserved_Instruction;
	Cop0[21] = Reserved_Instruction;
	Cop0[22] = Reserved_Instruction;
	Cop0[23] = Reserved_Instruction;
	Cop0[24] = Reserved_Instruction;
	Cop0[25] = Reserved_Instruction;
	Cop0[26] = Reserved_Instruction;
	Cop0[27] = Reserved_Instruction;
	Cop0[28] = Reserved_Instruction;
	Cop0[29] = Reserved_Instruction;
	Cop0[30] = Reserved_Instruction;
	Cop0[31] = Reserved_Instruction;

	Cop2[0] = MFC2;
	Cop2[1] = Reserved_Instruction;
	Cop2[2] = CFC2;
	Cop2[3] = Reserved_Instruction;
	Cop2[4] = MTC2;
	Cop2[5] = Reserved_Instruction;
	Cop2[6] = CTC2;
	Cop2[7] = Reserved_Instruction;
	Cop2[8] = Reserved_Instruction;
	Cop2[9] = Reserved_Instruction;
	Cop2[10] = Reserved_Instruction;
	Cop2[11] = Reserved_Instruction;
	Cop2[12] = Reserved_Instruction;
	Cop2[13] = Reserved_Instruction;
	Cop2[14] = Reserved_Instruction;
	Cop2[15] = Reserved_Instruction;
	Cop2[16] = VECTOP;
	Cop2[17] = VECTOP;
	Cop2[18] = VECTOP;
	Cop2[19] = VECTOP;
	Cop2[20] = VECTOP;
	Cop2[21] = VECTOP;
	Cop2[22] = VECTOP;
	Cop2[23] = VECTOP;
	Cop2[24] = VECTOP;
	Cop2[25] = VECTOP;
	Cop2[26] = VECTOP;
	Cop2[27] = VECTOP;
	Cop2[28] = VECTOP;
	Cop2[29] = VECTOP;
	Cop2[30] = VECTOP;
	Cop2[31] = VECTOP;

	VectOp[0] = VMULF;
	VectOp[1] = Reserved_Instruction;
	VectOp[2] = Reserved_Instruction;
	VectOp[3] = Reserved_Instruction;
	VectOp[4] = VMUDL;
	VectOp[5] = VMUDM;
	VectOp[6] = VMUDN;
	VectOp[7] = VMUDH;
	VectOp[8] = VMACF;
	VectOp[9] = Reserved_Instruction;
	VectOp[10] = Reserved_Instruction;
	VectOp[11] = Reserved_Instruction;
	VectOp[12] = VMADL;
	VectOp[13] = VMADM;
	VectOp[14] = VMADN;
	VectOp[15] = VMADH;
	VectOp[16] = VADD;
	VectOp[17] = VSUB;
	VectOp[18] = Reserved_Instruction; //VSUT;
	VectOp[19] = Reserved_Instruction;
	VectOp[20] = Reserved_Instruction;
	VectOp[21] = VSUBC;
	VectOp[22] = Reserved_Instruction;
	VectOp[23] = Reserved_Instruction;
	VectOp[24] = Reserved_Instruction;
	VectOp[25] = Reserved_Instruction;
	VectOp[26] = Reserved_Instruction;
	VectOp[27] = Reserved_Instruction;
	VectOp[28] = Reserved_Instruction;
	VectOp[29] = Reserved_Instruction;
	VectOp[30] = Reserved_Instruction;
	VectOp[31] = Reserved_Instruction;
	VectOp[32] = Reserved_Instruction;
	VectOp[33] = Reserved_Instruction;
	VectOp[34] = Reserved_Instruction;
	VectOp[35] = Reserved_Instruction;
	VectOp[36] = Reserved_Instruction;
	VectOp[37] = Reserved_Instruction;
	VectOp[38] = Reserved_Instruction;
	VectOp[39] = Reserved_Instruction;
	VectOp[40] = VAND;
	VectOp[41] = VNAND;
	VectOp[42] = VOR;
	VectOp[43] = VNOR;
	VectOp[44] = VXOR;
	VectOp[45] = VNXOR;
	VectOp[46] = Reserved_Instruction;
	VectOp[47] = Reserved_Instruction;
	VectOp[48] = Reserved_Instruction;
	VectOp[49] = VRCPL;
	VectOp[50] = VRCPH;
	VectOp[51] = VMOV;
	VectOp[52] = Reserved_Instruction;
	VectOp[53] = Reserved_Instruction;
	VectOp[54] = Reserved_Instruction;
	VectOp[55] = VNOOP;
	VectOp[56] = Reserved_Instruction;
	VectOp[57] = Reserved_Instruction;
	VectOp[58] = Reserved_Instruction;
	VectOp[59] = Reserved_Instruction;
	VectOp[60] = Reserved_Instruction;
	VectOp[61] = Reserved_Instruction;
	VectOp[62] = Reserved_Instruction;
	VectOp[63] = Reserved_Instruction;

	RSPOpcodePrintTable[0] = P_RSP_SPECIAL;
	RSPOpcodePrintTable[1] = P_RSP_RegIMM;
	RSPOpcodePrintTable[2] = P_RSP_J;
	RSPOpcodePrintTable[3] = P_RSP_JAL;
	RSPOpcodePrintTable[4] = P_RSP_BEQ;
	RSPOpcodePrintTable[5] = P_RSP_BNE;
	RSPOpcodePrintTable[6] = P_RSP_BLEZ;
	RSPOpcodePrintTable[7] = P_RSP_BGTZ;
	RSPOpcodePrintTable[8] = P_RSP_ADDI;
	RSPOpcodePrintTable[9] = P_RSP_ADDIU;
	RSPOpcodePrintTable[10] = P_RSP_SLTI;
	RSPOpcodePrintTable[11] = P_RSP_SLTIU;
	RSPOpcodePrintTable[12] = P_RSP_ANDI;
	RSPOpcodePrintTable[13] = P_RSP_ORI;
	RSPOpcodePrintTable[14] = P_RSP_XORI;
	RSPOpcodePrintTable[15] = P_RSP_LUI;
	RSPOpcodePrintTable[16] = P_RSP_COP0;
	RSPOpcodePrintTable[17] = P_RSP_Reserved_Instruction;
	RSPOpcodePrintTable[18] = P_RSP_COP2;
	RSPOpcodePrintTable[19] = P_RSP_Reserved_Instruction;
	RSPOpcodePrintTable[20] = P_RSP_Reserved_Instruction;
	RSPOpcodePrintTable[21] = P_RSP_Reserved_Instruction;
	RSPOpcodePrintTable[22] = P_RSP_Reserved_Instruction;
	RSPOpcodePrintTable[23] = P_RSP_Reserved_Instruction;
	RSPOpcodePrintTable[24] = P_RSP_Reserved_Instruction;
	RSPOpcodePrintTable[25] = P_RSP_Reserved_Instruction;
	RSPOpcodePrintTable[26] = P_RSP_Reserved_Instruction;
	RSPOpcodePrintTable[27] = P_RSP_Reserved_Instruction;
	RSPOpcodePrintTable[28] = P_RSP_Reserved_Instruction;
	RSPOpcodePrintTable[29] = P_RSP_Reserved_Instruction;
	RSPOpcodePrintTable[30] = P_RSP_Reserved_Instruction;
	RSPOpcodePrintTable[31] = P_RSP_Reserved_Instruction;
	RSPOpcodePrintTable[32] = P_RSP_LB;
	RSPOpcodePrintTable[33] = P_RSP_LH;
	RSPOpcodePrintTable[34] = P_RSP_Reserved_Instruction;
	RSPOpcodePrintTable[35] = P_RSP_LW;
	RSPOpcodePrintTable[36] = P_RSP_LBU;
	RSPOpcodePrintTable[37] = P_RSP_LHU;
	RSPOpcodePrintTable[38] = P_RSP_Reserved_Instruction;
	RSPOpcodePrintTable[39] = P_RSP_Reserved_Instruction;
	RSPOpcodePrintTable[40] = P_RSP_SB;
	RSPOpcodePrintTable[41] = P_RSP_SH;
	RSPOpcodePrintTable[42] = P_RSP_Reserved_Instruction;
	RSPOpcodePrintTable[43] = P_RSP_SW;
	RSPOpcodePrintTable[44] = P_RSP_Reserved_Instruction;
	RSPOpcodePrintTable[45] = P_RSP_Reserved_Instruction;
	RSPOpcodePrintTable[46] = P_RSP_Reserved_Instruction;
	RSPOpcodePrintTable[47] = P_RSP_Reserved_Instruction;
	RSPOpcodePrintTable[48] = P_RSP_Reserved_Instruction;
	RSPOpcodePrintTable[49] = P_RSP_Reserved_Instruction;
	RSPOpcodePrintTable[50] = P_RSP_LWC2;
	RSPOpcodePrintTable[51] = P_RSP_Reserved_Instruction;
	RSPOpcodePrintTable[52] = P_RSP_Reserved_Instruction;
	RSPOpcodePrintTable[53] = P_RSP_Reserved_Instruction;
	RSPOpcodePrintTable[54] = P_RSP_Reserved_Instruction;
	RSPOpcodePrintTable[55] = P_RSP_Reserved_Instruction;
	RSPOpcodePrintTable[56] = P_RSP_Reserved_Instruction;
	RSPOpcodePrintTable[57] = P_RSP_Reserved_Instruction;
	RSPOpcodePrintTable[58] = P_RSP_SWC2;
	RSPOpcodePrintTable[59] = P_RSP_Reserved_Instruction;
	RSPOpcodePrintTable[60] = P_RSP_Reserved_Instruction;
	RSPOpcodePrintTable[61] = P_RSP_Reserved_Instruction;
	RSPOpcodePrintTable[62] = P_RSP_Reserved_Instruction;
	RSPOpcodePrintTable[63] = P_RSP_Reserved_Instruction;

	/* Set up Special function pointers */
	P_Special[0] = P_RSP_SLL;
	P_Special[1] = P_RSP_Reserved_Instruction;
	P_Special[2] = P_RSP_SRL;
	P_Special[3] = P_RSP_SRA;
	P_Special[4] = P_RSP_SLLV;
	P_Special[5] = P_RSP_Reserved_Instruction;
	P_Special[6] = P_RSP_SRLV;
	P_Special[7] = P_RSP_SRAV;
	P_Special[8] = P_RSP_JR;
	P_Special[9] = P_RSP_Reserved_Instruction;
	P_Special[10] = P_RSP_Reserved_Instruction;
	P_Special[11] = P_RSP_Reserved_Instruction;
	P_Special[12] = P_RSP_Reserved_Instruction;
	P_Special[13] = P_RSP_BREAK;
	P_Special[14] = P_RSP_Reserved_Instruction;
	P_Special[15] = P_RSP_Reserved_Instruction;
	P_Special[16] = P_RSP_Reserved_Instruction;
	P_Special[17] = P_RSP_Reserved_Instruction;
	P_Special[18] = P_RSP_Reserved_Instruction;
	P_Special[19] = P_RSP_Reserved_Instruction;
	P_Special[20] = P_RSP_Reserved_Instruction;
	P_Special[21] = P_RSP_Reserved_Instruction;
	P_Special[22] = P_RSP_Reserved_Instruction;
	P_Special[23] = P_RSP_Reserved_Instruction;
	P_Special[24] = P_RSP_Reserved_Instruction;
	P_Special[25] = P_RSP_Reserved_Instruction;
	P_Special[26] = P_RSP_Reserved_Instruction;
	P_Special[27] = P_RSP_Reserved_Instruction;
	P_Special[28] = P_RSP_Reserved_Instruction;
	P_Special[29] = P_RSP_Reserved_Instruction;
	P_Special[30] = P_RSP_Reserved_Instruction;
	P_Special[31] = P_RSP_Reserved_Instruction;
	P_Special[32] = P_RSP_ADD;
	P_Special[33] = P_RSP_ADDU;
	P_Special[34] = P_RSP_SUB;
	P_Special[35] = P_RSP_SUBU;
	P_Special[36] = P_RSP_AND;
	P_Special[37] = P_RSP_OR;
	P_Special[38] = P_RSP_XOR;
	P_Special[39] = P_RSP_NOR;
	P_Special[40] = P_RSP_Reserved_Instruction;
	P_Special[41] = P_RSP_Reserved_Instruction;
	P_Special[42] = P_RSP_SLT;
	P_Special[43] = P_RSP_SLTU;
	P_Special[44] = P_RSP_Reserved_Instruction;
	P_Special[45] = P_RSP_Reserved_Instruction;
	P_Special[46] = P_RSP_Reserved_Instruction;
	P_Special[47] = P_RSP_Reserved_Instruction;
	P_Special[48] = P_RSP_Reserved_Instruction;
	P_Special[49] = P_RSP_Reserved_Instruction;
	P_Special[50] = P_RSP_Reserved_Instruction;
	P_Special[51] = P_RSP_Reserved_Instruction;
	P_Special[52] = P_RSP_Reserved_Instruction;
	P_Special[53] = P_RSP_Reserved_Instruction;
	P_Special[54] = P_RSP_Reserved_Instruction;
	P_Special[55] = P_RSP_Reserved_Instruction;
	P_Special[56] = P_RSP_Reserved_Instruction;
	P_Special[57] = P_RSP_Reserved_Instruction;
	P_Special[58] = P_RSP_Reserved_Instruction;
	P_Special[59] = P_RSP_Reserved_Instruction;
	P_Special[60] = P_RSP_Reserved_Instruction;
	P_Special[61] = P_RSP_Reserved_Instruction;
	P_Special[62] = P_RSP_Reserved_Instruction;
	P_Special[63] = P_RSP_Reserved_Instruction;

	/* Set up Register Immediate Instructions */
	P_RegIMM[0] = P_RSP_BLTZ;
	P_RegIMM[1] = P_RSP_BGEZ;
	P_RegIMM[2] = P_RSP_Reserved_Instruction;
	P_RegIMM[3] = P_RSP_Reserved_Instruction;
	P_RegIMM[4] = P_RSP_Reserved_Instruction;
	P_RegIMM[5] = P_RSP_Reserved_Instruction;
	P_RegIMM[6] = P_RSP_Reserved_Instruction;
	P_RegIMM[7] = P_RSP_Reserved_Instruction;
	P_RegIMM[8] = P_RSP_Reserved_Instruction;
	P_RegIMM[9] = P_RSP_Reserved_Instruction;
	P_RegIMM[10] = P_RSP_Reserved_Instruction;
	P_RegIMM[11] = P_RSP_Reserved_Instruction;
	P_RegIMM[12] = P_RSP_Reserved_Instruction;
	P_RegIMM[13] = P_RSP_Reserved_Instruction;
	P_RegIMM[14] = P_RSP_Reserved_Instruction;
	P_RegIMM[15] = P_RSP_Reserved_Instruction;
	P_RegIMM[16] = P_RSP_BLTZAL;
	P_RegIMM[17] = P_RSP_BGEZAL;
	P_RegIMM[18] = P_RSP_Reserved_Instruction;
	P_RegIMM[19] = P_RSP_Reserved_Instruction;
	P_RegIMM[20] = P_RSP_Reserved_Instruction;
	P_RegIMM[21] = P_RSP_Reserved_Instruction;
	P_RegIMM[22] = P_RSP_Reserved_Instruction;
	P_RegIMM[23] = P_RSP_Reserved_Instruction;
	P_RegIMM[24] = P_RSP_Reserved_Instruction;
	P_RegIMM[25] = P_RSP_Reserved_Instruction;
	P_RegIMM[26] = P_RSP_Reserved_Instruction;
	P_RegIMM[27] = P_RSP_Reserved_Instruction;
	P_RegIMM[28] = P_RSP_Reserved_Instruction;
	P_RegIMM[29] = P_RSP_Reserved_Instruction;
	P_RegIMM[30] = P_RSP_Reserved_Instruction;
	P_RegIMM[31] = P_RSP_Reserved_Instruction;

	P_Cop0[0] = P_RSP_MFC0;
	P_Cop0[1] = P_RSP_Reserved_Instruction;
	P_Cop0[2] = P_RSP_Reserved_Instruction;
	P_Cop0[3] = P_RSP_Reserved_Instruction;
	P_Cop0[4] = P_RSP_MTC0;
	P_Cop0[5] = P_RSP_Reserved_Instruction;
	P_Cop0[6] = P_RSP_Reserved_Instruction;
	P_Cop0[7] = P_RSP_Reserved_Instruction;
	P_Cop0[8] = P_RSP_Reserved_Instruction;
	P_Cop0[9] = P_RSP_Reserved_Instruction;
	P_Cop0[10] = P_RSP_Reserved_Instruction;
	P_Cop0[11] = P_RSP_Reserved_Instruction;
	P_Cop0[12] = P_RSP_Reserved_Instruction;
	P_Cop0[13] = P_RSP_Reserved_Instruction;
	P_Cop0[14] = P_RSP_Reserved_Instruction;
	P_Cop0[15] = P_RSP_Reserved_Instruction;
	P_Cop0[16] = P_RSP_Reserved_Instruction;
	P_Cop0[17] = P_RSP_Reserved_Instruction;
	P_Cop0[18] = P_RSP_Reserved_Instruction;
	P_Cop0[19] = P_RSP_Reserved_Instruction;
	P_Cop0[20] = P_RSP_Reserved_Instruction;
	P_Cop0[21] = P_RSP_Reserved_Instruction;
	P_Cop0[22] = P_RSP_Reserved_Instruction;
	P_Cop0[23] = P_RSP_Reserved_Instruction;
	P_Cop0[24] = P_RSP_Reserved_Instruction;
	P_Cop0[25] = P_RSP_Reserved_Instruction;
	P_Cop0[26] = P_RSP_Reserved_Instruction;
	P_Cop0[27] = P_RSP_Reserved_Instruction;
	P_Cop0[28] = P_RSP_Reserved_Instruction;
	P_Cop0[29] = P_RSP_Reserved_Instruction;
	P_Cop0[30] = P_RSP_Reserved_Instruction;
	P_Cop0[31] = P_RSP_Reserved_Instruction;

	P_Cop2[0] = P_RSP_MFC2;
	P_Cop2[1] = P_RSP_Reserved_Instruction;
	P_Cop2[2] = P_RSP_CFC2;
	P_Cop2[3] = P_RSP_Reserved_Instruction;
	P_Cop2[4] = P_RSP_MTC2;
	P_Cop2[5] = P_RSP_Reserved_Instruction;
	P_Cop2[6] = P_RSP_CTC2;
	P_Cop2[7] = P_RSP_Reserved_Instruction;
	P_Cop2[8] = P_RSP_Reserved_Instruction;
	P_Cop2[9] = P_RSP_Reserved_Instruction;
	P_Cop2[10] = P_RSP_Reserved_Instruction;
	P_Cop2[11] = P_RSP_Reserved_Instruction;
	P_Cop2[12] = P_RSP_Reserved_Instruction;
	P_Cop2[13] = P_RSP_Reserved_Instruction;
	P_Cop2[14] = P_RSP_Reserved_Instruction;
	P_Cop2[15] = P_RSP_Reserved_Instruction;
	P_Cop2[16] = P_RSP_VECTOP;
	P_Cop2[17] = P_RSP_VECTOP;
	P_Cop2[18] = P_RSP_VECTOP;
	P_Cop2[19] = P_RSP_VECTOP;
	P_Cop2[20] = P_RSP_VECTOP;
	P_Cop2[21] = P_RSP_VECTOP;
	P_Cop2[22] = P_RSP_VECTOP;
	P_Cop2[23] = P_RSP_VECTOP;
	P_Cop2[24] = P_RSP_VECTOP;
	P_Cop2[25] = P_RSP_VECTOP;
	P_Cop2[26] = P_RSP_VECTOP;
	P_Cop2[27] = P_RSP_VECTOP;
	P_Cop2[28] = P_RSP_VECTOP;
	P_Cop2[29] = P_RSP_VECTOP;
	P_Cop2[30] = P_RSP_VECTOP;
	P_Cop2[31] = P_RSP_VECTOP;

	P_VectOp[0] = P_RSP_VMULF;
	P_VectOp[1] = P_RSP_VMULU;
	P_VectOp[2] = P_RSP_VRNDP;
	P_VectOp[3] = P_RSP_VMULQ;
	P_VectOp[4] = P_RSP_VMUDL;
	P_VectOp[5] = P_RSP_VMUDM;
	P_VectOp[6] = P_RSP_VMUDN;
	P_VectOp[7] = P_RSP_VMUDH;
	P_VectOp[8] = P_RSP_VMACF;
	P_VectOp[9] = P_RSP_VMACU;
	P_VectOp[10] = P_RSP_VRNDN;
	P_VectOp[11] = P_RSP_VMACQ;
	P_VectOp[12] = P_RSP_VMADL;
	P_VectOp[13] = P_RSP_VMADM;
	P_VectOp[14] = P_RSP_VMADN;
	P_VectOp[15] = P_RSP_VMADH;
	P_VectOp[16] = P_RSP_VADD;
	P_VectOp[17] = P_RSP_VSUB;
	P_VectOp[18] = P_RSP_VSUT;
	P_VectOp[19] = P_RSP_VABS;
	P_VectOp[20] = P_RSP_VADDC;
	P_VectOp[21] = P_RSP_VSUBC;
	P_VectOp[22] = P_RSP_VADDB;
	P_VectOp[23] = P_RSP_VSUBB;
	P_VectOp[24] = P_RSP_VACCB;
	P_VectOp[25] = P_RSP_VSUCB;
	P_VectOp[26] = P_RSP_VSAD;
	P_VectOp[27] = P_RSP_VSAC;
	P_VectOp[28] = P_RSP_VSUM;
	P_VectOp[29] = P_RSP_VSAW;
	P_VectOp[30] = P_RSP_Reserved_Instruction;
	P_VectOp[31] = P_RSP_Reserved_Instruction;
	P_VectOp[32] = P_RSP_VLT;
	P_VectOp[33] = P_RSP_VEQ;
	P_VectOp[34] = P_RSP_VNE;
	P_VectOp[35] = P_RSP_VGE;
	P_VectOp[36] = P_RSP_VCL;
	P_VectOp[37] = P_RSP_VCH;
	P_VectOp[38] = P_RSP_VCR;
	P_VectOp[39] = P_RSP_VMRG;
	P_VectOp[40] = P_RSP_VAND;
	P_VectOp[41] = P_RSP_VNAND;
	P_VectOp[42] = P_RSP_VOR;
	P_VectOp[43] = P_RSP_VNOR;
	P_VectOp[44] = P_RSP_VXOR;
	P_VectOp[45] = P_RSP_VNXOR;
	P_VectOp[46] = P_RSP_Reserved_Instruction;
	P_VectOp[47] = P_RSP_Reserved_Instruction;
	P_VectOp[48] = P_RSP_VRCP;
	P_VectOp[49] = P_RSP_VRCPL;
	P_VectOp[50] = P_RSP_VRCPH;
	P_VectOp[51] = P_RSP_VMOV;
	P_VectOp[52] = P_RSP_VRSQ;
	P_VectOp[53] = P_RSP_VRSQL;
	P_VectOp[54] = P_RSP_VRSQH;
	P_VectOp[55] = P_RSP_VNOOP;
	P_VectOp[56] = P_RSP_VEXTT;
	P_VectOp[57] = P_RSP_VEXTQ;
	P_VectOp[58] = P_RSP_VEXTN;
	P_VectOp[59] = P_RSP_Reserved_Instruction;
	P_VectOp[60] = P_RSP_VINST;
	P_VectOp[61] = P_RSP_VINSQ;
	P_VectOp[62] = P_RSP_VINSN;
	P_VectOp[63] = P_RSP_Reserved_Instruction;

	Cop0_Regs[0] = CPU_RSP_SP_RegWrite_MEM_ADDR;
	Cop0_Regs[1] = CPU_RSP_SP_RegWrite_DRAM_ADDR;
	Cop0_Regs[2] = CPU_RSP_SP_RegWrite_RD_LEN;
	Cop0_Regs[3] = CPU_RSP_SP_RegWrite_WR_LEN;
	Cop0_Regs[4] = CPU_RSP_SP_RegWrite_STATUS;
	Cop0_Regs[5] = CPU_RSP_SP_RegWrite_DMA_FULL;
	Cop0_Regs[6] = CPU_RSP_SP_RegWrite_DMA_BUSY;
	Cop0_Regs[7] = CPU_RSP_SP_RegWrite_SEMAPHORE;
	Cop0_Regs[8] = CPU_RSP_DPC_RegWrite_START;
	Cop0_Regs[9] = CPU_RSP_DPC_RegWrite_END;
	Cop0_Regs[10] = CPU_RSP_DPC_RegWrite_CURRENT;
	Cop0_Regs[11] = CPU_RSP_DPC_RegWrite_STATUS;
	Cop0_Regs[12] = CPU_RSP_DPC_RegWrite_CLOCK;
	Cop0_Regs[13] = CPU_RSP_DPC_RegWrite_BUFBUSY;
	Cop0_Regs[14] = CPU_RSP_DPC_RegWrite_PIPEBUSY;
	Cop0_Regs[15] = CPU_RSP_DPC_RegWrite_TMEM;

	Cop0_Addr[0] = &spreg.mem_addr;
	Cop0_Addr[1] = &spreg.dram_addr;
	Cop0_Addr[2] = &spreg.read_len;
	Cop0_Addr[3] = &spreg.write_len;
	Cop0_Addr[4] = &spreg.status;
	Cop0_Addr[5] = &spreg.dma_full;
	Cop0_Addr[6] = &spreg.dma_busy;
	Cop0_Addr[7] = &spreg.semaphore;
	Cop0_Addr[8] = &dpcreg.start;
	Cop0_Addr[9] = &dpcreg.end;
	Cop0_Addr[10] = &dpcreg.current;
	Cop0_Addr[11] = &dpcreg.status;
	Cop0_Addr[12] = &dpcreg.clock;
	Cop0_Addr[13] = &dpcreg.bufbusy;
	Cop0_Addr[14] = &dpcreg.pipebusy;
	Cop0_Addr[15] = &dpcreg.tmem;

    // Do a reset on the RSP first, before execution.
    Cold_Reset();

    // Create RSP events for debugging and other assorted purposes.
    hRSPRunEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
    hRSPDebugEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

    // Init RSP vars..
    RSP_want_to_exit = FALSE;
    RSP_running = FALSE;

    // Create the RSP thread and fire it off.
    hRSPThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)RSPThreadFunc, this, CREATE_SUSPENDED, &ThreadID);
	ResumeThread(hRSPThread);
}

RSP_Processor::~RSP_Processor()
{
    // Flag the RSP to stop.
    RSP_want_to_exit = TRUE;
    RSP_running = FALSE;
    SetEvent(hRSPRunEvent);

    // Wait for the RSP to shut down.
    WaitForSingleObject(hRSPThread, INFINITE);

    // Cleanup.
    CloseHandle(hRSPThread);
    hRSPThread = NULL;
}

void RSP_Processor::Cold_Reset(void)
{
	int t;

    // Initialize SP Interface...
    spreg.mem_addr  = 0x00000000;
    spreg.dram_addr = 0x00000000;
    spreg.read_len  = 0x00000000;
    spreg.write_len = 0x00000000;
    spreg.status    = SP_STATUS_HALT | SP_STATUS_BROKE;
    spreg.dma_full  = 0x00000000;
    spreg.dma_busy  = 0x00000000;
    spreg.semaphore = 0x00000000;

	// Initialize DP Interface...
    dpcreg.start	= 0x00000000;
    dpcreg.end		= 0x00000000;
    dpcreg.current	= 0x00000000;
    dpcreg.status	= 0x00000000;
    dpcreg.clock	= 0x00000000;
    dpcreg.bufbusy	= 0x00000000;
    dpcreg.pipebusy	= 0x00000000;
    dpcreg.tmem		= 0x00000000;

	// Zap RSP's GPRs and vector regs.
	for (t = 0; t < 32; t++)
	{
		RSP_GPR[t] = 0x00000000;
		V[t].d[0]  = 0x0000000000000000;
		V[t].d[1]  = 0x0000000000000000;
	}

	// Zap accumulators.
	for (t = 0; t < 8; t++)
	{
		AccumH[t] = 0x0000;
		AccumN[t] = 0x0000;
	}

	// Zap flags.
	for (t = 0; t < 4; t++)
		VFlags[t] = 0x00000000;
}

void RSP_Processor::RSP_Start(void)
{
    if (RSP_running) return;

	NextPC = sp_pc.PC;

	/* Load the instuction */
	Instruction = RSP_Read32(SP_IMEM_BASE + (sp_pc.PC & 0xFFF));

	// Only start the RSP if we're not in the debugger...
	if (!inDebugger)
	{
		RSP_running = TRUE;
		SetEvent(hRSPRunEvent);
	}
}

void RSP_Processor::RSP_Stop(void)
{
    if (!RSP_running) return;

	RSP_running = FALSE;

    // Wait for the RSP to finish it's current opcode.
    WaitForSingleObject(hRSPDebugEvent, INFINITE);
	spreg.status |= SP_STATUS_HALT | SP_STATUS_BROKE;
}

void RSP_Processor::DoThread(void)
{
	__try
	{
		for (;;)
		{
			if (RSP_running == FALSE)
			{
				if (RSP_want_to_exit == TRUE) return;

				// Flag our debug event, saying we just finished the opcode.
				SetEvent(hRSPDebugEvent);

				// Now wait for our run event to get flagged before we go on.
				WaitForSingleObject(hRSPRunEvent, INFINITE);

				// Check if we should exit again...
				if (RSP_want_to_exit == TRUE) return;
			}

			// Do next opcode...
			/* Move Program Counter */	

			NextPC = SP_IMEM_BASE + ((NextPC + 4) & 0x0FFC);
			sp_pc.PC = NextPC;


			/* Call Correct Routine for Instruction */
			(this->*Opcode[(Instruction & 0xFC000000) >> 26])(); /* Array of function pointers */

			/* Load the instuction */
			Instruction = RSP_Read32(SP_IMEM_BASE + (sp_pc.PC & 0x0FFC));
		}
	}
	__except (Eval_EmulationException(GetExceptionInformation()))
	{
		ulong base_addr;
		char buf[256];

		// Check in_MemCopy and in_MemSet variables first...
		if (in_MemCopy)
		{
			sprintf(buf, "Attempt to DMA to unmapped memory via RSP! Address = %08X, PC = %08X\n\nEmulation has been terminated.", MemCopy_dest, sp_pc.PC);
			MessageBox(NULL, buf, "Fatal Non-recoverable Error", MB_OK);
		}
		else
		{
			if (in_MemSet)
			{
				sprintf(buf, "Attempt to MemSet unmapped memory via RSP! Address = %08X, PC = %08X\n\nEmulation has been terminated.", MemSet_dest, sp_pc.PC);
				MessageBox(NULL, buf, "Fatal Non-recoverable Error", MB_OK);
			}
			else
			{
				// Try to determine if this was an access to the memory map by examining ESI and seeing if it's within bounds of
				// the N64Memory -> N64Memory + 512Mb address.

				if ((xp.ContextRecord->Esi >= (ulong)N64Memory) && (xp.ContextRecord->Esi <= (ulong)((char *)N64Memory + 0x20000000)))
				{
					base_addr = (ulong)xp.ContextRecord->Esi - (ulong)N64Memory;
					sprintf(buf, "Attempt to access unmapped memory via RSP! Address = %08X, PC = %08X\n\nEmulation has been terminated.", base_addr, sp_pc.PC);
					MessageBox(NULL, buf, "Fatal Non-recoverable Error", MB_OK);
				}
				else
				{
					MessageBox(NULL, "Unhandled access violation, emulation has been terminated.", "Fatal Non-recoverable Error", MB_OK);
				}
			}
		}

		RSP_running = FALSE;
	};
}

// *******************************************************************************************************
// *******************************************************************************************************
//
//                                           OPCODE PRINTING
//
// *******************************************************************************************************
// *******************************************************************************************************

void RSP_Processor::P_RSP_SPECIAL(char *buf)
{
	(this->*P_Special[DECODE_FUNCTION])(buf);
}

void RSP_Processor::P_RSP_RegIMM(char *buf)
{
	(this->*P_RegIMM[DECODE_RT])(buf);
}

void RSP_Processor::P_RSP_Reserved_Instruction(char *buf)
{ 
	strcpy(buf, "???");
}

void RSP_Processor::P_RSP_COP0(char *buf)
{
	(this->*P_Cop0[DECODE_RS])(buf);
}

void RSP_Processor::P_RSP_COP2(char *buf)
{
	(this->*P_Cop2[DECODE_RS])(buf);
}

void RSP_Processor::P_RSP_VECTOP(char *buf)
{
	(this->*P_VectOp[DECODE_FUNCTION])(buf);
}

// -------------------------------------------------------------------
//
//                       RSP Opcodes
//
// -------------------------------------------------------------------

void RSP_Processor::P_RSP_J(char *buf)     { sprintf(buf, "J\t0x%08X",			   DECODE_JUMP); }
void RSP_Processor::P_RSP_JAL(char *buf)   { sprintf(buf, "JAL\t0x%08X",		   DECODE_JUMP); }
void RSP_Processor::P_RSP_BEQ(char *buf)   { sprintf(buf, "BEQ\t%s, %s, 0x%08X",   GPR_LUT[DECODE_RS], GPR_LUT[DECODE_RT], DECODE_OFFSET); }
void RSP_Processor::P_RSP_BNE(char *buf)   { sprintf(buf, "BNE\t%s, %s, 0x%08X",   GPR_LUT[DECODE_RS], GPR_LUT[DECODE_RT], DECODE_OFFSET); }
void RSP_Processor::P_RSP_BLEZ(char *buf)  { sprintf(buf, "BLEZ\t%s, 0x%08X",      GPR_LUT[DECODE_RS], DECODE_OFFSET); }
void RSP_Processor::P_RSP_BGTZ(char *buf)  { sprintf(buf, "BGTZ\t%s, 0x%08X",      GPR_LUT[DECODE_RS], DECODE_OFFSET); }
void RSP_Processor::P_RSP_ADDI(char *buf)  { sprintf(buf, "ADDI\t%s, %s, 0x%04X",  GPR_LUT[DECODE_RT], GPR_LUT[DECODE_RS], DECODE_IMMED); }
void RSP_Processor::P_RSP_ADDIU(char *buf) { sprintf(buf, "ADDIU\t%s, %s, 0x%04X", GPR_LUT[DECODE_RT], GPR_LUT[DECODE_RS], DECODE_IMMED); }
void RSP_Processor::P_RSP_SLTI(char *buf)  { sprintf(buf, "SLTI\t%s, %s, 0x%04X",  GPR_LUT[DECODE_RT], GPR_LUT[DECODE_RS], DECODE_IMMED); }
void RSP_Processor::P_RSP_SLTIU(char *buf) { sprintf(buf, "SLTIU\t%s, %s, 0x%04X", GPR_LUT[DECODE_RT], GPR_LUT[DECODE_RS], DECODE_IMMED); }
void RSP_Processor::P_RSP_ANDI(char *buf)  { sprintf(buf, "ANDI\t%s, %s, 0x%04X",  GPR_LUT[DECODE_RT], GPR_LUT[DECODE_RS], DECODE_IMMED); }
void RSP_Processor::P_RSP_ORI(char *buf)   { sprintf(buf, "ORI\t%s, %s, 0x%04X",   GPR_LUT[DECODE_RT], GPR_LUT[DECODE_RS], DECODE_IMMED); }
void RSP_Processor::P_RSP_XORI(char *buf)  { sprintf(buf, "XORI\t%s, %s, 0x%04X",  GPR_LUT[DECODE_RT], GPR_LUT[DECODE_RS], DECODE_IMMED); }
void RSP_Processor::P_RSP_LUI(char *buf)   { sprintf(buf, "LUI\t%s, 0x%04X",       GPR_LUT[DECODE_RT], DECODE_IMMED); }
void RSP_Processor::P_RSP_LB(char *buf)    { sprintf(buf, "LB\t%s, 0x%04X(%s)",    GPR_LUT[DECODE_RT], DECODE_IMMED, GPR_LUT[DECODE_BASE]); }
void RSP_Processor::P_RSP_LH(char *buf)    { sprintf(buf, "LH\t%s, 0x%04X(%s)",    GPR_LUT[DECODE_RT], DECODE_IMMED, GPR_LUT[DECODE_BASE]); }
void RSP_Processor::P_RSP_LW(char *buf)    { sprintf(buf, "LW\t%s, 0x%04X(%s)",    GPR_LUT[DECODE_RT], DECODE_IMMED, GPR_LUT[DECODE_BASE]); }
void RSP_Processor::P_RSP_LBU(char *buf)   { sprintf(buf, "LBU\t%s, 0x%04X(%s)",   GPR_LUT[DECODE_RT], DECODE_IMMED, GPR_LUT[DECODE_BASE]); }
void RSP_Processor::P_RSP_LHU(char *buf)   { sprintf(buf, "LHU\t%s, 0x%04X(%s)",   GPR_LUT[DECODE_RT], DECODE_IMMED, GPR_LUT[DECODE_BASE]); }
void RSP_Processor::P_RSP_SB(char *buf)    { sprintf(buf, "SB\t%s, 0x%04X(%s)",    GPR_LUT[DECODE_RT], DECODE_IMMED, GPR_LUT[DECODE_BASE]); }
void RSP_Processor::P_RSP_SH(char *buf)    { sprintf(buf, "SH\t%s, 0x%04X(%s)",    GPR_LUT[DECODE_RT], DECODE_IMMED, GPR_LUT[DECODE_BASE]); }
void RSP_Processor::P_RSP_SW(char *buf)    { sprintf(buf, "SW\t%s, 0x%04X(%s)",    GPR_LUT[DECODE_RT], DECODE_IMMED, GPR_LUT[DECODE_BASE]); }

void RSP_Processor::P_RSP_LWC2(char *buf)
{ 
	char ch;
	schar ofs;
	slong offset;

	ofs = raw_opcode[3] & 0x7F;
	if (ofs & 0x40) ofs |= 0x80;		// Extend sign bit.
	offset = (slong)ofs << VectorShiftTable[DECODE_C2TYPE];
	ch = VectorCodeTable[DECODE_C2TYPE];

	sprintf(buf, "L%cV\t%s[%d], %d(%s)", ch, COP2_LUT[DECODE_RT], DECODE_SA >> 1, offset, GPR_LUT[DECODE_BASE]);
}

void RSP_Processor::P_RSP_SWC2(char *buf)
{ 
	char ch;
	schar ofs;
	slong offset;

	ofs = raw_opcode[3] & 0x7F;
	if (ofs & 0x40) ofs |= 0x80;		// Extend sign bit.
	offset = (slong)ofs << VectorShiftTable[DECODE_C2TYPE];
	ch = VectorCodeTable[DECODE_C2TYPE];

	sprintf(buf, "S%cV\t%s[%d], %d(%s)", ch, COP2_LUT[DECODE_RT], DECODE_SA >> 1, offset, GPR_LUT[DECODE_BASE]);
}

// -------------------------------------------------------------------
//
//                       Special Opcodes
//
// -------------------------------------------------------------------

void RSP_Processor::P_RSP_SLL(char *buf)
{
    if (raw_opcode_ulong == 0x00000000)
        strcpy(buf, "NOP");
    else
        sprintf(buf, "SLL\t%s, %s, 0x%02X", GPR_LUT[DECODE_RD], GPR_LUT[DECODE_RT], DECODE_SA);
}

void RSP_Processor::P_RSP_SRL(char *buf)   { sprintf(buf, "SRL\t%s, %s, 0x%02X", GPR_LUT[DECODE_RD], GPR_LUT[DECODE_RT], DECODE_SA); }
void RSP_Processor::P_RSP_SRA(char *buf)   { sprintf(buf, "SRA\t%s, %s, 0x%02X", GPR_LUT[DECODE_RD], GPR_LUT[DECODE_RT], DECODE_SA); }
void RSP_Processor::P_RSP_SLLV(char *buf)  { sprintf(buf, "SLLV\t%s, %s, %s",    GPR_LUT[DECODE_RD], GPR_LUT[DECODE_RT], GPR_LUT[DECODE_RS]); }
void RSP_Processor::P_RSP_SRLV(char *buf)  { sprintf(buf, "SRLV\t%s, %s, %s",    GPR_LUT[DECODE_RD], GPR_LUT[DECODE_RT], GPR_LUT[DECODE_RS]); }
void RSP_Processor::P_RSP_SRAV(char *buf)  { sprintf(buf, "SRAV\t%s, %s, %s",    GPR_LUT[DECODE_RD], GPR_LUT[DECODE_RT], GPR_LUT[DECODE_RS]); }
void RSP_Processor::P_RSP_JR(char *buf)    { sprintf(buf, "JR\t%s",              GPR_LUT[DECODE_RS]); }
void RSP_Processor::P_RSP_BREAK(char *buf) { sprintf(buf, "BREAK\t0x%05X",       DECODE_BREAK); }
void RSP_Processor::P_RSP_ADD(char *buf)   { sprintf(buf, "ADD\t%s, %s, %s",     GPR_LUT[DECODE_RD], GPR_LUT[DECODE_RS], GPR_LUT[DECODE_RT]); }
void RSP_Processor::P_RSP_ADDU(char *buf)  { sprintf(buf, "ADDU\t%s, %s, %s",    GPR_LUT[DECODE_RD], GPR_LUT[DECODE_RS], GPR_LUT[DECODE_RT]); }
void RSP_Processor::P_RSP_SUB(char *buf)   { sprintf(buf, "SUB\t%s, %s, %s",     GPR_LUT[DECODE_RD], GPR_LUT[DECODE_RS], GPR_LUT[DECODE_RT]); }
void RSP_Processor::P_RSP_SUBU(char *buf)  { sprintf(buf, "SUBU\t%s, %s, %s",    GPR_LUT[DECODE_RD], GPR_LUT[DECODE_RS], GPR_LUT[DECODE_RT]); }
void RSP_Processor::P_RSP_AND(char *buf)   { sprintf(buf, "AND\t%s, %s, %s",     GPR_LUT[DECODE_RD], GPR_LUT[DECODE_RS], GPR_LUT[DECODE_RT]); }
void RSP_Processor::P_RSP_OR(char *buf)    { sprintf(buf, "OR\t%s, %s, %s",      GPR_LUT[DECODE_RD], GPR_LUT[DECODE_RS], GPR_LUT[DECODE_RT]); }
void RSP_Processor::P_RSP_XOR(char *buf)   { sprintf(buf, "XOR\t%s, %s, %s",     GPR_LUT[DECODE_RD], GPR_LUT[DECODE_RS], GPR_LUT[DECODE_RT]); }
void RSP_Processor::P_RSP_NOR(char *buf)   { sprintf(buf, "NOR\t%s, %s, %s",     GPR_LUT[DECODE_RD], GPR_LUT[DECODE_RS], GPR_LUT[DECODE_RT]); }
void RSP_Processor::P_RSP_SLT(char *buf)   { sprintf(buf, "SLT\t%s, %s, %s",     GPR_LUT[DECODE_RD], GPR_LUT[DECODE_RS], GPR_LUT[DECODE_RT]); }
void RSP_Processor::P_RSP_SLTU(char *buf)  { sprintf(buf, "SLTU\t%s, %s, %s",    GPR_LUT[DECODE_RD], GPR_LUT[DECODE_RS], GPR_LUT[DECODE_RT]); }

// -------------------------------------------------------------------
//
//                       REGIMM Opcodes
//
// -------------------------------------------------------------------

void RSP_Processor::P_RSP_BLTZ(char *buf)   { sprintf(buf, "BLTZ\t%s, 0x%08X",    GPR_LUT[DECODE_RS], DECODE_OFFSET); }
void RSP_Processor::P_RSP_BGEZ(char *buf)   { sprintf(buf, "BGEZ\t%s, 0x%08X",    GPR_LUT[DECODE_RS], DECODE_OFFSET); }
void RSP_Processor::P_RSP_BLTZAL(char *buf) { sprintf(buf, "BLTZAL\t%s, 0x%08X",  GPR_LUT[DECODE_RS], DECODE_OFFSET); }
void RSP_Processor::P_RSP_BGEZAL(char *buf) { sprintf(buf, "BGEZAL\t%s, 0x%08X",  GPR_LUT[DECODE_RS], DECODE_OFFSET); }

// -------------------------------------------------------------------
//
//                          COP0 Opcodes
//
// -------------------------------------------------------------------

void RSP_Processor::P_RSP_MTC0(char *buf)  { sprintf(buf, "MTC0\t%s, %s", GPR_LUT[DECODE_RT], RSP_LUT[DECODE_FS]); }
void RSP_Processor::P_RSP_MFC0(char *buf)  { sprintf(buf, "MFC0\t%s, %s", GPR_LUT[DECODE_RT], RSP_LUT[DECODE_FS]); }

// -------------------------------------------------------------------
//
//                          COP2 Opcodes
//
// -------------------------------------------------------------------

void RSP_Processor::P_RSP_MTC2(char *buf)  { sprintf(buf, "MTC2\t%s, %s[%d]",   GPR_LUT[DECODE_RT], COP2_LUT[DECODE_FS], (DECODE_SA >> 1) & 0x0F); }
void RSP_Processor::P_RSP_MFC2(char *buf)  { sprintf(buf, "MFC2\t%s, %s[%d]",   GPR_LUT[DECODE_RT], COP2_LUT[DECODE_FS], (DECODE_SA >> 1) & 0x0F); }
void RSP_Processor::P_RSP_CTC2(char *buf)  { sprintf(buf, "CTC2\t%s, flag[%d]", GPR_LUT[DECODE_RT], DECODE_RD & 0x03); }
void RSP_Processor::P_RSP_CFC2(char *buf)  { sprintf(buf, "CFC2\t%s, flag[%d]", GPR_LUT[DECODE_RT], DECODE_RD & 0x03); }

// -------------------------------------------------------------------
//
//                         Vector Opcodes
//
// -------------------------------------------------------------------

void RSP_Processor::P_RSP_VectorOp(char *buf, char *op)
{
	switch (DECODE_RS & 0x0F)
	{
		case 0x00: sprintf(buf, "%s\t%s, %s, %s",     op, COP2_LUT[DECODE_C2VEC], COP2_LUT[DECODE_RD], COP2_LUT[DECODE_RT]); break;
		case 0x01: sprintf(buf, "%s ???",             op);
		case 0x02: sprintf(buf, "%s\t%s, %s, %s[0q]", op, COP2_LUT[DECODE_C2VEC], COP2_LUT[DECODE_RD], COP2_LUT[DECODE_RT]); break;
		case 0x03: sprintf(buf, "%s\t%s, %s, %s[1q]", op, COP2_LUT[DECODE_C2VEC], COP2_LUT[DECODE_RD], COP2_LUT[DECODE_RT]); break;
		case 0x04: sprintf(buf, "%s\t%s, %s, %s[0h]", op, COP2_LUT[DECODE_C2VEC], COP2_LUT[DECODE_RD], COP2_LUT[DECODE_RT]); break;
		case 0x05: sprintf(buf, "%s\t%s, %s, %s[1h]", op, COP2_LUT[DECODE_C2VEC], COP2_LUT[DECODE_RD], COP2_LUT[DECODE_RT]); break;
		case 0x06: sprintf(buf, "%s\t%s, %s, %s[2h]", op, COP2_LUT[DECODE_C2VEC], COP2_LUT[DECODE_RD], COP2_LUT[DECODE_RT]); break;
		case 0x07: sprintf(buf, "%s\t%s, %s, %s[3h]", op, COP2_LUT[DECODE_C2VEC], COP2_LUT[DECODE_RD], COP2_LUT[DECODE_RT]); break;
		case 0x08: sprintf(buf, "%s\t%s, %s, %s[0]",  op, COP2_LUT[DECODE_C2VEC], COP2_LUT[DECODE_RD], COP2_LUT[DECODE_RT]); break;
		case 0x09: sprintf(buf, "%s\t%s, %s, %s[1]",  op, COP2_LUT[DECODE_C2VEC], COP2_LUT[DECODE_RD], COP2_LUT[DECODE_RT]); break;
		case 0x0A: sprintf(buf, "%s\t%s, %s, %s[2]",  op, COP2_LUT[DECODE_C2VEC], COP2_LUT[DECODE_RD], COP2_LUT[DECODE_RT]); break;
		case 0x0B: sprintf(buf, "%s\t%s, %s, %s[3]",  op, COP2_LUT[DECODE_C2VEC], COP2_LUT[DECODE_RD], COP2_LUT[DECODE_RT]); break;
		case 0x0C: sprintf(buf, "%s\t%s, %s, %s[4]",  op, COP2_LUT[DECODE_C2VEC], COP2_LUT[DECODE_RD], COP2_LUT[DECODE_RT]); break;
		case 0x0D: sprintf(buf, "%s\t%s, %s, %s[5]",  op, COP2_LUT[DECODE_C2VEC], COP2_LUT[DECODE_RD], COP2_LUT[DECODE_RT]); break;
		case 0x0E: sprintf(buf, "%s\t%s, %s, %s[6]",  op, COP2_LUT[DECODE_C2VEC], COP2_LUT[DECODE_RD], COP2_LUT[DECODE_RT]); break;
		case 0x0F: sprintf(buf, "%s\t%s, %s, %s[7]",  op, COP2_LUT[DECODE_C2VEC], COP2_LUT[DECODE_RD], COP2_LUT[DECODE_RT]); break;
	}
}

void RSP_Processor::P_RSP_VMULF(char *buf) { P_RSP_VectorOp(buf, "VMULF"); }
void RSP_Processor::P_RSP_VMULU(char *buf) { P_RSP_VectorOp(buf, "VMULU"); }
void RSP_Processor::P_RSP_VRNDP(char *buf) { P_RSP_VectorOp(buf, "VRNDP"); }
void RSP_Processor::P_RSP_VMULQ(char *buf) { P_RSP_VectorOp(buf, "VMULQ"); }
void RSP_Processor::P_RSP_VMUDL(char *buf) { P_RSP_VectorOp(buf, "VMUDL"); }
void RSP_Processor::P_RSP_VMUDM(char *buf) { P_RSP_VectorOp(buf, "VMUDM"); }
void RSP_Processor::P_RSP_VMUDN(char *buf) { P_RSP_VectorOp(buf, "VMUDN"); }
void RSP_Processor::P_RSP_VMUDH(char *buf) { P_RSP_VectorOp(buf, "VMUDH"); }
void RSP_Processor::P_RSP_VMACF(char *buf) { P_RSP_VectorOp(buf, "VMACF"); }
void RSP_Processor::P_RSP_VMACU(char *buf) { P_RSP_VectorOp(buf, "VMACU"); }
void RSP_Processor::P_RSP_VRNDN(char *buf) { P_RSP_VectorOp(buf, "VRNDN"); }
void RSP_Processor::P_RSP_VMACQ(char *buf) { P_RSP_VectorOp(buf, "VMACQ"); }
void RSP_Processor::P_RSP_VMADL(char *buf) { P_RSP_VectorOp(buf, "VMADL"); }
void RSP_Processor::P_RSP_VMADM(char *buf) { P_RSP_VectorOp(buf, "VMADM"); }
void RSP_Processor::P_RSP_VMADN(char *buf) { P_RSP_VectorOp(buf, "VMADN"); }
void RSP_Processor::P_RSP_VMADH(char *buf) { P_RSP_VectorOp(buf, "VMADH"); }
void RSP_Processor::P_RSP_VADD(char *buf)  { P_RSP_VectorOp(buf, "VADD"); }
void RSP_Processor::P_RSP_VSUB(char *buf)  { P_RSP_VectorOp(buf, "VSUB"); }
void RSP_Processor::P_RSP_VSUT(char *buf)  { P_RSP_VectorOp(buf, "VSUT"); }
void RSP_Processor::P_RSP_VABS(char *buf)  { P_RSP_VectorOp(buf, "VABS"); }
void RSP_Processor::P_RSP_VADDC(char *buf) { P_RSP_VectorOp(buf, "VADDC"); }
void RSP_Processor::P_RSP_VSUBC(char *buf) { P_RSP_VectorOp(buf, "VSUBC"); }
void RSP_Processor::P_RSP_VADDB(char *buf) { P_RSP_VectorOp(buf, "VADDB"); }
void RSP_Processor::P_RSP_VSUBB(char *buf) { P_RSP_VectorOp(buf, "VSUBB"); }
void RSP_Processor::P_RSP_VACCB(char *buf) { P_RSP_VectorOp(buf, "VACCB"); }
void RSP_Processor::P_RSP_VSUCB(char *buf) { P_RSP_VectorOp(buf, "VSUCB"); }
void RSP_Processor::P_RSP_VSAD(char *buf)  { P_RSP_VectorOp(buf, "VSAD"); }
void RSP_Processor::P_RSP_VSAC(char *buf)  { P_RSP_VectorOp(buf, "VSAC"); }
void RSP_Processor::P_RSP_VSUM(char *buf)  { P_RSP_VectorOp(buf, "VSUM"); }
void RSP_Processor::P_RSP_VSAW(char *buf)  { P_RSP_VectorOp(buf, "VSAW"); }
void RSP_Processor::P_RSP_VLT(char *buf)   { P_RSP_VectorOp(buf, "VLT"); }
void RSP_Processor::P_RSP_VEQ(char *buf)   { P_RSP_VectorOp(buf, "VEQ"); }
void RSP_Processor::P_RSP_VNE(char *buf)   { P_RSP_VectorOp(buf, "VNE"); }
void RSP_Processor::P_RSP_VGE(char *buf)   { P_RSP_VectorOp(buf, "VGE"); }
void RSP_Processor::P_RSP_VCL(char *buf)   { P_RSP_VectorOp(buf, "VCL"); }
void RSP_Processor::P_RSP_VCH(char *buf)   { P_RSP_VectorOp(buf, "VCH"); }
void RSP_Processor::P_RSP_VCR(char *buf)   { P_RSP_VectorOp(buf, "VCR"); }
void RSP_Processor::P_RSP_VMRG(char *buf)  { P_RSP_VectorOp(buf, "VMRG"); }
void RSP_Processor::P_RSP_VAND(char *buf)  { P_RSP_VectorOp(buf, "VAND"); }
void RSP_Processor::P_RSP_VNAND(char *buf) { P_RSP_VectorOp(buf, "VNAND"); }
void RSP_Processor::P_RSP_VOR(char *buf)   { P_RSP_VectorOp(buf, "VOR"); }
void RSP_Processor::P_RSP_VNOR(char *buf)  { P_RSP_VectorOp(buf, "VNOR"); }
void RSP_Processor::P_RSP_VXOR(char *buf)  { P_RSP_VectorOp(buf, "VXOR"); }
void RSP_Processor::P_RSP_VNXOR(char *buf) { P_RSP_VectorOp(buf, "VNXOR"); }
void RSP_Processor::P_RSP_VRCP(char *buf)  { sprintf(buf, "VRCP\t%s[%d], %s[%d]",  COP2_LUT[DECODE_C2VEC], DECODE_RD & 0x07, COP2_LUT[DECODE_RT], DECODE_RS & 0x07); }
void RSP_Processor::P_RSP_VRCPL(char *buf) { sprintf(buf, "VRCPL\t%s[%d], %s[%d]", COP2_LUT[DECODE_C2VEC], DECODE_RD & 0x07, COP2_LUT[DECODE_RT], DECODE_RS & 0x07); }
void RSP_Processor::P_RSP_VRCPH(char *buf) { sprintf(buf, "VRCPH\t%s[%d], %s[%d]", COP2_LUT[DECODE_C2VEC], DECODE_RD & 0x07, COP2_LUT[DECODE_RT], DECODE_RS & 0x07); }
void RSP_Processor::P_RSP_VMOV(char *buf)  { sprintf(buf, "VMOV\t%s[%d], %s[%d]",  COP2_LUT[DECODE_C2VEC], DECODE_RD & 0x07, COP2_LUT[DECODE_RT], DECODE_RS & 0x07); }
void RSP_Processor::P_RSP_VRSQ(char *buf)  { sprintf(buf, "VRSQ\t%s[%d], %s[%d]",  COP2_LUT[DECODE_C2VEC], DECODE_RD & 0x07, COP2_LUT[DECODE_RT], DECODE_RS & 0x07); }
void RSP_Processor::P_RSP_VRSQL(char *buf) { sprintf(buf, "VRSQL\t%s[%d], %s[%d]", COP2_LUT[DECODE_C2VEC], DECODE_RD & 0x07, COP2_LUT[DECODE_RT], DECODE_RS & 0x07); }
void RSP_Processor::P_RSP_VRSQH(char *buf) { sprintf(buf, "VRSQH\t%s[%d], %s[%d]", COP2_LUT[DECODE_C2VEC], DECODE_RD & 0x07, COP2_LUT[DECODE_RT], DECODE_RS & 0x07); }
void RSP_Processor::P_RSP_VNOOP(char *buf) { P_RSP_VectorOp(buf, "VNOOP"); }
void RSP_Processor::P_RSP_VEXTT(char *buf) { P_RSP_VectorOp(buf, "VEXTT"); }
void RSP_Processor::P_RSP_VEXTQ(char *buf) { P_RSP_VectorOp(buf, "VEXTQ"); }
void RSP_Processor::P_RSP_VEXTN(char *buf) { P_RSP_VectorOp(buf, "VEXTN"); }
void RSP_Processor::P_RSP_VINST(char *buf) { P_RSP_VectorOp(buf, "VINST"); }
void RSP_Processor::P_RSP_VINSQ(char *buf) { P_RSP_VectorOp(buf, "VINSQ"); }
void RSP_Processor::P_RSP_VINSN(char *buf) { P_RSP_VectorOp(buf, "VINSN"); }
