/*
 * RSP Compiler plug in for Project 64 (A Nintendo 64 emulator).
 *
 * (c) Copyright 2001 jabo (jabo@emulation64.com) and
 * zilmar (zilmar@emulation64.com)
 *
 * pj64 homepage: www.pj64.net
 * 
 * Permission to use, copy, modify and distribute Project64 in both binary and
 * source form, for non-commercial purposes, is hereby granted without fee,
 * providing that this license information and copyright notice appear with
 * all copies and any derived work.
 *
 * This software is provided 'as-is', without any express or implied
 * warranty. In no event shall the authors be held liable for any damages
 * arising from the use of this software.
 *
 * Project64 is freeware for PERSONAL USE only. Commercial users should
 * seek permission of the copyright holders first. Commercial use includes
 * charging money for Project64 or software derived from Project64.
 *
 * The copyright holders request that bug fixes and improvements to the code
 * should be forwarded to them so if they want them.
 *
 */

#include <windows.h>
#include <stdio.h>
#include "RSP.h"
#include "CPU.h"
#include "Interpreter CPU.h"
#include "Interpreter Ops.h"
#include "Recompiler CPU.h"
#include "RSP Command.h"
#include "RSP Registers.h"
#include "memory.h"
#include "dma.h"
#include "log.h"
#include "x86.h"
#include "Profiling.h"

#pragma warning(disable : 4152) // nonstandard extension, function/data pointer conversion in expression

UWORD32 Recp, RecpResult, SQroot, SQrootResult;
DWORD ESP_RegSave = 0, EBP_RegSave = 0;
DWORD BranchCompare = 0;

/* align option affects: sw, lh, sh */
/* align option affects: lrv, ssv, lsv */

#define Compile_Immediates	/* ADDI, ADDIU, ANDI, ORI, XORI, LUI */
#define Compile_GPRLoads	/* LB, LH, LW, LBU, LHU */
#define Compile_GPRStores	/* SB, SH, SW */
#define Compile_Special		/* SLL, SRL, SRA, SRLV */
							/* XOR, OR, AND, SUB, SUBU, ADDU, ADD, SLT */
#define Compile_Cop0
#define Compile_Cop2

#define RSP_VectorMuls
#define RSP_VectorLoads
#define RSP_VectorMisc

#ifdef RSP_VectorMuls
#	define CompileVmulf	/* Verified 12/17/2000 - Jabo */
#	define CompileVmacf	/* Rewritten & Verified 12/15/2000 - Jabo */
#	define CompileVmudm	/* Verified 12/17/2000 - Jabo */
#	define CompileVmudh	/* Verified 12/17/2000 - Jabo */
#	define CompileVmudn	/* Verified 12/17/2000 - Jabo */
#	define CompileVmudl	/* Verified 12/17/2000 - Jabo */
#	define CompileVmadl	
#	define CompileVmadm	/* Verified 12/17/2000 - Jabo */
#	define CompileVmadh	/* Verified 12/15/2000 - Jabo */
#	define CompileVmadn	/* Verified 12/17/2000 - Jabo */
#endif
#ifdef RSP_VectorMisc
#	define CompileVrsqh
#	define CompileVrcph
#	define CompileVsaw		/* Verified 12/17/2000 - Jabo */
#	define CompileVabs		/* Verified 12/15/2000 - Jabo */
#	define CompileVmov		/* Verified 12/17/2000 - Jabo */
#	define CompileVxor		/* Verified 12/17/2000 - Jabo */
#	define CompileVor		/* Verified 12/17/2000 - Jabo */
#	define CompileVand		/* Verified 12/17/2000 - Jabo */
#	define CompileVsub		/* Verified 12/17/2000 - Jabo (watch flags) */
#	define CompileVadd		/* Verified 12/17/2000 - Jabo (watch flags) */
#	define CompileVaddc
#	define CompileVsubc
#	define CompileVmrg
#	define CompileVnxor
#	define CompileVnor
#	define CompileVnand
#endif
#ifdef RSP_VectorLoads
#	define CompileSqv		/* Verified 12/17/2000 - Jabo */
#	define CompileSdv		/* Verified 12/17/2000 - Jabo */
#	define CompileSsv		/* Verified 12/17/2000 - Jabo */
#	define CompileLrv		/* Rewritten & Verified 12/17/2000 - Jabo */
#	define CompileLqv		/* Verified 12/17/2000 - Jabo */
#	define CompileLdv		/* Verified 12/17/2000 - Jabo */
#	define CompileLsv		/* Verified 12/17/2000 - Jabo */
#	define CompileLlv		/* Verified 12/17/2000 - Jabo */
#	define CompileSlv
#endif

void Branch_AddRef(DWORD Target, DWORD * X86Loc) {
	if (CurrentBlock.ResolveCount >= 150) {
		CompilerWarning("Out of branch reference space");
	} else {
		BYTE * KnownCode = *(JumpTable + (Target >> 2));

		if (KnownCode == NULL) {
			DWORD i = CurrentBlock.ResolveCount;
			CurrentBlock.BranchesToResolve[i].TargetPC = Target;
			CurrentBlock.BranchesToResolve[i].X86JumpLoc = X86Loc;
			CurrentBlock.ResolveCount += 1;
		} else {
			CPU_Message("      (static jump to %X)", KnownCode);
			x86_SetBranch32b((DWORD*)X86Loc, (DWORD*)KnownCode);
		}
	}
}

void Cheat_r4300iOpcode(p_func FunctAddress, char * FunctName) {
	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));
	MoveConstToVariable(RSPOpC.Hex, &RSPOpC.Hex, "RSPOpC.Hex" );
	Call_Direct(FunctAddress, FunctName);
}

void Cheat_r4300iOpcodeNoMessage(p_func FunctAddress, char * FunctName) {
	MoveConstToVariable(RSPOpC.Hex, &RSPOpC.Hex, "RSPOpC.Hex" );
	Call_Direct(FunctAddress, FunctName);
}

void x86_SetBranch8b(void * JumpByte, void * Destination) {
	/* calculate 32-bit relative offset */
	signed int n = (BYTE*)Destination - ((BYTE*)JumpByte + 1);

	/* check limits, no pun intended */
	if (n > 0x80 || n < -0x7F) {
		CompilerWarning("FATAL: Jump out of 8b range %i (PC = %04X)", n, CompilePC);
	} else
		*(BYTE*)(JumpByte) = (BYTE)n;
}

void x86_SetBranch32b(void * JumpByte, void * Destination) {
	*(DWORD*)(JumpByte) = (DWORD)((BYTE*)Destination - (BYTE*)((DWORD*)JumpByte + 1));
}

void BreakPoint() {
	CPU_Message("      int 3");
	*(RecompPos++) = 0xCC;
}

void CompileBranchExit(DWORD TargetPC, DWORD ContinuePC)
{
	DWORD * X86Loc = NULL;

	NextInstruction = FINISH_SUB_BLOCK;	
	CompConstToVariable(TRUE, &BranchCompare, "BranchCompare");
	JeLabel32("BranchEqual", 0);
	X86Loc = (DWORD*)(RecompPos - 4);
	MoveConstToVariable(ContinuePC,PrgCount,"RSP PC");
	Ret();

	CPU_Message("BranchEqual:");
	x86_SetBranch32b(X86Loc, RecompPos);
	MoveConstToVariable(TargetPC,PrgCount,"RSP PC");
	Ret();
}

/************************* OpCode functions *************************/
void Compile_SPECIAL ( void ) {
	RSP_Special[ RSPOpC.funct ]();
}

void Compile_REGIMM ( void ) {
	RSP_RegImm[ RSPOpC.rt ]();
}

void Compile_J ( void ) {
	if ( NextInstruction == NORMAL ) {
		CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));
		NextInstruction = DO_DELAY_SLOT;
	} else if ( NextInstruction == DELAY_SLOT_DONE ) {
		JmpLabel32 ( "BranchToJump", 0 );
		Branch_AddRef((RSPOpC.target << 2) & 0xFFC, (DWORD*)(RecompPos - 4));
		NextInstruction = FINISH_SUB_BLOCK;
	} else if ( NextInstruction == DELAY_SLOT_EXIT_DONE ) {
		MoveConstToVariable((RSPOpC.target << 2) & 0xFFC,PrgCount,"RSP PC");
		NextInstruction = FINISH_SUB_BLOCK;	
		Ret();
	} else {
		CompilerWarning("J error\nWeird Delay Slot.\n\nNextInstruction = %X\nEmulation will now stop", NextInstruction);
		BreakPoint();
	}
}

void Compile_JAL ( void ) {
	if ( NextInstruction == NORMAL ) {
		CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));
		MoveConstToVariable(CompilePC + 8, &RSP_GPR[31].UW, "RA.W");
		NextInstruction = DO_DELAY_SLOT;
	} else if ( NextInstruction == DELAY_SLOT_DONE ) {
		// before we branch quickly update our stats
		if (Profiling && IndvidualBlock)
		{
			char Str[40];
			sprintf(Str,"%03X",(RSPOpC.target << 2) & 0xFFC);
			Push(x86_EAX);
			PushImm32(Str,*PrgCount);
			Call_Direct(StartTimer, "StartTimer");
			AddConstToX86Reg(x86_ESP, 4);
			Pop(x86_EAX);
		}
		JmpLabel32 ( "BranchToJump", 0 );
		Branch_AddRef((RSPOpC.target << 2) & 0xFFC, (DWORD*)(RecompPos - 4));
		NextInstruction = FINISH_SUB_BLOCK;
	} else if ( NextInstruction == DELAY_SLOT_EXIT_DONE ) {
		MoveConstToVariable((RSPOpC.target << 2) & 0xFFC,PrgCount,"RSP PC");
		NextInstruction = FINISH_SUB_BLOCK;	
		Ret();
	} else {
		CompilerWarning("J error\nWeird Delay Slot.\n\nNextInstruction = %X\nEmulation will now stop", NextInstruction);
		BreakPoint();
	}
}

void Compile_BEQ ( void ) {
	static BOOL bDelayAffect;

	if ( NextInstruction == NORMAL ) {
		CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));
		if (RSPOpC.rs == 0 && RSPOpC.rt == 0) {
			NextInstruction = DO_DELAY_SLOT;			
			return;
		}
		bDelayAffect = DelaySlotAffectBranch(CompilePC);
		if (FALSE == bDelayAffect) {
			NextInstruction = DO_DELAY_SLOT;
			return;
		}
		if (RSPOpC.rt == 0) {
			CompConstToVariable(0,&RSP_GPR[RSPOpC.rs].W,GPR_Name(RSPOpC.rs));
		} else if (RSPOpC.rs == 0) {			
			CompConstToVariable(0,&RSP_GPR[RSPOpC.rt].W,GPR_Name(RSPOpC.rt));
		} else {
			MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].W,GPR_Name(RSPOpC.rt),x86_EAX);
			CompX86regToVariable(x86_EAX,&RSP_GPR[RSPOpC.rs].W,GPR_Name(RSPOpC.rs));
		}
		SetzVariable(&BranchCompare, "BranchCompare");
		NextInstruction = DO_DELAY_SLOT;	
	} else if ( NextInstruction == DELAY_SLOT_DONE ) {
		DWORD Target = (CompilePC + ((short)RSPOpC.offset << 2) + 4) & 0xFFC;
		
		if (RSPOpC.rs == 0 && RSPOpC.rt == 0) {
			JmpLabel32 ( "BranchToJump", 0 );
			Branch_AddRef(Target, (DWORD*)(RecompPos - 4));
			NextInstruction = FINISH_SUB_BLOCK;
			return;
		}
		if (FALSE == bDelayAffect) {
			if (RSPOpC.rt == 0) {
				CompConstToVariable(0,&RSP_GPR[RSPOpC.rs].W,GPR_Name(RSPOpC.rs));
			} else if (RSPOpC.rs == 0) {			
				CompConstToVariable(0,&RSP_GPR[RSPOpC.rt].W,GPR_Name(RSPOpC.rt));
			} else {
				MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].W,GPR_Name(RSPOpC.rt),x86_EAX);
				CompX86regToVariable(x86_EAX,&RSP_GPR[RSPOpC.rs].W,GPR_Name(RSPOpC.rs));
			}
			JeLabel32("BranchEqual", 0);
		} else {
			/* take a look at the branch compare variable */
			CompConstToVariable(TRUE, &BranchCompare, "BranchCompare");
			JeLabel32("BranchEqual", 0);
		}
		Branch_AddRef(Target, (DWORD*)(RecompPos - 4));
		NextInstruction = FINISH_SUB_BLOCK;
	} else if ( NextInstruction == DELAY_SLOT_EXIT_DONE ) {
		DWORD Target = (CompilePC + ((short)RSPOpC.offset << 2) + 4) & 0xFFC;
		CompileBranchExit(Target, CompilePC + 8);
	} else {
		CompilerWarning("BEQ error\nWeird Delay Slot.\n\nNextInstruction = %X\nEmulation will now stop", NextInstruction);
		BreakPoint();
	}
}

void Compile_BNE ( void ) {
	static BOOL bDelayAffect;

	if ( NextInstruction == NORMAL ) {
		CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));
		if (RSPOpC.rs == 0 && RSPOpC.rt == 0) {
			NextInstruction = DO_DELAY_SLOT;
			return;
		}

		bDelayAffect = DelaySlotAffectBranch(CompilePC);
		if (FALSE == bDelayAffect) {
			NextInstruction = DO_DELAY_SLOT;
			return;
		}
		if (RSPOpC.rt == 0) {			
			CompConstToVariable(0,&RSP_GPR[RSPOpC.rs].W,GPR_Name(RSPOpC.rs));
		} else if (RSPOpC.rs == 0) {			
			CompConstToVariable(0,&RSP_GPR[RSPOpC.rt].W,GPR_Name(RSPOpC.rt));
		} else {
			MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].W,GPR_Name(RSPOpC.rt),x86_EAX);
			CompX86regToVariable(x86_EAX,&RSP_GPR[RSPOpC.rs].W,GPR_Name(RSPOpC.rs));
		}
		SetnzVariable(&BranchCompare, "BranchCompare");
		NextInstruction = DO_DELAY_SLOT;	
	} else if ( NextInstruction == DELAY_SLOT_DONE ) {
		DWORD Target = (CompilePC + ((short)RSPOpC.offset << 2) + 4) & 0xFFC;
		
		if (RSPOpC.rs == 0 && RSPOpC.rt == 0) {			
			NextInstruction = FINISH_SUB_BLOCK;
			return;
		}

		if (FALSE == bDelayAffect) {
			if (RSPOpC.rt == 0) {			
				CompConstToVariable(0,&RSP_GPR[RSPOpC.rs].W,GPR_Name(RSPOpC.rs));
			} else if (RSPOpC.rs == 0) {			
				CompConstToVariable(0,&RSP_GPR[RSPOpC.rt].W,GPR_Name(RSPOpC.rt));
			} else {
				MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].W,GPR_Name(RSPOpC.rt),x86_EAX);
				CompX86regToVariable(x86_EAX,&RSP_GPR[RSPOpC.rs].W,GPR_Name(RSPOpC.rs));
			}
			JneLabel32("BranchNotEqual", 0);
		} else {
			/* take a look at the branch compare variable */
			CompConstToVariable(TRUE, &BranchCompare, "BranchCompare");
			JeLabel32("BranchNotEqual", 0);
		}
		Branch_AddRef(Target, (DWORD*)(RecompPos - 4));
		NextInstruction = FINISH_SUB_BLOCK;
	} else if ( NextInstruction == DELAY_SLOT_EXIT_DONE ) {
		DWORD Target = (CompilePC + ((short)RSPOpC.offset << 2) + 4) & 0xFFC;
		CompileBranchExit(Target, CompilePC + 8);
	} else {
		CompilerWarning("BNE error\nWeird Delay Slot.\n\nNextInstruction = %X\nEmulation will now stop", NextInstruction);
		BreakPoint();
	}
}

void Compile_BLEZ ( void ) {
	static BOOL bDelayAffect;

	if ( NextInstruction == NORMAL ) {
		CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));
		if (RSPOpC.rs == 0) {
			NextInstruction = DO_DELAY_SLOT;			
			return;
		}
		bDelayAffect = DelaySlotAffectBranch(CompilePC);
		if (FALSE == bDelayAffect) {
			NextInstruction = DO_DELAY_SLOT;
			return;
		}
		CompConstToVariable(0,&RSP_GPR[RSPOpC.rs].W,GPR_Name(RSPOpC.rs));
		SetleVariable(&BranchCompare, "BranchCompare");
		NextInstruction = DO_DELAY_SLOT;	
	} else if ( NextInstruction == DELAY_SLOT_DONE ) {
		DWORD Target = (CompilePC + ((short)RSPOpC.offset << 2) + 4) & 0xFFC;
		
		if (RSPOpC.rs == 0) {
			JmpLabel32 ( "BranchToJump", 0 );
			Branch_AddRef(Target, (DWORD*)(RecompPos - 4));
			NextInstruction = FINISH_SUB_BLOCK;
			return;
		}
		if (FALSE == bDelayAffect) {
			CompConstToVariable(0,&RSP_GPR[RSPOpC.rs].W,GPR_Name(RSPOpC.rs));
			JleLabel32("BranchLessEqual", 0);
		} else {
			/* take a look at the branch compare variable */
			CompConstToVariable(TRUE, &BranchCompare, "BranchCompare");
			JeLabel32("BranchLessEqual", 0);
		}

		Branch_AddRef(Target, (DWORD*)(RecompPos - 4));
		NextInstruction = FINISH_SUB_BLOCK;
	} else if ( NextInstruction == DELAY_SLOT_EXIT_DONE ) {
		DWORD Target = (CompilePC + ((short)RSPOpC.offset << 2) + 4) & 0xFFC;
		CompileBranchExit(Target, CompilePC + 8);
	} else {
		CompilerWarning("BLEZ error\nWeird Delay Slot.\n\nNextInstruction = %X\nEmulation will now stop", NextInstruction);
		BreakPoint();
	}
}

void Compile_BGTZ ( void ) {
	static BOOL bDelayAffect;

	if ( NextInstruction == NORMAL ) {
		CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));
		if (RSPOpC.rs == 0) {
			NextInstruction = DO_DELAY_SLOT;			
			return;
		}
		bDelayAffect = DelaySlotAffectBranch(CompilePC);
		if (FALSE == bDelayAffect) {
			NextInstruction = DO_DELAY_SLOT;
			return;
		}
		CompConstToVariable(0,&RSP_GPR[RSPOpC.rs].W,GPR_Name(RSPOpC.rs));
		SetgVariable(&BranchCompare, "BranchCompare");
		NextInstruction = DO_DELAY_SLOT;	
	} else if ( NextInstruction == DELAY_SLOT_DONE ) {
		DWORD Target = (CompilePC + ((short)RSPOpC.offset << 2) + 4) & 0xFFC;
		
		if (RSPOpC.rs == 0) {			
			NextInstruction = FINISH_SUB_BLOCK;
			return;
		}
		if (FALSE == bDelayAffect) {
			CompConstToVariable(0,&RSP_GPR[RSPOpC.rs].W,GPR_Name(RSPOpC.rs));
			JgLabel32("BranchGreater", 0);
		} else {
			/* take a look at the branch compare variable */
			CompConstToVariable(TRUE, &BranchCompare, "BranchCompare");
			JeLabel32("BranchGreater", 0);
		}
		Branch_AddRef(Target, (DWORD*)(RecompPos - 4));
		NextInstruction = FINISH_SUB_BLOCK;
	} else if ( NextInstruction == DELAY_SLOT_EXIT_DONE ) {
		DWORD Target = (CompilePC + ((short)RSPOpC.offset << 2) + 4) & 0xFFC;
		CompileBranchExit(Target, CompilePC + 8);
	} else {
		CompilerWarning("BGTZ error\nWeird Delay Slot.\n\nNextInstruction = %X\nEmulation will now stop", NextInstruction);
		BreakPoint();
	}
}

void Compile_ADDI ( void ) {
	int Immediate = (short)RSPOpC.immediate;

	#ifndef Compile_Immediates
	Cheat_r4300iOpcode(RSP_Opcode_ADDI,"RSP_Opcode_ADDI"); return;
	#endif

	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));

	if (RSPOpC.rt == 0) return;

	if (RSPOpC.rt == RSPOpC.rs) {
		AddConstToVariable(Immediate, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt));
	} else if (RSPOpC.rs == 0) {
		MoveConstToVariable(Immediate, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt));
	} else if ((IsRegConst(RSPOpC.rs) && 1) != 0) {
		MoveConstToVariable(MipsRegConst(RSPOpC.rs) + Immediate, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt));
	} else {
		MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].UW, GPR_Name(RSPOpC.rs), x86_EAX);
		if (Immediate != 0) {
			AddConstToX86Reg(x86_EAX, Immediate);
		}
		MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt));		
	}
}

void Compile_ADDIU ( void ) {
	int Immediate = (short)RSPOpC.immediate;

	#ifndef Compile_Immediates
	Cheat_r4300iOpcode(RSP_Opcode_ADDIU,"RSP_Opcode_ADDIU"); return;
	#endif

	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));

	if (RSPOpC.rt == 0) return;

	if (RSPOpC.rt == RSPOpC.rs) {
		AddConstToVariable(Immediate, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt));
	} else if (RSPOpC.rs == 0) {
		MoveConstToVariable(Immediate, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt));
	} else {
		MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].UW, GPR_Name(RSPOpC.rs), x86_EAX);
		AddConstToX86Reg(x86_EAX, Immediate);
		MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt));
	}
}

void Compile_SLTI ( void ) {
	Cheat_r4300iOpcode(RSP_Opcode_SLTI,"RSP_Opcode_SLTI");
	
}

void Compile_SLTIU ( void ) {
	Cheat_r4300iOpcode(RSP_Opcode_SLTIU,"RSP_Opcode_SLTIU");
	
}

void Compile_ANDI ( void ) {
	int Immediate = (unsigned short)RSPOpC.immediate;

	#ifndef Compile_Immediates
	Cheat_r4300iOpcode(RSP_Opcode_ANDI,"RSP_Opcode_ANDI"); return;
	#endif

	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));

	if (RSPOpC.rt == 0) return;

	if (RSPOpC.rt == RSPOpC.rs) {
		AndConstToVariable(Immediate, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt));
	} else if (RSPOpC.rs == 0) {
		MoveConstToVariable(0, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt));
	} else {
		MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].UW, GPR_Name(RSPOpC.rs), x86_EAX);
		AndConstToX86Reg(x86_EAX, Immediate);
		MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt));
	}
}

void Compile_ORI ( void ) {
	int Immediate = (unsigned short)RSPOpC.immediate;

	#ifndef Compile_Immediates
	Cheat_r4300iOpcode(RSP_Opcode_ORI,"RSP_Opcode_ORI"); return;
	#endif

	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));

	if (RSPOpC.rt == 0) return;

	if (RSPOpC.rt == RSPOpC.rs) {
		OrConstToVariable(Immediate, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt));
	} else if (RSPOpC.rs == 0) {
		MoveConstToVariable(Immediate, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt));
	} else {
		MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].UW, GPR_Name(RSPOpC.rs), x86_EAX);
		if (Immediate != 0) {
			OrConstToX86Reg(Immediate, x86_EAX);
		}
		MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt));
	}
}

void Compile_XORI ( void ) {
	int Immediate = (unsigned short)RSPOpC.immediate;

	#ifndef Compile_Immediates
	Cheat_r4300iOpcode(RSP_Opcode_XORI,"RSP_Opcode_XORI"); return;
	#endif

	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));

	if (RSPOpC.rt == 0) return;

	if (RSPOpC.rt == RSPOpC.rs) {
		XorConstToVariable(&RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt), Immediate);
	} else if (RSPOpC.rs == 0) {
		MoveConstToVariable(Immediate, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt));
	} else {
		MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].UW, GPR_Name(RSPOpC.rs), x86_EAX);
		if (Immediate != 0) {
			XorConstToX86Reg(x86_EAX, Immediate);
		}
		MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt));
	}
}

void Compile_LUI ( void ) {
	int constant = (short)RSPOpC.offset << 16;

	#ifndef Compile_Immediates
	Cheat_r4300iOpcode(RSP_Opcode_LUI,"RSP_Opcode_LUI"); return;
	#endif

	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));

	if (RSPOpC.rt == 0) return;
	MoveConstToVariable(constant, &RSP_GPR[RSPOpC.rt].W, GPR_Name(RSPOpC.rt));
}

void Compile_COP0 (void) {
	RSP_Cop0[ RSPOpC.rs ]();
}

void Compile_COP2 (void) {
	RSP_Cop2[ RSPOpC.rs ]();
}

void Compile_LB ( void ) {
	int Offset = (short)RSPOpC.offset;

	#ifndef Compile_GPRLoads
	Cheat_r4300iOpcode(RSP_Opcode_LB,"RSP_Opcode_LB"); return;
	#endif

	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));
	
	MoveVariableToX86reg(&RSP_GPR[RSPOpC.base].UW, GPR_Name(RSPOpC.base), x86_EBX);
	if (Offset != 0) AddConstToX86Reg(x86_EBX, Offset);
	XorConstToX86Reg(x86_EBX, 3);
	AndConstToX86Reg(x86_EBX, 0x0fff);

	MoveSxN64MemToX86regByte(x86_EAX, x86_EBX);
	MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt));
}

void Compile_LH ( void ) {
	int Offset = (short)RSPOpC.offset;
	BYTE * Jump[2];

	#ifndef Compile_GPRLoads
	Cheat_r4300iOpcode(RSP_Opcode_LH,"RSP_Opcode_LH"); return;
	#endif

	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));
	
	if (IsRegConst(RSPOpC.base) == TRUE) {
		DWORD Addr = (MipsRegConst(RSPOpC.base) + Offset) ^ 2;
		Addr &= 0xfff;

		if ((Addr & 1) != 0) {
			CompilerWarning("Unaligned LH at constant address PC = %04X", CompilePC);
			Cheat_r4300iOpcodeNoMessage(RSP_Opcode_LH,"RSP_Opcode_LH");
		} else {
			char Address[32];			
			sprintf(Address, "Dmem + %Xh", Addr);
			MoveSxVariableToX86regHalf(RSPInfo.DMEM + Addr, Address, x86_EAX);
			MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt));
		}
		return;
	}

	MoveVariableToX86reg(&RSP_GPR[RSPOpC.base].UW, GPR_Name(RSPOpC.base), x86_EBX);
	if (Offset != 0) AddConstToX86Reg(x86_EBX, Offset);

	AndConstToX86Reg(x86_EBX, 0x0fff);
	TestConstToX86Reg(1, x86_EBX);
	JneLabel32("Unaligned", 0);
	Jump[0] = RecompPos - 4;

	CompilerToggleBuffer();

	CPU_Message("   Unaligned:");
	x86_SetBranch32b(Jump[0], RecompPos);

	Cheat_r4300iOpcodeNoMessage(RSP_Opcode_LH,"RSP_Opcode_LH");

	JmpLabel32("Done", 0);
	Jump[1] = RecompPos - 4;

	CompilerToggleBuffer();

	XorConstToX86Reg(x86_EBX, 2);

	MoveSxN64MemToX86regHalf(x86_EAX, x86_EBX);
	MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt));

	CPU_Message("   Done:");
	x86_SetBranch32b(Jump[1], RecompPos);
}

void Compile_LW ( void ) {
	int Offset = (short)RSPOpC.offset;
	BYTE * Jump[2];

	#ifndef Compile_GPRLoads
	Cheat_r4300iOpcode(RSP_Opcode_LW,"RSP_Opcode_LW"); return;
	#endif

	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));
	
	if (IsRegConst(RSPOpC.base) == TRUE) {
		DWORD Addr = (MipsRegConst(RSPOpC.base) + Offset) & 0xfff;

		if ((Addr & 3) != 0) {
			CompilerWarning("Unaligned LW at constant address PC = %04X", CompilePC);
			Cheat_r4300iOpcodeNoMessage(RSP_Opcode_LW,"RSP_Opcode_LW");
		} else {
			char Address[32];			
			sprintf(Address, "Dmem + %Xh", Addr);
			MoveVariableToX86reg(RSPInfo.DMEM + Addr, Address, x86_EAX);
			MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt));
		}
		return;
	}

	MoveVariableToX86reg(&RSP_GPR[RSPOpC.base].UW, GPR_Name(RSPOpC.base), x86_EBX);
	if (Offset != 0) AddConstToX86Reg(x86_EBX, Offset);
	
	AndConstToX86Reg(x86_EBX, 0x0fff);
	TestConstToX86Reg(3, x86_EBX);
	JneLabel32("UnAligned", 0);
	Jump[0] = RecompPos - 4;

	CompilerToggleBuffer();

	x86_SetBranch32b(Jump[0], RecompPos);
	CPU_Message("   Unaligned:");

	LeaSourceAndOffset(x86_ECX , x86_EBX, 2);
	LeaSourceAndOffset(x86_EDX , x86_EBX, 3);
	MoveX86RegToX86Reg(x86_EBX, x86_EAX);
	AddConstToX86Reg(x86_EBX, 1);
	
	XorConstToX86Reg(x86_EAX, 3);
	XorConstToX86Reg(x86_EBX, 3);
	XorConstToX86Reg(x86_ECX, 3);
	XorConstToX86Reg(x86_EDX, 3);
	MoveN64MemToX86regByte(x86_EAX, x86_EAX);
	MoveN64MemToX86regByte(x86_EBX, x86_EBX);
	MoveN64MemToX86regByte(x86_ECX, x86_ECX);
	MoveN64MemToX86regByte(x86_EDX, x86_EDX);
	MoveX86regByteToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UB[3], GPR_Name(RSPOpC.rt));
	MoveX86regByteToVariable(x86_EBX, &RSP_GPR[RSPOpC.rt].UB[2], GPR_Name(RSPOpC.rt));
	MoveX86regByteToVariable(x86_ECX, &RSP_GPR[RSPOpC.rt].UB[1], GPR_Name(RSPOpC.rt));
	MoveX86regByteToVariable(x86_EDX, &RSP_GPR[RSPOpC.rt].UB[0], GPR_Name(RSPOpC.rt));

	JmpLabel32("Done", 0);
	Jump[1] = RecompPos - 4;
	CompilerToggleBuffer();

	MoveN64MemToX86reg(x86_EAX, x86_EBX);
	MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt));

	CPU_Message("   Done:");
	x86_SetBranch32b(Jump[1], RecompPos);
}

void Compile_LBU ( void ) {
	int Offset = (short)RSPOpC.offset;

	#ifndef Compile_GPRLoads
	Cheat_r4300iOpcode(RSP_Opcode_LBU,"RSP_Opcode_LBU"); return;
	#endif

	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));

	MoveVariableToX86reg(&RSP_GPR[RSPOpC.base].UW, GPR_Name(RSPOpC.base), x86_EBX);
	XorX86RegToX86Reg(x86_EAX, x86_EAX);

	if (Offset != 0) AddConstToX86Reg(x86_EBX, Offset);
	XorConstToX86Reg(x86_EBX, 3);
	AndConstToX86Reg(x86_EBX, 0x0fff);

	MoveN64MemToX86regByte(x86_EAX, x86_EBX);
	MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt));
}

void Compile_LHU ( void ) {
	int Offset = (short)RSPOpC.offset;
	BYTE * Jump[2];

	#ifndef Compile_GPRLoads
	Cheat_r4300iOpcode(RSP_Opcode_LHU,"RSP_Opcode_LHU"); return;
	#endif

	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));

	if (IsRegConst(RSPOpC.base) == TRUE) {
		DWORD Addr = (MipsRegConst(RSPOpC.base) + Offset) ^ 2;
		Addr &= 0xfff;

		if ((Addr & 1) != 0) {
			CompilerWarning("Unaligned LHU at constant address PC = %04X", CompilePC);
			Cheat_r4300iOpcodeNoMessage(RSP_Opcode_LHU,"RSP_Opcode_LHU");
			return;
		} else {
			char Address[32];			
			sprintf(Address, "Dmem + %Xh", Addr);
			MoveZxVariableToX86regHalf(RSPInfo.DMEM + Addr, Address, x86_ECX);
			MoveX86regToVariable(x86_ECX, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt));
			return;
		}
	}

	/*
	 * should really just do it by bytes but whatever for now
	 */
	MoveVariableToX86reg(&RSP_GPR[RSPOpC.base].UW, GPR_Name(RSPOpC.base), x86_EBX);
	if (Offset != 0) {
		AddConstToX86Reg(x86_EBX, Offset);
	}
	TestConstToX86Reg(1, x86_EBX);
	JneLabel32("Unaligned", 0);
	Jump[0] = RecompPos - 4;

	CompilerToggleBuffer();
	CPU_Message("   Unaligned:");
	x86_SetBranch32b(Jump[0], RecompPos);
	Cheat_r4300iOpcodeNoMessage(RSP_Opcode_LHU,"RSP_Opcode_LHU");
	JmpLabel32("Done", 0);
	Jump[1] = RecompPos - 4;
	CompilerToggleBuffer();

	XorConstToX86Reg(x86_EBX, 2);
	AndConstToX86Reg(x86_EBX, 0x0fff);
	MoveZxN64MemToX86regHalf(x86_EAX, x86_EBX);
	MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt));

	CPU_Message("   Done:");
	x86_SetBranch32b(Jump[1], RecompPos);
}

void Compile_SB ( void ) {
	int Offset = (short)RSPOpC.offset;

	#ifndef Compile_GPRStores
	Cheat_r4300iOpcode(RSP_Opcode_SB,"RSP_Opcode_SB"); return;
	#endif

	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));

	MoveVariableToX86reg(&RSP_GPR[RSPOpC.base].UW, GPR_Name(RSPOpC.base), x86_EBX);
	MoveVariableToX86regByte(&RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt), x86_EAX);

	if (Offset != 0) AddConstToX86Reg(x86_EBX, Offset);
	XorConstToX86Reg(x86_EBX, 3);
	AndConstToX86Reg(x86_EBX, 0x0fff);

	MoveX86regByteToN64Mem(x86_EAX, x86_EBX);
}

void Compile_SH ( void ) {
	int Offset = (short)RSPOpC.offset;
	BYTE * Jump[2];

	#ifndef Compile_GPRStores
	Cheat_r4300iOpcode(RSP_Opcode_SH,"RSP_Opcode_SH"); return;
	#endif

	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));

	if (IsRegConst(RSPOpC.base) == TRUE) {
		DWORD Addr = (MipsRegConst(RSPOpC.base) + Offset) ^ 2;
		Addr &= 0xfff;

		if ((Offset & 1) != 0) {
			CompilerWarning("Unaligned SH at constant address PC = %04X", CompilePC);
			Cheat_r4300iOpcodeNoMessage(RSP_Opcode_SH,"RSP_Opcode_SH");
			return;
		} else {
			char Address[32];			
			sprintf(Address, "Dmem + %Xh", Addr);
			MoveVariableToX86regHalf(&RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt), x86_EAX);
			MoveX86regHalfToVariable(x86_EAX, RSPInfo.DMEM + Addr, Address);
			return;
		}
	}

	MoveVariableToX86reg(&RSP_GPR[RSPOpC.base].UW, GPR_Name(RSPOpC.base), x86_EBX);
	if (Offset != 0) AddConstToX86Reg(x86_EBX, Offset);

	TestConstToX86Reg(1, x86_EBX);
	JneLabel32("Unaligned", 0);
	Jump[0] = RecompPos - 4;

	CompilerToggleBuffer();

	CPU_Message("   Unaligned:");
	x86_SetBranch32b(Jump[0], RecompPos);

	X86BreakPoint(__FILE__,__LINE__);
	JmpLabel32("Done", 0);
	Jump[1] = RecompPos - 4;

	CompilerToggleBuffer();

	XorConstToX86Reg(x86_EBX, 2);
	AndConstToX86Reg(x86_EBX, 0x0fff);

	MoveVariableToX86regHalf(&RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt), x86_EAX);
	MoveX86regHalfToN64Mem(x86_EAX, x86_EBX);

	CPU_Message("   Done:");
	x86_SetBranch32b(Jump[1], RecompPos);
}

void Compile_SW ( void ) {
	int Offset = (short)RSPOpC.offset;
	BYTE * Jump[2];

	#ifndef Compile_GPRStores
	Cheat_r4300iOpcode(RSP_Opcode_SW,"RSP_Opcode_SW"); return;
	#endif

	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));

	if (IsRegConst(RSPOpC.base) == TRUE) {
		DWORD Addr = (MipsRegConst(RSPOpC.base) + Offset) & 0xfff;

		if ((Addr & 3) != 0) {
			CompilerWarning("Unaligned SW at constant address PC = %04X", CompilePC);
			Cheat_r4300iOpcodeNoMessage(RSP_Opcode_SW,"RSP_Opcode_SW");
			return;
		} else {
			char Address[32];			
			sprintf(Address, "Dmem + %Xh", Addr);
			MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt), x86_EAX);
			MoveX86regToVariable(x86_EAX, RSPInfo.DMEM + Addr, Address);			
			return;
		}
	} 

	MoveVariableToX86reg(&RSP_GPR[RSPOpC.base].UW, GPR_Name(RSPOpC.base), x86_EBX);
	if (Offset != 0) AddConstToX86Reg(x86_EBX, Offset);
	
	AndConstToX86Reg(x86_EBX, 0x0fff);
	TestConstToX86Reg(3, x86_EBX);
	JneLabel32("Unaligned", 0);
	Jump[0] = RecompPos - 4;

	CompilerToggleBuffer();

	CPU_Message("   Unaligned:");
	x86_SetBranch32b(Jump[0], RecompPos);

//	X86BreakPoint(__FILE__,__LINE__);

	Push(x86_EBX);
	LeaSourceAndOffset(x86_ECX , x86_EBX, 2);
	LeaSourceAndOffset(x86_EDX , x86_EBX, 3);
	XorConstToX86Reg(x86_ECX, 3);
	XorConstToX86Reg(x86_EDX, 3);
	MoveVariableToX86regByte(&RSP_GPR[RSPOpC.rt].UB[1], GPR_Name(RSPOpC.rt),x86_EAX); //cx
	MoveVariableToX86regByte(&RSP_GPR[RSPOpC.rt].UB[0], GPR_Name(RSPOpC.rt),x86_EBX); //dx
	MoveX86regByteToN64Mem(x86_EAX, x86_ECX);
	MoveX86regByteToN64Mem(x86_EBX, x86_EDX);
	Pop(x86_EBX);
	
	MoveX86RegToX86Reg(x86_EBX, x86_EAX);
	AddConstToX86Reg(x86_EBX, 1);
	XorConstToX86Reg(x86_EAX, 3);
	XorConstToX86Reg(x86_EBX, 3);
	
	MoveVariableToX86regByte(&RSP_GPR[RSPOpC.rt].UB[3], GPR_Name(RSPOpC.rt),x86_ECX); //ax
	MoveVariableToX86regByte(&RSP_GPR[RSPOpC.rt].UB[2], GPR_Name(RSPOpC.rt),x86_EDX); //bx

	MoveX86regByteToN64Mem(x86_ECX, x86_EAX);
	MoveX86regByteToN64Mem(x86_EDX, x86_EBX);

	JmpLabel32("Done", 0);
	Jump[1] = RecompPos - 4;

	CompilerToggleBuffer();

	if (RSPOpC.rt == 0) {
		XorX86RegToX86Reg(x86_EAX,x86_EAX);
	} else {
		MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt), x86_EAX);		
	}
	MoveX86regToN64Mem(x86_EAX, x86_EBX);
	
	CPU_Message("   Done:");
	x86_SetBranch32b(Jump[1], RecompPos);
}

void Compile_LC2 (void) {
	RSP_Lc2 [ RSPOpC.rd ]();
}

void Compile_SC2 (void) {
	RSP_Sc2 [ RSPOpC.rd ]();
}
/********************** R4300i OpCodes: Special **********************/

void Compile_Special_SLL ( void ) {
	#ifndef Compile_Special
	Cheat_r4300iOpcode(RSP_Special_SLL,"RSP_Special_SLL"); return;
	#endif

	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));
	if (RSPOpC.rd == 0) return;

	if (RSPOpC.rd == RSPOpC.rt) {
		ShiftLeftSignVariableImmed(&RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd), (BYTE)RSPOpC.sa);
	} else {
		MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].W, GPR_Name(RSPOpC.rt), x86_EAX);
		ShiftLeftSignImmed(x86_EAX, (BYTE)RSPOpC.sa);
		MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd));
	}
}

void Compile_Special_SRL ( void ) {
	#ifndef Compile_Special
	Cheat_r4300iOpcode(RSP_Special_SRL,"RSP_Special_SRL"); return;
	#endif

	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));
	if (RSPOpC.rd == 0) return;

	if (RSPOpC.rd == RSPOpC.rt) {
		ShiftRightUnsignVariableImmed(&RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd), (BYTE)RSPOpC.sa);
	} else {
		MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].W, GPR_Name(RSPOpC.rt), x86_EAX);
		ShiftRightUnsignImmed(x86_EAX, (BYTE)RSPOpC.sa);
		MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd));
	}
}

void Compile_Special_SRA ( void ) {
	#ifndef Compile_Special
	Cheat_r4300iOpcode(RSP_Special_SRA,"RSP_Special_SRA"); return;
	#endif

	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));
	if (RSPOpC.rd == 0) return;

	if (RSPOpC.rd == RSPOpC.rt) {
		ShiftRightSignVariableImmed(&RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd), (BYTE)RSPOpC.sa);
	} else {
		MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].W, GPR_Name(RSPOpC.rt), x86_EAX);
		ShiftRightSignImmed(x86_EAX, (BYTE)RSPOpC.sa);
		MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd));
	}
}

void Compile_Special_SLLV ( void ) {
	Cheat_r4300iOpcode(RSP_Special_SLLV,"RSP_Special_SLLV");
}

void Compile_Special_SRLV ( void ) {
	#ifndef Compile_Special
	Cheat_r4300iOpcode(RSP_Special_SRLV,"RSP_Special_SRLV"); return;
	#endif

	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));
	if (RSPOpC.rd == 0) return;

	MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].W, GPR_Name(RSPOpC.rt), x86_EAX);
	MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, GPR_Name(RSPOpC.rs), x86_ECX);
	AndConstToX86Reg(x86_ECX, 0x1F);
	ShiftRightUnsign(x86_EAX);
	MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd));	
}

void Compile_Special_SRAV ( void ) {
	Cheat_r4300iOpcode(RSP_Special_SRAV,"RSP_Special_SRAV");
}

void UpdateAudioTimer() {
/*	char Label[100];
	sprintf(Label,"COMMAND: %02X (PC = %08X)",RSP_GPR[1].UW >> 1, *PrgCount);
	StartTimer(Label);*/
}

void Compile_Special_JR (void) {
	BYTE * Jump;

	if ( NextInstruction == NORMAL ) {		
		CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));
		/* transfer destination to location pointed to by PrgCount */
		MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W,GPR_Name(RSPOpC.rs),x86_EAX);
		AndConstToX86Reg(x86_EAX,0xFFC);
		MoveX86regToVariable(x86_EAX,PrgCount,"RSP PC");
		ChangedPC = TRUE;
		NextInstruction = DO_DELAY_SLOT;
	} else if ( NextInstruction == DELAY_SLOT_DONE ) {
		MoveVariableToX86reg(PrgCount,"RSP PC", x86_EAX);
		if (Profiling && IndvidualBlock)
		{
			Push(x86_EAX);
			Push(x86_EAX);
			Call_Direct(StartTimer, "StartTimer");
			AddConstToX86Reg(x86_ESP, 4);
			Pop(x86_EAX);
		}
		AddVariableToX86reg(x86_EAX, &JumpTable, "JumpTable");
		MoveX86regPointerToX86reg(x86_EAX, x86_EAX);

		TestX86RegToX86Reg(x86_EAX, x86_EAX);
		JeLabel8("Null", 0);
		Jump = RecompPos - 1;

		// before we branch quickly update our stats
		/*if (CompilePC == 0x080) {
			Pushad();
			Call_Direct(UpdateAudioTimer, "UpdateAudioTimer");
			Popad();
		}*/
		JumpX86Reg(x86_EAX);

		x86_SetBranch8b(Jump, RecompPos);
		CPU_Message(" Null:");
		Ret();
		ChangedPC = FALSE;
		NextInstruction = FINISH_SUB_BLOCK;
	} else if ( NextInstruction == DELAY_SLOT_EXIT_DONE ) {
		NextInstruction = FINISH_SUB_BLOCK;	
		Ret();
	} else {
		CompilerWarning("WTF\n\nJR\nNextInstruction = %X", NextInstruction);
		BreakPoint();
	}
}

void Compile_Special_JALR ( void ) {
	BYTE * Jump;
	DWORD Const = (CompilePC + 8) & 0xFFC;

	if (NextInstruction == NORMAL) {		
		CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));
		MoveConstToVariable(Const, &RSP_GPR[RSPOpC.rd].W,GPR_Name(RSPOpC.rd));
		MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W,GPR_Name(RSPOpC.rs),x86_EAX);
		AndConstToX86Reg(x86_EAX,0xFFC);
		MoveX86regToVariable(x86_EAX,PrgCount,"RSP PC");
		NextInstruction = DO_DELAY_SLOT;
	} else if (NextInstruction == DELAY_SLOT_DONE) {
		MoveVariableToX86reg(PrgCount,"RSP PC", x86_EAX);
		AddVariableToX86reg(x86_EAX, &JumpTable, "JumpTable");
		MoveX86regPointerToX86reg(x86_EAX, x86_EAX);

		TestX86RegToX86Reg(x86_EAX, x86_EAX);
		JeLabel8("Null", 0);
		Jump = RecompPos - 1;
		JumpX86Reg(x86_EAX);

		x86_SetBranch8b(Jump, RecompPos);
		CPU_Message(" Null:");
		Ret();
		NextInstruction = FINISH_SUB_BLOCK;
	} else if ( NextInstruction == DELAY_SLOT_EXIT_DONE ) {
		NextInstruction = FINISH_SUB_BLOCK;	
		Ret();
	} else {
		CompilerWarning("WTF\n\nJALR\nNextInstruction = %X", NextInstruction);
		BreakPoint();
	}
}

void Compile_Special_BREAK ( void ) {
	Cheat_r4300iOpcode(RSP_Special_BREAK,"RSP_Special_BREAK");
	if (NextInstruction == NORMAL) {
		MoveConstToVariable(CompilePC + 4,PrgCount,"RSP PC");
		Ret();
		NextInstruction = FINISH_SUB_BLOCK;
	} else {
		CompilerWarning("WTF\n\nBREAK\nNextInstruction = %X", NextInstruction);
		BreakPoint();
	}
}

void Compile_Special_ADD ( void ) {
	#ifndef Compile_Special
	Cheat_r4300iOpcode(RSP_Special_ADD,"RSP_Special_ADD"); return;
	#endif

	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));

	if (RSPOpC.rd == 0) return;

	if (RSPOpC.rd == RSPOpC.rs) {
		MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].W, GPR_Name(RSPOpC.rt), x86_EAX);
		AddX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd));
	} else if (RSPOpC.rd == RSPOpC.rt) {
		MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, GPR_Name(RSPOpC.rs), x86_EAX);
		AddX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd));
	} else if (RSPOpC.rs == RSPOpC.rt) {
		MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, GPR_Name(RSPOpC.rs), x86_EAX);
		AddX86RegToX86Reg(x86_EAX, x86_EAX);
		MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd));
	} else if (RSPOpC.rs == 0) {
		MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].W, GPR_Name(RSPOpC.rt), x86_EAX);
		MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd));
	} else if (RSPOpC.rt == 0) {
		MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, GPR_Name(RSPOpC.rs), x86_EAX);
		MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd));
	} else {
		MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, GPR_Name(RSPOpC.rs), x86_EAX);
		AddVariableToX86reg(x86_EAX, &RSP_GPR[RSPOpC.rt].W, GPR_Name(RSPOpC.rt));
		MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd));
	}
}

void Compile_Special_ADDU ( void ) {
	#ifndef Compile_Special
	Cheat_r4300iOpcode(RSP_Special_ADDU,"RSP_Special_ADDU"); return;
	#endif

	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));

	if (RSPOpC.rd == 0) return;

	if (RSPOpC.rd == RSPOpC.rs) {
		MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].W, GPR_Name(RSPOpC.rt), x86_EAX);
		AddX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd));
	} else if (RSPOpC.rd == RSPOpC.rt) {
		MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, GPR_Name(RSPOpC.rs), x86_EAX);
		AddX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd));
	} else if (RSPOpC.rs == RSPOpC.rt) {
		MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, GPR_Name(RSPOpC.rs), x86_EAX);
		AddX86RegToX86Reg(x86_EAX, x86_EAX);
		MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd));
	} else if (RSPOpC.rs == 0) {
		MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].W, GPR_Name(RSPOpC.rt), x86_EAX);
		MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd));
	} else if (RSPOpC.rt == 0) {
		MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, GPR_Name(RSPOpC.rs), x86_EAX);
		MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd));
	} else {
		MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, GPR_Name(RSPOpC.rs), x86_EAX);
		AddVariableToX86reg(x86_EAX, &RSP_GPR[RSPOpC.rt].W, GPR_Name(RSPOpC.rt));
		MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd));
	}
}

void Compile_Special_SUB ( void ) {
	#ifndef Compile_Special
	Cheat_r4300iOpcode(RSP_Special_SUB,"RSP_Special_SUB"); return;
	#endif

	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));

	if (RSPOpC.rd == 0) return;

	if (RSPOpC.rd == RSPOpC.rs) {
		MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].W, GPR_Name(RSPOpC.rt), x86_EAX);
		SubX86regFromVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W, "RSP_GPR[RSPOpC.rd].W");
	} else if (RSPOpC.rs == RSPOpC.rt) {
		MoveConstToVariable(0, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd));
	} else {
		MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, GPR_Name(RSPOpC.rs), x86_EAX);
		SubVariableFromX86reg(x86_EAX, &RSP_GPR[RSPOpC.rt].W, GPR_Name(RSPOpC.rt));
		MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd));
	}
}

void Compile_Special_SUBU ( void ) {
	#ifndef Compile_Special
	Cheat_r4300iOpcode(RSP_Special_SUBU,"RSP_Special_SUBU"); return;
	#endif

	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));

	if (RSPOpC.rd == 0) return;

	if (RSPOpC.rd == RSPOpC.rs) {
		MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].W, GPR_Name(RSPOpC.rt), x86_EAX);
		SubX86regFromVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd));
	} else if (RSPOpC.rs == RSPOpC.rt) {
		MoveConstToVariable(0, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd));
	} else {
		MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, GPR_Name(RSPOpC.rs), x86_EAX);
		SubVariableFromX86reg(x86_EAX, &RSP_GPR[RSPOpC.rt].W, GPR_Name(RSPOpC.rt));
		MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd));
	}
}

void Compile_Special_AND ( void ) {
	#ifndef Compile_Special
	Cheat_r4300iOpcode(RSP_Special_AND,"RSP_Special_AND"); return;
	#endif

	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));

	if (RSPOpC.rd == 0) return;

	if (RSPOpC.rd == RSPOpC.rs) {
		MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].W, GPR_Name(RSPOpC.rt), x86_EAX);
		AndX86RegToVariable(&RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd), x86_EAX);
	} else if (RSPOpC.rd == RSPOpC.rt) {
		MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, GPR_Name(RSPOpC.rs), x86_EAX);
		AndX86RegToVariable(&RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd), x86_EAX);
	} else if (RSPOpC.rs == RSPOpC.rt) {
		MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, GPR_Name(RSPOpC.rs), x86_EAX);
		MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd));
	} else {
		MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, GPR_Name(RSPOpC.rs), x86_EAX);
		AndVariableToX86Reg(&RSP_GPR[RSPOpC.rt].W, GPR_Name(RSPOpC.rt), x86_EAX);
		MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd));
	}
}

void Compile_Special_OR ( void ) {
	#ifndef Compile_Special
	Cheat_r4300iOpcode(RSP_Special_OR,"RSP_Special_OR"); return;
	#endif

	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));

	if (RSPOpC.rd == 0) return;

	if (RSPOpC.rd == RSPOpC.rs) {
		MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].W, GPR_Name(RSPOpC.rt), x86_EAX);
		OrX86RegToVariable(&RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd), x86_EAX);
	} else if (RSPOpC.rd == RSPOpC.rt) {
		MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, GPR_Name(RSPOpC.rs), x86_EAX);
		OrX86RegToVariable(&RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd), x86_EAX);
	} else if (RSPOpC.rs == 0) {
		MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].W, GPR_Name(RSPOpC.rt), x86_EAX);
		MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd));
	} else if (RSPOpC.rt == 0) {
		MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, GPR_Name(RSPOpC.rs), x86_EAX);
		MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd));
	} else {
		MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, GPR_Name(RSPOpC.rs), x86_EAX);
		OrVariableToX86Reg(&RSP_GPR[RSPOpC.rt].W, GPR_Name(RSPOpC.rt), x86_EAX);
		MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd));
	}
}

void Compile_Special_XOR ( void ) {
	#ifndef Compile_Special
	Cheat_r4300iOpcode(RSP_Special_XOR,"RSP_Special_XOR"); return;
	#endif
	
	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));

	if (RSPOpC.rd == 0) return;

	if (RSPOpC.rd == RSPOpC.rs) {
		MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].W, GPR_Name(RSPOpC.rt), x86_EAX);
		XorX86RegToVariable(&RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd), x86_EAX);
	} else if (RSPOpC.rd == RSPOpC.rt) {
		MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, GPR_Name(RSPOpC.rs), x86_EAX);
		XorX86RegToVariable(&RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd), x86_EAX);
	} else if (RSPOpC.rs == RSPOpC.rt) {
		MoveConstToVariable(0, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd));
	} else {
		MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, GPR_Name(RSPOpC.rs), x86_EAX);
		XorVariableToX86reg(&RSP_GPR[RSPOpC.rt].W, GPR_Name(RSPOpC.rt), x86_EAX);
		MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd));
	}
}

void Compile_Special_NOR ( void ) {
	Cheat_r4300iOpcode(RSP_Special_NOR,"RSP_Special_NOR");
}

void Compile_Special_SLT ( void ) {
	#ifndef Compile_Special
	Cheat_r4300iOpcode(RSP_Special_SLT,"RSP_Special_SLT"); return;
	#endif

	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));
	if (RSPOpC.rt == 0) { return; }

	if (RSPOpC.rt == RSPOpC.rs) {
		MoveConstToVariable(0, &RSP_GPR[RSPOpC.rd].UW, GPR_Name(RSPOpC.rd));
	} else {
		XorX86RegToX86Reg(x86_EBX, x86_EBX);
		if (RSPOpC.rs == 0) {
			MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt), x86_EAX);
			CompConstToX86reg(x86_EAX, 0);
			Setg(x86_EBX);
		} else if (RSPOpC.rt == 0) {
			MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].UW, GPR_Name(RSPOpC.rs), x86_EAX);
			CompConstToX86reg(x86_EAX, 0);
			Setl(x86_EBX);
		} else {
			MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].UW, GPR_Name(RSPOpC.rs), x86_EAX);
			CompX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt));
			Setl(x86_EBX);
		}
		MoveX86regToVariable(x86_EBX, &RSP_GPR[RSPOpC.rd].UW, GPR_Name(RSPOpC.rd));
	}
}

void Compile_Special_SLTU ( void ) {
	Cheat_r4300iOpcode(RSP_Special_SLTU,"RSP_Special_SLTU");
}

/********************** R4300i OpCodes: RegImm **********************/
void Compile_RegImm_BLTZ ( void ) {
	static BOOL bDelayAffect;

	if ( NextInstruction == NORMAL ) {
		CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));
		if (RSPOpC.rs == 0) {
			NextInstruction = DO_DELAY_SLOT;			
			return;
		}
		bDelayAffect = DelaySlotAffectBranch(CompilePC);
		if (FALSE == bDelayAffect) {
			NextInstruction = DO_DELAY_SLOT;
			return;
		}
		CompConstToVariable(0,&RSP_GPR[RSPOpC.rs].W,GPR_Name(RSPOpC.rs));
		SetlVariable(&BranchCompare, "BranchCompare");
		NextInstruction = DO_DELAY_SLOT;	
	} else if ( NextInstruction == DELAY_SLOT_DONE ) {
		DWORD Target = (CompilePC + ((short)RSPOpC.offset << 2) + 4) & 0xFFC;
		
		if (RSPOpC.rs == 0) {
			NextInstruction = FINISH_SUB_BLOCK;
			return;
		}
		if (FALSE == bDelayAffect) {
			CompConstToVariable(0,&RSP_GPR[RSPOpC.rs].W,GPR_Name(RSPOpC.rs));
			JlLabel32("BranchLess", 0);
		} else {
			/* take a look at the branch compare variable */
			CompConstToVariable(TRUE, &BranchCompare, "BranchCompare");
			JeLabel32("BranchLess", 0);
		}
		Branch_AddRef(Target, (DWORD*)(RecompPos - 4));
		NextInstruction = FINISH_SUB_BLOCK;
	} else if ( NextInstruction == DELAY_SLOT_EXIT_DONE ) {
		DWORD Target = (CompilePC + ((short)RSPOpC.offset << 2) + 4) & 0xFFC;
		CompileBranchExit(Target, CompilePC + 8);
	} else {
		CompilerWarning("BLTZ error\nWeird Delay Slot.\n\nNextInstruction = %X\nPC = %X\nEmulation will now stop", NextInstruction, CompilePC);
		BreakPoint();
	}
}

void Compile_RegImm_BGEZ ( void ) {
	static BOOL bDelayAffect;

	if ( NextInstruction == NORMAL ) {
		CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));
		if (RSPOpC.rs == 0) {
			NextInstruction = DO_DELAY_SLOT;			
			return;
		}
		bDelayAffect = DelaySlotAffectBranch(CompilePC);
		if (FALSE == bDelayAffect) {
			NextInstruction = DO_DELAY_SLOT;
			return;
		}
		CompConstToVariable(0,&RSP_GPR[RSPOpC.rs].W,GPR_Name(RSPOpC.rs));
		SetgeVariable(&BranchCompare, "BranchCompare");
		NextInstruction = DO_DELAY_SLOT;	
	} else if ( NextInstruction == DELAY_SLOT_DONE ) {
		DWORD Target = (CompilePC + ((short)RSPOpC.offset << 2) + 4) & 0xFFC;
		
		if (RSPOpC.rs == 0) {			
			JmpLabel32 ( "BranchToJump", 0 );
			Branch_AddRef(Target, (DWORD*)(RecompPos - 4));
			NextInstruction = FINISH_SUB_BLOCK;
			return;
		}
		if (FALSE == bDelayAffect) {
			CompConstToVariable(0,&RSP_GPR[RSPOpC.rs].W,GPR_Name(RSPOpC.rs));
			JgeLabel32("BranchGreaterEqual", 0);
		} else {
			/* take a look at the branch compare variable */
			CompConstToVariable(TRUE, &BranchCompare, "BranchCompare");
			JeLabel32("BranchGreaterEqual", 0);
		}
		Branch_AddRef(Target, (DWORD*)(RecompPos - 4));
		NextInstruction = FINISH_SUB_BLOCK;
	} else if ( NextInstruction == DELAY_SLOT_EXIT_DONE ) {
		DWORD Target = (CompilePC + ((short)RSPOpC.offset << 2) + 4) & 0xFFC;
		CompileBranchExit(Target, CompilePC + 8);
	} else {
		CompilerWarning("BGEZ error\nWeird Delay Slot.\n\nNextInstruction = %X\nEmulation will now stop", NextInstruction);
		BreakPoint();
	}
}

void Compile_RegImm_BLTZAL ( void ) {
	if ( NextInstruction == NORMAL ) {
		CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));
		MoveConstToVariable(CompilePC + 8, &RSP_GPR[31].UW, "RA.W");
		if (RSPOpC.rs == 0) {
			NextInstruction = DO_DELAY_SLOT;			
			return;
		}
		CompConstToVariable(0,&RSP_GPR[RSPOpC.rs].W,GPR_Name(RSPOpC.rs));
		SetlVariable(&BranchCompare, "BranchCompare");
		NextInstruction = DO_DELAY_SLOT;	
	} else if ( NextInstruction == DELAY_SLOT_DONE ) {
		DWORD Target = (CompilePC + ((short)RSPOpC.offset << 2) + 4) & 0xFFC;
		
		if (RSPOpC.rs == 0) {
			NextInstruction = FINISH_SUB_BLOCK;
			return;
		}

		/* take a look at the branch compare variable */
		CompConstToVariable(TRUE, &BranchCompare, "BranchCompare");
		JeLabel32("BranchLessEqual", 0);
		Branch_AddRef(Target, (DWORD*)(RecompPos - 4));
		NextInstruction = FINISH_SUB_BLOCK;
	} else if ( NextInstruction == DELAY_SLOT_EXIT_DONE ) {
		DWORD Target = (CompilePC + ((short)RSPOpC.offset << 2) + 4) & 0xFFC;
		CompileBranchExit(Target, CompilePC + 8);
	} else {
		CompilerWarning("BLTZAL error\nWeird Delay Slot.\n\nNextInstruction = %X\nEmulation will now stop", NextInstruction);
		BreakPoint();
	}
}

void Compile_RegImm_BGEZAL ( void ) {
	static BOOL bDelayAffect;

	if ( NextInstruction == NORMAL ) {
		CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));
		MoveConstToVariable(CompilePC + 8, &RSP_GPR[31].UW, "RA.W");
		if (RSPOpC.rs == 0) {
			NextInstruction = DO_DELAY_SLOT;
			return;
		}
		bDelayAffect = DelaySlotAffectBranch(CompilePC);
		if (FALSE == bDelayAffect) {
			NextInstruction = DO_DELAY_SLOT;
			return;
		}
		CompConstToVariable(0,&RSP_GPR[RSPOpC.rs].W,GPR_Name(RSPOpC.rs));
		SetgeVariable(&BranchCompare, "BranchCompare");
		NextInstruction = DO_DELAY_SLOT;	
	} else if ( NextInstruction == DELAY_SLOT_DONE ) {
		DWORD Target = (CompilePC + ((short)RSPOpC.offset << 2) + 4) & 0xFFC;
		
		if (RSPOpC.rs == 0) {			
			JmpLabel32 ( "BranchToJump", 0 );
			Branch_AddRef(Target, (DWORD*)(RecompPos - 4));
			NextInstruction = FINISH_SUB_BLOCK;
			return;
		}
		if (FALSE == bDelayAffect) {
			CompConstToVariable(0,&RSP_GPR[RSPOpC.rs].W,GPR_Name(RSPOpC.rs));
			JgeLabel32("BranchGreaterEqual", 0);
		} else {
			/* take a look at the branch compare variable */
			CompConstToVariable(TRUE, &BranchCompare, "BranchCompare");
			JeLabel32("BranchGreaterEqual", 0);
		}
		Branch_AddRef(Target, (DWORD*)(RecompPos - 4));
		NextInstruction = FINISH_SUB_BLOCK;
	} else if ( NextInstruction == DELAY_SLOT_EXIT_DONE ) {
		DWORD Target = (CompilePC + ((short)RSPOpC.offset << 2) + 4) & 0xFFC;
		CompileBranchExit(Target, CompilePC + 8);
	} else {
		CompilerWarning("BGEZAL error\nWeird Delay Slot.\n\nNextInstruction = %X\nEmulation will now stop", NextInstruction);
		BreakPoint();
	}
}

/************************** Cop0 functions *************************/

void Compile_Cop0_MF ( void ) {
	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));
	if (LogRDP)
	{		
		char str[40];

		sprintf(str,"%d",RSPOpC.rd);
		PushImm32(str,RSPOpC.rd);
		sprintf(str,"%X",CompilePC);		
		PushImm32(str,CompilePC);
		Call_Direct(RDP_LogMF0,"RDP_LogMF0");
		AddConstToX86Reg(x86_ESP, 8);
	}

#ifndef Compile_Cop0
	Cheat_r4300iOpcode(RSP_Cop0_MF,"RSP_Cop0_MF"); 
	if (NextInstruction == NORMAL)
	{
		MoveConstToVariable(CompilePC + 4,PrgCount,"RSP PC");
		Ret();
		NextInstruction = FINISH_SUB_BLOCK;
	} else if (NextInstruction == DELAY_SLOT) {
		NextInstruction = DELAY_SLOT_EXIT;
	} else {
		CompilerWarning("MF error\nWeird Delay Slot.\n\nNextInstruction = %X\nEmulation will now stop", NextInstruction);
		BreakPoint();
	}
	return;
#else
	switch (RSPOpC.rd) {
	case 5: 
		MoveVariableToX86reg(RSPInfo.SP_DMA_FULL_REG, "SP_DMA_FULL_REG", x86_EAX);
		MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt));
		break;
	case 6: 
		MoveVariableToX86reg(RSPInfo.SP_DMA_BUSY_REG, "SP_DMA_BUSY_REG", x86_EAX);
		MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt));
		break;
	case 4: 
	case 7: 
		MoveConstToVariable(RSPOpC.Hex, &RSPOpC.Hex, "RSPOpC.Hex" );
		Call_Direct(RSP_Cop0_MF,"RSP_Cop0_MF");
		if (NextInstruction == NORMAL)
		{
			MoveConstToVariable(CompilePC + 4,PrgCount,"RSP PC");
			Ret();
			NextInstruction = FINISH_SUB_BLOCK;
		} else if (NextInstruction == DELAY_SLOT) {
			NextInstruction = DELAY_SLOT_EXIT;
		} else {
			CompilerWarning("MF error\nWeird Delay Slot.\n\nNextInstruction = %X\nEmulation will now stop", NextInstruction);
			BreakPoint();
		}
		break;
	case 8:
		MoveVariableToX86reg(RSPInfo.DPC_START_REG, "DPC_START_REG", x86_EAX);
		MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt));
		break;
	case 9:
		MoveVariableToX86reg(RSPInfo.DPC_END_REG, "DPC_END_REG", x86_EAX);
		MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt));
		break;
	case 10:
		MoveVariableToX86reg(RSPInfo.DPC_CURRENT_REG, "DPC_CURRENT_REG", x86_EAX);
		MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt));
		break;
	case 11: 
		MoveVariableToX86reg(RSPInfo.DPC_STATUS_REG, "DPC_STATUS_REG", x86_EAX);
		MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt));
		break;
	case 12: 
		MoveVariableToX86reg(RSPInfo.DPC_CLOCK_REG, "DPC_CLOCK_REG", x86_EAX);
		MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt));
		break;

	default:
		CompilerWarning("have not implemented RSP MF CP0 reg %s (%d)",COP0_Name(RSPOpC.rd),RSPOpC.rd);
	}
#endif
}

void Compile_Cop0_MT ( void ) 
{
	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));

	if (LogRDP)
	{	
		char str[40];

		MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt), x86_EAX);
		Push(x86_EAX);
		sprintf(str,"%d",RSPOpC.rd);
		PushImm32(str,RSPOpC.rd);
		sprintf(str,"%X",CompilePC);		
		PushImm32(str,CompilePC);
		Call_Direct(RDP_LogMT0,"RDP_LogMT0");
		AddConstToX86Reg(x86_ESP, 12);
	}

#ifndef Compile_Cop0
	Cheat_r4300iOpcode(RSP_Cop0_MT,"RSP_Cop0_MT");
	if (RSPOpC.rd == 4)
	{
		if (NextInstruction == NORMAL)
		{
			MoveConstToVariable(CompilePC + 4,PrgCount,"RSP PC");
			Ret();
			NextInstruction = FINISH_BLOCK;
		} else if (NextInstruction == DELAY_SLOT) {
			NextInstruction = DELAY_SLOT_EXIT;
		} else {
			CompilerWarning("MF error\nWeird Delay Slot.\n\nNextInstruction = %X\nEmulation will now stop", NextInstruction);
			BreakPoint();
		}
	}
#else
	switch (RSPOpC.rd) {
	case 0:
		MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt), x86_EAX);
		MoveX86regToVariable(x86_EAX, RSPInfo.SP_MEM_ADDR_REG,"SP_MEM_ADDR_REG");
		break;
	case 1:
		MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt), x86_EAX);
		MoveX86regToVariable(x86_EAX, RSPInfo.SP_DRAM_ADDR_REG,"SP_DRAM_ADDR_REG");
		break;
	case 2: 
		MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt), x86_EAX);
		MoveX86regToVariable(x86_EAX, RSPInfo.SP_RD_LEN_REG,"SP_RD_LEN_REG");
		Call_Direct(SP_DMA_READ, "SP_DMA_READ");
		break;
	case 3: 
		MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt), x86_EAX);
		MoveX86regToVariable(x86_EAX, RSPInfo.SP_WR_LEN_REG,"SP_WR_LEN_REG");
		Call_Direct(SP_DMA_WRITE, "SP_DMA_WRITE");
		break;
	case 7: 
		MoveConstToVariable(0, RSPInfo.SP_SEMAPHORE_REG, "SP_SEMAPHORE_REG");
		break;
	case 8: 
		MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt), x86_EAX);
		MoveX86regToVariable(x86_EAX, RSPInfo.DPC_START_REG,"DPC_START_REG");
		MoveX86regToVariable(x86_EAX, RSPInfo.DPC_CURRENT_REG,"DPC_CURRENT_REG");
		break;
	case 9: 
		MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt), x86_EAX);
		MoveX86regToVariable(x86_EAX, RSPInfo.DPC_END_REG,"DPC_END_REG");

		if (LogRDP)
		{
			Call_Direct(RDP_LogDlist, "RDP_LogDlist");
		}
			
		if (RSPInfo.ProcessRdpList != NULL)
		{
			if (Profiling)
			{
				PushImm32("Timer_RDP_Running",(DWORD)Timer_RDP_Running);
				Call_Direct(StartTimer,"StartTimer");
				AddConstToX86Reg(x86_ESP, 4);
				Push(x86_EAX);
			}
			Call_Direct(RSPInfo.ProcessRdpList, "ProcessRdpList");
			if (Profiling)
			{
				Call_Direct(StartTimer,"StartTimer");
				AddConstToX86Reg(x86_ESP, 4);
			}
		}


		break;
	case 10:
		MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt), x86_EAX);
		MoveX86regToVariable(x86_EAX, RSPInfo.DPC_CURRENT_REG,"DPC_CURRENT_REG");
		break;

	default:
		Cheat_r4300iOpcode(RSP_Cop0_MT,"RSP_Cop0_MT");
		break;
	}
#endif
	if (RSPOpC.rd == 2 && !ChangedPC) {
		BYTE * Jump;

		TestConstToVariable(0x1000, RSPInfo.SP_MEM_ADDR_REG, "RSPInfo.SP_MEM_ADDR_REG");
		JeLabel8("DontExit", 0);
		Jump = RecompPos - 1;

		MoveConstToVariable(CompilePC + 4,PrgCount,"RSP PC");
		Ret();

		CPU_Message("DontExit:");
		x86_SetBranch8b(Jump, RecompPos);
	}
}
/************************** Cop2 functions *************************/

void Compile_Cop2_MF ( void ) {
	char Reg[256];
	int element = (RSPOpC.sa >> 1);

	int element1 = 15 - element;
	int element2 = 15 - ((element + 1) % 16);
	
	#ifndef Compile_Cop2
	Cheat_r4300iOpcode(RSP_Cop2_MF,"RSP_Cop2_MF"); return;
	#endif

	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));

	if (element2 != (element1 - 1)) {
		XorX86RegToX86Reg(x86_EAX, x86_EAX);
		XorX86RegToX86Reg(x86_EBX, x86_EBX);

		sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rd, element1);
		MoveVariableToX86regByte(&RSP_Vect[RSPOpC.rd].B[element1], Reg, x86_EAX);

		sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rd, element2);
		MoveVariableToX86regByte(&RSP_Vect[RSPOpC.rd].B[element2], Reg, x86_EBX);

		ShiftLeftSignImmed(x86_EAX, 8);
		OrX86RegToX86Reg(x86_EAX, x86_EBX);
		Cwde();

		MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].W, GPR_Name(RSPOpC.rt));
	} else {
		sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rd, element2);
		MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].B[element2], Reg, x86_EAX);

		MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].W, GPR_Name(RSPOpC.rt));
	}
}

void Compile_Cop2_CF ( void ) {
	#ifndef Compile_Cop2
	Cheat_r4300iOpcode(RSP_Cop2_CF, "RSP_Cop2_CF"); return;
	#endif
	
	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));
	
	switch ((RSPOpC.rd & 0x03)) {
	case 0:
		MoveSxVariableToX86regHalf(&RSP_Flags[0].HW[0], "RSP_Flags[0].HW[0]", x86_EAX);
		MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].W, GPR_Name(RSPOpC.rt));
		break;
	case 1:
		MoveSxVariableToX86regHalf(&RSP_Flags[1].HW[0], "RSP_Flags[1].HW[0]", x86_EAX);
		MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].W, GPR_Name(RSPOpC.rt));
		break;
	case 2:
	case 3:
		MoveSxVariableToX86regHalf(&RSP_Flags[2].HW[0], "RSP_Flags[2].HW[0]", x86_EAX);
		MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].W, GPR_Name(RSPOpC.rt));
		break;
	}
}

void Compile_Cop2_MT ( void ) {
	char Reg[256];
	int element = 15 - (RSPOpC.sa >> 1);

	#ifndef Compile_Cop2
	Cheat_r4300iOpcode(RSP_Cop2_MT,"RSP_Cop2_MT"); return;
	#endif

	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));

	if (element == 0) {
		sprintf(Reg, "RSP_GPR[%i].B[1]", RSPOpC.rt);
		MoveVariableToX86regByte(&RSP_GPR[RSPOpC.rt].B[1], Reg, x86_EAX);

		sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rd, element);
		MoveX86regByteToVariable(x86_EAX, &RSP_Vect[RSPOpC.rd].B[element], Reg);
	} else {
		sprintf(Reg, "RSP_GPR[%i].B[0]", RSPOpC.rt);
		MoveVariableToX86regHalf(&RSP_GPR[RSPOpC.rt].B[0], Reg, x86_EAX);

		sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rd, element - 1);
		MoveX86regHalfToVariable(x86_EAX, &RSP_Vect[RSPOpC.rd].B[element - 1], Reg);
	}
}

void Compile_Cop2_CT ( void ) {
	#ifndef Compile_Cop2
	Cheat_r4300iOpcode(RSP_Cop2_CT, "RSP_Cop2_CT"); return;
	#endif

	CPU_Message("  %X %s", CompilePC, RSPOpcodeName(RSPOpC.Hex, CompilePC));

	if (RSPOpC.rt == 0){
		switch ((RSPOpC.rd & 0x03)) {
		case 0:
			MoveConstHalfToVariable(0, &RSP_Flags[0].HW[0], "RSP_Flags[0].HW[0]");
			break;
		case 1:
			MoveConstHalfToVariable(0, &RSP_Flags[1].HW[0], "RSP_Flags[1].HW[0]");
			break;
		case 2:
		case 3:
			MoveConstByteToVariable(0, &RSP_Flags[2].B[0], "RSP_Flags[2].B[0]");
			break;
		}
	} else{
		switch ((RSPOpC.rd & 0x03)) {
		case 0:
			MoveVariableToX86regHalf(&RSP_GPR[RSPOpC.rt].HW[0], GPR_Name(RSPOpC.rt), x86_EAX);
			MoveX86regHalfToVariable(x86_EAX, &RSP_Flags[0].HW[0], "RSP_Flags[0].HW[0]");
			break;
		case 1:
			MoveVariableToX86regHalf(&RSP_GPR[RSPOpC.rt].HW[0], GPR_Name(RSPOpC.rt), x86_EAX);
			MoveX86regHalfToVariable(x86_EAX, &RSP_Flags[1].HW[0], "RSP_Flags[1].HW[0]");
			break;
		case 2:
		case 3:
			MoveVariableToX86regByte(&RSP_GPR[RSPOpC.rt].B[0], GPR_Name(RSPOpC.rt), x86_EAX);
			MoveX86regByteToVariable(x86_EAX, &RSP_Flags[2].B[0], "RSP_Flags[2].B[0]");
			break;
		}
	}
}

void Compile_COP2_VECTOR (void) {
	RSP_Vector[ RSPOpC.funct ]();
}

/************************** Vect functions **************************/

UDWORD MMX_Scratch;

void RSP_Element2Mmx(int MmxReg) {
	char Reg[256];

	DWORD Rs = RSPOpC.rs & 0x0f;
	DWORD el;

	switch (Rs) {
	case 0: case 1:
	case 2: case 3:
	case 4:	case 5:
	case 6:	case 7:
		CompilerWarning("Unimplemented RSP_Element2Mmx");
		break;

	default:
		/*
		 * Noticed the exclusive-or of seven to take into account
		 * the pseudo-swapping we have in the vector registers
		 */

		el = (RSPOpC.rs & 0x07) ^ 7;

		if (IsMmx2Enabled == FALSE) {
			sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, el);
			MoveVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[el], Reg, x86_ECX);
			MoveX86regHalfToVariable(x86_ECX, &MMX_Scratch.HW[0], "MMX_Scratch.HW[0]");
			MoveX86regHalfToVariable(x86_ECX, &MMX_Scratch.HW[1], "MMX_Scratch.HW[1]");
			MoveX86regHalfToVariable(x86_ECX, &MMX_Scratch.HW[2], "MMX_Scratch.HW[2]");
			MoveX86regHalfToVariable(x86_ECX, &MMX_Scratch.HW[3], "MMX_Scratch.HW[3]");
			MmxMoveQwordVariableToReg(MmxReg, &MMX_Scratch.HW[0], "MMX_Scratch.HW[0]");
		} else {
			unsigned long Qword;
			
			Qword = (el >> 2) & 0x1;
			el &= 0x3;

			sprintf(Reg, "RSP_Vect[%i].DW[%i]", RSPOpC.rt, Qword);
			MmxShuffleMemoryToReg(MmxReg, 
				&RSP_Vect[RSPOpC.rt].DW[Qword], Reg, _MMX_SHUFFLE(el, el, el, el));
		}
		break;
	}
}

void RSP_MultiElement2Mmx(int MmxReg1, int MmxReg2) {
	char Reg[256];
	DWORD Rs = RSPOpC.rs & 0x0f;

	/*
	 * Ok, this is tricky, hopefully this clears it up:
	 *
	 * $vd[0] = $vd[0] + $vt[2] 
	 * because of swapped registers becomes:
	 * $vd[7] = $vd[7] + $vt[5]
	 *
	 * we must perform this swap correctly, this involves the 3-bit
	 * xclusive or, 2-bits of which are done within a dword boundary, 
	 * the last bit, is ignored because we are loading the source linearly,
	 * so the xclusive or has transparently happened on that side
	 *
	 */

	switch (Rs) {
	case 0:
	case 1:
		sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.rt);
		MmxMoveQwordVariableToReg(MmxReg1, &RSP_Vect[RSPOpC.rt].UHW[0], Reg);
		sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.rt);
		MmxMoveQwordVariableToReg(MmxReg2, &RSP_Vect[RSPOpC.rt].UHW[4], Reg);
		break;
	case 2:
		/* [0q]    | 0 | 0 | 2 | 2 | 4 | 4 | 6 | 6 | */
		sprintf(Reg, "RSP_Vect[%i].DW[0]", RSPOpC.rt);
		MmxShuffleMemoryToReg(MmxReg1, &RSP_Vect[RSPOpC.rt].DW[0], Reg, 0xF5);
		sprintf(Reg, "RSP_Vect[%i].DW[1]", RSPOpC.rt);
		MmxShuffleMemoryToReg(MmxReg2, &RSP_Vect[RSPOpC.rt].DW[1], Reg, 0xF5);
		break;
	case 3:
		/* [1q]    | 1 | 1 | 3 | 3 | 5 | 5 | 7 | 7 | */
		sprintf(Reg, "RSP_Vect[%i].DW[0]", RSPOpC.rt);
		MmxShuffleMemoryToReg(MmxReg1, &RSP_Vect[RSPOpC.rt].DW[0], Reg, 0xA0);
		//MmxShuffleMemoryToReg(MmxReg1, &RSP_Vect[RSPOpC.rt].DW[0], Reg, 0x0A);
		sprintf(Reg, "RSP_Vect[%i].DW[1]", RSPOpC.rt);
		MmxShuffleMemoryToReg(MmxReg2, &RSP_Vect[RSPOpC.rt].DW[1], Reg, 0xA0);
		//MmxShuffleMemoryToReg(MmxReg2, &RSP_Vect[RSPOpC.rt].DW[1], Reg, 0x0A);
		break;
	case 4:
		/* [0h]    | 0 | 0 | 0 | 0 | 4 | 4 | 4 | 4 | */
		sprintf(Reg, "RSP_Vect[%i].DW[0]", RSPOpC.rt);
		MmxShuffleMemoryToReg(MmxReg1, &RSP_Vect[RSPOpC.rt].DW[0], Reg, 0xFF);
		sprintf(Reg, "RSP_Vect[%i].DW[1]", RSPOpC.rt);
		MmxShuffleMemoryToReg(MmxReg2, &RSP_Vect[RSPOpC.rt].DW[1], Reg, 0xFF);
		break;
	case 5:
		/* [1h]    | 1 | 1 | 1 | 1 | 5 | 5 | 5 | 5 | */
		sprintf(Reg, "RSP_Vect[%i].DW[0]", RSPOpC.rt);
		MmxShuffleMemoryToReg(MmxReg1, &RSP_Vect[RSPOpC.rt].DW[0], Reg, 0xAA);
		sprintf(Reg, "RSP_Vect[%i].DW[1]", RSPOpC.rt);
		MmxShuffleMemoryToReg(MmxReg2, &RSP_Vect[RSPOpC.rt].DW[1], Reg, 0xAA);
		break;
	case 6:
		/* [2h]    | 2 | 2 | 2 | 2 | 6 | 6 | 6 | 6 | */
		sprintf(Reg, "RSP_Vect[%i].DW[0]", RSPOpC.rt);
		MmxShuffleMemoryToReg(MmxReg1, &RSP_Vect[RSPOpC.rt].DW[0], Reg, 0x55);
		sprintf(Reg, "RSP_Vect[%i].DW[1]", RSPOpC.rt);
		MmxShuffleMemoryToReg(MmxReg2, &RSP_Vect[RSPOpC.rt].DW[1], Reg, 0x55);
		break;
	case 7:
		/* [3h]    | 3 | 3 | 3 | 3 | 7 | 7 | 7 | 7 | */
		sprintf(Reg, "RSP_Vect[%i].DW[0]", RSPOpC.rt);
		MmxShuffleMemoryToReg(MmxReg1, &RSP_Vect[RSPOpC.rt].DW[0], Reg, 0x00);
		sprintf(Reg, "RSP_Vect[%i].DW[1]", RSPOpC.rt);
		MmxShuffleMemoryToReg(MmxReg2, &RSP_Vect[RSPOpC.rt].DW[1], Reg, 0x00);
		break;

	default:
		CompilerWarning("Unimplemented RSP_MultiElement2Mmx [?]");
		break;
	}
}

BOOL Compile_Vector_VMULF_MMX ( void ) {
	char Reg[256];

	/* Do our MMX checks here */
	if (IsMmxEnabled == FALSE)
		return FALSE;
	if ((RSPOpC.rs & 0x0f) >= 2 && (RSPOpC.rs & 0x0f) <= 7 && IsMmx2Enabled == FALSE)
		return FALSE;

	/* NOTE: Problem here is the lack of +/- 0x8000 rounding */
	sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.rd);
	MmxMoveQwordVariableToReg(x86_MM0, &RSP_Vect[RSPOpC.rd].UHW[0], Reg);
	sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.rd);
	MmxMoveQwordVariableToReg(x86_MM1, &RSP_Vect[RSPOpC.rd].UHW[4], Reg);

	if ((RSPOpC.rs & 0xF) < 2) {
		if (RSPOpC.rd == RSPOpC.rt){
			MmxPmulhwRegToReg(x86_MM0, x86_MM0);
			MmxPmulhwRegToReg(x86_MM1, x86_MM1);
		} else {
			sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.rt);
			MmxPmulhwRegToVariable(x86_MM0, &RSP_Vect[RSPOpC.rt].UHW[0], Reg);
			sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.rt);
			MmxPmulhwRegToVariable(x86_MM1, &RSP_Vect[RSPOpC.rt].UHW[4], Reg);
		}
	} else if ((RSPOpC.rs & 0xF) >= 8) {
		RSP_Element2Mmx(x86_MM2);
		MmxPmulhwRegToReg(x86_MM0, x86_MM2);
		MmxPmulhwRegToReg(x86_MM1, x86_MM2);
	} else {
		RSP_MultiElement2Mmx(x86_MM2, x86_MM3);
		MmxPmulhwRegToReg(x86_MM0, x86_MM2);
		MmxPmulhwRegToReg(x86_MM1, x86_MM3);
	}
	MmxPsllwImmed(x86_MM0, 1);
	MmxPsllwImmed(x86_MM1, 1);

	sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.sa);
	MmxMoveQwordRegToVariable(x86_MM0, &RSP_Vect[RSPOpC.sa].UHW[0], Reg);
	sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.sa);
	MmxMoveQwordRegToVariable(x86_MM1, &RSP_Vect[RSPOpC.sa].UHW[4], Reg);

	if (IsNextInstructionMmx(CompilePC) == FALSE)
		MmxEmptyMultimediaState();

	return TRUE;
}

void Compile_Vector_VMULF ( void ) {
	char Reg[256];
	int count, el, del;

	BOOL bOptimize = ((RSPOpC.rs & 0x0f) >= 8) ? TRUE : FALSE;
	BOOL bWriteToAccum = WriteToAccum(EntireAccum, CompilePC);
	BOOL bWriteToDest = WriteToVectorDest(RSPOpC.sa, CompilePC);

	#ifndef CompileVmulf
	Cheat_r4300iOpcode(RSP_Vector_VMULF,"RSP_Vector_VMULF"); return;
	#endif

	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));

	if (bWriteToAccum == FALSE) {
		if (TRUE == Compile_Vector_VMULF_MMX())
			return;
	}

	if (bOptimize == TRUE) {
		del = (RSPOpC.rs & 0x07) ^ 7;
		sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del);
		MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX);
	}

	if (bWriteToDest == TRUE) {
		MoveConstToX86reg(0x7fff0000, x86_ESI);
	}
	if (bWriteToAccum == TRUE) {
		XorX86RegToX86Reg(x86_EDI, x86_EDI);
	}

	for (count = 0; count < 8; count++) {
		CPU_Message("     Iteration: %i", count);

		el = Indx[RSPOpC.rs].B[count];
		del = EleSpec[RSPOpC.rs].B[el];

		sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rd, el);
		MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].HW[el], Reg, x86_EAX);

		if (RSPOpC.rt == RSPOpC.rd && !bOptimize) {
			imulX86reg(x86_EAX);
		} else {
			if (bOptimize == FALSE) {
				sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del);
				MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX);
			}
			imulX86reg(x86_EBX);
		}

		ShiftLeftSignImmed(x86_EAX, 1);
		AddConstToX86Reg(x86_EAX, 0x8000);

		if (bWriteToAccum == TRUE) {
			MoveX86regToVariable(x86_EAX, &RSP_ACCUM[el].HW[1], "RSP_ACCUM[el].HW[1]");
			/* calculate sign extension into edx */
			MoveX86RegToX86Reg(x86_EAX, x86_EDX);
			ShiftRightSignImmed(x86_EDX, 31);
		}

		CompConstToX86reg(x86_EAX, 0x80008000);

		if (bWriteToAccum == TRUE) {
			CondMoveEqual(x86_EDX, x86_EDI);
			MoveX86regHalfToVariable(x86_EDX, &RSP_ACCUM[el].HW[3], "RSP_ACCUM[el].HW[3]");
		}
		if (bWriteToDest == TRUE) {
			CondMoveEqual(x86_EAX, x86_ESI);
			ShiftRightUnsignImmed(x86_EAX, 16);
			MoveX86regHalfToVariable(x86_EAX, &RSP_Vect[RSPOpC.sa].HW[el], "RSP_Vect[RSPOpC.sa].HW[el]");
		}
	}
}

void Compile_Vector_VMULU ( void ) {
	Cheat_r4300iOpcode(RSP_Vector_VMULU,"RSP_Vector_VMULU");
}

BOOL Compile_Vector_VMUDL_MMX ( void ) {
	char Reg[256];

	/* Do our MMX checks here */
	if (IsMmxEnabled == FALSE)
		return FALSE;
	if (IsMmx2Enabled == FALSE)
		return FALSE;

	sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.rd);
	MmxMoveQwordVariableToReg(x86_MM0, &RSP_Vect[RSPOpC.rd].UHW[0], Reg);
	sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.rd);
	MmxMoveQwordVariableToReg(x86_MM1, &RSP_Vect[RSPOpC.rd].UHW[4], Reg);

	if ((RSPOpC.rs & 0xF) < 2) {
		if (RSPOpC.rd == RSPOpC.rt){
			MmxPmulhuwRegToReg(x86_MM0, x86_MM0);
			MmxPmulhuwRegToReg(x86_MM1, x86_MM1);
		} else {
			sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.rt);
			MmxMoveQwordVariableToReg(x86_MM2, &RSP_Vect[RSPOpC.rt].UHW[0], Reg);
			sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.rt);
			MmxMoveQwordVariableToReg(x86_MM3, &RSP_Vect[RSPOpC.rt].UHW[4], Reg);

			MmxPmulhuwRegToReg(x86_MM0, x86_MM2);
			MmxPmulhuwRegToReg(x86_MM1, x86_MM3);
		}
	} else if ((RSPOpC.rs & 0xF) >= 8) {
		RSP_Element2Mmx(x86_MM2);
		MmxPmulhuwRegToReg(x86_MM0, x86_MM2);
		MmxPmulhuwRegToReg(x86_MM1, x86_MM2);
	} else {
		RSP_MultiElement2Mmx(x86_MM2, x86_MM3);
		MmxPmulhuwRegToReg(x86_MM0, x86_MM2);
		MmxPmulhuwRegToReg(x86_MM1, x86_MM3);
	}

	sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.sa);
	MmxMoveQwordRegToVariable(x86_MM0, &RSP_Vect[RSPOpC.sa].UHW[0], Reg);
	sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.sa);
	MmxMoveQwordRegToVariable(x86_MM1, &RSP_Vect[RSPOpC.sa].UHW[4], Reg);
	
	if (IsNextInstructionMmx(CompilePC) == FALSE)
		MmxEmptyMultimediaState();

	return TRUE;
}

void Compile_Vector_VMUDL ( void ) {
	char Reg[256];
	int count, el, del;
	
	BOOL bOptimize = ((RSPOpC.rs & 0x0f) >= 8) ? TRUE : FALSE;
	BOOL bWriteToDest = WriteToVectorDest(RSPOpC.sa, CompilePC);
	BOOL bWriteToAccum = WriteToAccum(EntireAccum, CompilePC);

	#ifndef CompileVmudl
	Cheat_r4300iOpcode(RSP_Vector_VMUDL,"RSP_Vector_VMUDL"); return;
	#endif

	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));

	if (bWriteToAccum == FALSE) {
		if (TRUE == Compile_Vector_VMUDL_MMX())
			return;
	}
	
	if (bOptimize == TRUE) {
		del = (RSPOpC.rs & 0x07) ^ 7;
		sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del);
		MoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX);
	}

	if (bWriteToAccum == TRUE)
		XorX86RegToX86Reg(x86_EDI, x86_EDI);

	for (count = 0; count < 8; count++) {
		CPU_Message("     Iteration: %i", count);
		el = Indx[RSPOpC.rs].B[count];
		del = EleSpec[RSPOpC.rs].B[el];

		sprintf(Reg, "RSP_Vect[%i].UHW[%i]", RSPOpC.rd, el);
		MoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].UHW[el], Reg, x86_EAX);

		if (bOptimize == FALSE) {
			sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del);
			MoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX);
		}

		imulX86reg(x86_EBX);

		if (bWriteToAccum == TRUE) {
			sprintf(Reg, "RSP_ACCUM[%i].UW[0]", el);
			MoveX86regToVariable(x86_EAX, &RSP_ACCUM[el].UW[0], Reg);
			sprintf(Reg, "RSP_ACCUM[%i].UW[1]", el);
			MoveX86regToVariable(x86_EDI, &RSP_ACCUM[el].UW[1], Reg);
		}

		if (bWriteToDest == TRUE) {
			ShiftRightUnsignImmed(x86_EAX, 16);
			sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.sa, el);
			MoveX86regHalfToVariable(x86_EAX, &RSP_Vect[RSPOpC.sa].HW[el], Reg);
		}
	}
}

BOOL Compile_Vector_VMUDM_MMX ( void ) {
	char Reg[256];

	/* Do our MMX checks here */
	if (IsMmxEnabled == FALSE)
		return FALSE;
	if (IsMmx2Enabled == FALSE)
		return FALSE;

	sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.rd);
	MmxMoveQwordVariableToReg(x86_MM0, &RSP_Vect[RSPOpC.rd].UHW[0], Reg);
	sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.rd);
	MmxMoveQwordVariableToReg(x86_MM1, &RSP_Vect[RSPOpC.rd].UHW[4], Reg);

	if ((RSPOpC.rs & 0xF) < 2) {
		sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.rt);
		MmxMoveQwordVariableToReg(x86_MM4, &RSP_Vect[RSPOpC.rt].UHW[0], Reg);
		sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.rt);
		MmxMoveQwordVariableToReg(x86_MM5, &RSP_Vect[RSPOpC.rt].UHW[4], Reg);

		/* Copy the signed portion */
		MmxMoveRegToReg(x86_MM2, x86_MM0);
		MmxMoveRegToReg(x86_MM3, x86_MM1);

		/* high((u16)a * b) */
		MmxPmulhuwRegToReg(x86_MM0, x86_MM4);
		MmxPmulhuwRegToReg(x86_MM1, x86_MM5);

		/* low((a >> 15) * b) */
		MmxPsrawImmed(x86_MM2, 15);
		MmxPsrawImmed(x86_MM3, 15);
		MmxPmullwRegToReg(x86_MM2, x86_MM4);
		MmxPmullwRegToReg(x86_MM3, x86_MM5);
	} else if ((RSPOpC.rs & 0xF) >= 8) {
		RSP_Element2Mmx(x86_MM4);

		/* Copy the signed portion */
		MmxMoveRegToReg(x86_MM2, x86_MM0);
		MmxMoveRegToReg(x86_MM3, x86_MM1);

		/* high((u16)a * b) */
		MmxPmulhuwRegToReg(x86_MM0, x86_MM4);
		MmxPmulhuwRegToReg(x86_MM1, x86_MM4);

		/* low((a >> 15) * b) */
		MmxPsrawImmed(x86_MM2, 15);
		MmxPsrawImmed(x86_MM3, 15);
		MmxPmullwRegToReg(x86_MM2, x86_MM4);
		MmxPmullwRegToReg(x86_MM3, x86_MM4);
	} else {
		RSP_MultiElement2Mmx(x86_MM4, x86_MM5);

		/* Copy the signed portion */
		MmxMoveRegToReg(x86_MM2, x86_MM0);
		MmxMoveRegToReg(x86_MM3, x86_MM1);

		/* high((u16)a * b) */
		MmxPmulhuwRegToReg(x86_MM0, x86_MM4);
		MmxPmulhuwRegToReg(x86_MM1, x86_MM5);

		/* low((a >> 15) * b) */
		MmxPsrawImmed(x86_MM2, 15);
		MmxPsrawImmed(x86_MM3, 15);
		MmxPmullwRegToReg(x86_MM2, x86_MM4);
		MmxPmullwRegToReg(x86_MM3, x86_MM5);
	}

	/* Add them up */
	MmxPaddwRegToReg(x86_MM0, x86_MM2);
	MmxPaddwRegToReg(x86_MM1, x86_MM3);

	sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.sa);
	MmxMoveQwordRegToVariable(x86_MM0, &RSP_Vect[RSPOpC.sa].UHW[0], Reg);
	sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.sa);
	MmxMoveQwordRegToVariable(x86_MM1, &RSP_Vect[RSPOpC.sa].UHW[4], Reg);

	if (IsNextInstructionMmx(CompilePC) == FALSE)
		MmxEmptyMultimediaState();

	return TRUE;
}

void Compile_Vector_VMUDM ( void ) {
	char Reg[256];
	int count, el, del;

	BOOL bOptimize = ((RSPOpC.rs & 0x0f) >= 8) ? TRUE : FALSE;
	BOOL bWriteToDest = WriteToVectorDest(RSPOpC.sa, CompilePC);
	BOOL bWriteToAccum = WriteToAccum(EntireAccum, CompilePC);

	#ifndef CompileVmudm
	Cheat_r4300iOpcode(RSP_Vector_VMUDM,"RSP_Vector_VMUDM"); return;
	#endif

	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));

	if (bWriteToAccum == FALSE) {
		if (TRUE == Compile_Vector_VMUDM_MMX())
			return;
	}

	if (bOptimize == TRUE) {
		del = (RSPOpC.rs & 0x07) ^ 7;
		sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del);
		MoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX);
	}

	Push(x86_EBP);
	sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.rd);
	MoveOffsetToX86reg((DWORD)&RSP_Vect[RSPOpC.rd].HW[0], Reg, x86_EBP);

	if (bWriteToDest) {
		sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.sa);
		MoveOffsetToX86reg((DWORD)&RSP_Vect[RSPOpC.sa].HW[0], Reg, x86_ECX);
	} else if (!bOptimize) {
		sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.rt);
		MoveOffsetToX86reg((DWORD)&RSP_Vect[RSPOpC.rt].HW[0], Reg, x86_ECX);
	}

	for (count = 0; count < 8; count++) {
		CPU_Message("     Iteration: %i", count);
		el = Indx[RSPOpC.rs].B[count];
		del = EleSpec[RSPOpC.rs].B[el];
		
		/*sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rd, el);
		MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].HW[el], Reg, x86_EAX);*/
		MoveSxX86RegPtrDispToX86RegHalf(x86_EBP, (BYTE)(el * 2), x86_EAX);

		if (bOptimize == FALSE) {
			if (bWriteToDest == TRUE) {
				sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del);
				MoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX);
			} else {
				MoveZxX86RegPtrDispToX86RegHalf(x86_ECX, (BYTE)(del * 2), x86_EBX);
			}
		}

		imulX86reg(x86_EBX);

		if (bWriteToAccum == FALSE && bWriteToDest == TRUE) {
			ShiftRightUnsignImmed(x86_EAX, 16);
			/*sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.sa, el);
			MoveX86regHalfToVariable(x86_EAX, &RSP_Vect[RSPOpC.sa].HW[el], Reg);*/
			MoveX86regHalfToX86regPointerDisp(x86_EAX, x86_ECX, (BYTE)(el * 2));
		} else {
			MoveX86RegToX86Reg(x86_EAX, x86_EDX);
			ShiftRightSignImmed(x86_EDX, 16);
			ShiftLeftSignImmed(x86_EAX, 16);

			if (bWriteToAccum == TRUE) {
				sprintf(Reg, "RSP_ACCUM[%i].UW[0]", el);
				MoveX86regToVariable(x86_EAX, &RSP_ACCUM[el].UW[0], Reg);
				sprintf(Reg, "RSP_ACCUM[%i].UW[1]", el);
				MoveX86regToVariable(x86_EDX ,&RSP_ACCUM[el].UW[1], Reg);
			}
			if (bWriteToDest == TRUE) {
				/*sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.sa, el);
				MoveX86regHalfToVariable(x86_EDX, &RSP_Vect[RSPOpC.sa].HW[el], Reg);*/
				MoveX86regHalfToX86regPointerDisp(x86_EDX, x86_ECX, (BYTE)(el * 2));
			}
		}
	}

	Pop(x86_EBP);
}

BOOL Compile_Vector_VMUDN_MMX ( void ) {
	char Reg[256];

	/* Do our MMX checks here */
	if (IsMmxEnabled == FALSE)
		return FALSE;
	if ((RSPOpC.rs & 0x0f) >= 2 && (RSPOpC.rs & 0x0f) <= 7 && IsMmx2Enabled == FALSE)
		return FALSE;

	sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.rd);
	MmxMoveQwordVariableToReg(x86_MM0, &RSP_Vect[RSPOpC.rd].UHW[0], Reg);
	sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.rd);
	MmxMoveQwordVariableToReg(x86_MM1, &RSP_Vect[RSPOpC.rd].UHW[4], Reg);

	if ((RSPOpC.rs & 0xF) < 2) {
		sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.rt);
		MmxPmullwVariableToReg(x86_MM0, &RSP_Vect[RSPOpC.rt].UHW[0], Reg);
		sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.rt);
		MmxPmullwVariableToReg(x86_MM1, &RSP_Vect[RSPOpC.rt].UHW[4], Reg);
	} else if ((RSPOpC.rs & 0xF) >= 8) {
		RSP_Element2Mmx(x86_MM2);
		MmxPmullwRegToReg(x86_MM0, x86_MM2);
		MmxPmullwRegToReg(x86_MM1, x86_MM2);
	} else {
		RSP_MultiElement2Mmx(x86_MM2, x86_MM3);
		MmxPmullwRegToReg(x86_MM0, x86_MM2);
		MmxPmullwRegToReg(x86_MM1, x86_MM3);
	}

	sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.sa);
	MmxMoveQwordRegToVariable(x86_MM0, &RSP_Vect[RSPOpC.sa].UHW[0], Reg);
	sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.sa);
	MmxMoveQwordRegToVariable(x86_MM1, &RSP_Vect[RSPOpC.sa].UHW[4], Reg);

	if (IsNextInstructionMmx(CompilePC) == FALSE)
		MmxEmptyMultimediaState();

	return TRUE;
}

void Compile_Vector_VMUDN ( void ) {
	char Reg[256];
	int count, el, del;
	
	BOOL bOptimize = ((RSPOpC.rs & 0x0f) >= 8) ? TRUE : FALSE;
	BOOL bWriteToDest = WriteToVectorDest(RSPOpC.sa, CompilePC);
	BOOL bWriteToAccum = WriteToAccum(EntireAccum, CompilePC);

	#ifndef CompileVmudn
	Cheat_r4300iOpcode(RSP_Vector_VMUDN,"RSP_Vector_VMUDN"); return;
	#endif

	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));

	if (bWriteToAccum == FALSE) {
		if (TRUE == Compile_Vector_VMUDN_MMX())
			return;
	}

	if (bOptimize == TRUE) {
		del = (RSPOpC.rs & 0x07) ^ 7;
		sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del);
		MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX);
	}

	Push(x86_EBP);
	sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.rd);
	MoveOffsetToX86reg((DWORD)&RSP_Vect[RSPOpC.rd].HW[0], Reg, x86_EBP);

	for (count = 0; count < 8; count++) {
		CPU_Message("     Iteration: %i", count);
		el = Indx[RSPOpC.rs].B[count];
		del = EleSpec[RSPOpC.rs].B[el];

		/*sprintf(Reg, "RSP_Vect[%i].UHW[%i]", RSPOpC.rd, el);
		MoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].UHW[el], Reg, x86_EAX);*/
		MoveZxX86RegPtrDispToX86RegHalf(x86_EBP, (BYTE)(el * 2), x86_EAX);

		if (bOptimize == FALSE) {
			sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del);
			MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX);
		}

		imulX86reg(x86_EBX);

		if (bWriteToDest == TRUE) {
			sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.sa, el);
			MoveX86regHalfToVariable(x86_EAX, &RSP_Vect[RSPOpC.sa].HW[el], Reg);
		}

		if (bWriteToAccum == TRUE) {
			MoveX86RegToX86Reg(x86_EAX, x86_EDX);
			ShiftRightSignImmed(x86_EDX, 16);
			ShiftLeftSignImmed(x86_EAX, 16);
			sprintf(Reg, "RSP_ACCUM[%i].UW[0]", el);
			MoveX86regToVariable(x86_EAX, &RSP_ACCUM[el].UW[0], Reg);
			sprintf(Reg, "RSP_ACCUM[%i].UW[1]", el);
			MoveX86regToVariable(x86_EDX, &RSP_ACCUM[el].UW[1], Reg);
		}
	}
	Pop(x86_EBP);
}

BOOL Compile_Vector_VMUDH_MMX ( void ) {
	char Reg[256];

	/* Do our MMX checks here */
	if (IsMmxEnabled == FALSE)
		return FALSE;
	if ((RSPOpC.rs & 0x0f) >= 2 && (RSPOpC.rs & 0x0f) <= 7 && IsMmx2Enabled == FALSE)
		return FALSE;

	sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.rd);
	MmxMoveQwordVariableToReg(x86_MM0, &RSP_Vect[RSPOpC.rd].HW[0], Reg);
	sprintf(Reg, "RSP_Vect[%i].HW[4]", RSPOpC.rd);
	MmxMoveQwordVariableToReg(x86_MM1, &RSP_Vect[RSPOpC.rd].HW[4], Reg);

	/* Registers 4 & 5 are high */
	MmxMoveRegToReg(x86_MM4, x86_MM0);
	MmxMoveRegToReg(x86_MM5, x86_MM1);

	if ((RSPOpC.rs & 0x0f) < 2) {
		if (RSPOpC.rd == RSPOpC.rt){
			MmxPmullwRegToReg(x86_MM0, x86_MM0);
			MmxPmulhwRegToReg(x86_MM4, x86_MM4);
			MmxPmullwRegToReg(x86_MM1, x86_MM1);
			MmxPmulhwRegToReg(x86_MM5, x86_MM5);
		} else {
			sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.rt);
			MmxMoveQwordVariableToReg(x86_MM2, &RSP_Vect[RSPOpC.rt].HW[0], Reg);
			sprintf(Reg, "RSP_Vect[%i].HW[4]", RSPOpC.rt);
			MmxMoveQwordVariableToReg(x86_MM3, &RSP_Vect[RSPOpC.rt].HW[4], Reg);

			MmxPmullwRegToReg(x86_MM0, x86_MM2);
			MmxPmulhwRegToReg(x86_MM4, x86_MM2);
			MmxPmullwRegToReg(x86_MM1, x86_MM3);
			MmxPmulhwRegToReg(x86_MM5, x86_MM3);
		}
	} else if ((RSPOpC.rs & 0x0f) >= 8) {
		RSP_Element2Mmx(x86_MM2);

		MmxPmullwRegToReg(x86_MM0, x86_MM2);
		MmxPmulhwRegToReg(x86_MM4, x86_MM2);
		MmxPmullwRegToReg(x86_MM1, x86_MM2);
		MmxPmulhwRegToReg(x86_MM5, x86_MM2);
	} else {
		RSP_MultiElement2Mmx(x86_MM2, x86_MM3);

		MmxPmullwRegToReg(x86_MM0, x86_MM2);
		MmxPmulhwRegToReg(x86_MM4, x86_MM2);
		MmxPmullwRegToReg(x86_MM1, x86_MM3);
		MmxPmulhwRegToReg(x86_MM5, x86_MM3);
	}

	/* 0 & 1 are low, 4 & 5 are high */
	MmxMoveRegToReg(x86_MM6, x86_MM0);
	MmxMoveRegToReg(x86_MM7, x86_MM1);

	MmxUnpackLowWord(x86_MM0, x86_MM4);
	MmxUnpackHighWord(x86_MM6, x86_MM4);
	MmxUnpackLowWord(x86_MM1, x86_MM5);		
	MmxUnpackHighWord(x86_MM7, x86_MM5);

	/* Integrate copies */
	MmxPackSignedDwords(x86_MM0, x86_MM6);
	MmxPackSignedDwords(x86_MM1, x86_MM7);
	
	sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.sa);
	MmxMoveQwordRegToVariable(x86_MM0, &RSP_Vect[RSPOpC.sa].HW[0], Reg);
	sprintf(Reg, "RSP_Vect[%i].HW[4]", RSPOpC.sa);
	MmxMoveQwordRegToVariable(x86_MM1, &RSP_Vect[RSPOpC.sa].HW[4], Reg);

	if (IsNextInstructionMmx(CompilePC) == FALSE)
		MmxEmptyMultimediaState();

	return TRUE;
}

void Compile_Vector_VMUDH ( void ) {
	char Reg[256];
	int count, el, del;

	BOOL bOptimize = ((RSPOpC.rs & 0x0f) >= 8) ? TRUE : FALSE;
	BOOL bWriteToDest = WriteToVectorDest(RSPOpC.sa, CompilePC);
	BOOL bWriteToAccum = WriteToAccum(EntireAccum, CompilePC);

	#ifndef CompileVmudh
	Cheat_r4300iOpcode(RSP_Vector_VMUDH,"RSP_Vector_VMUDH"); return;
	#endif

	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));

	if (bWriteToAccum == FALSE) {
		if (TRUE == Compile_Vector_VMUDH_MMX())
			return;
	}

	if (bWriteToDest == FALSE && bOptimize == TRUE) {
		Push(x86_EBP);
		sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.rd);

		/* Load source */
		del = (RSPOpC.rs & 0x07) ^ 7;
		sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del);
		MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX);

		/* 
		 * Pipe lined segment 0
		 */
		
		sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.rd);
		MoveOffsetToX86reg((DWORD)&RSP_Vect[RSPOpC.rd].HW[0], Reg, x86_EBP);

		MoveSxX86RegPtrDispToX86RegHalf(x86_EBP, 0, x86_EAX);
		MoveSxX86RegPtrDispToX86RegHalf(x86_EBP, 2, x86_ECX);
		MoveSxX86RegPtrDispToX86RegHalf(x86_EBP, 4, x86_EDI);
		MoveSxX86RegPtrDispToX86RegHalf(x86_EBP, 6, x86_ESI);

		ImulX86RegToX86Reg(x86_EAX, x86_EBX);
		ImulX86RegToX86Reg(x86_ECX, x86_EBX);
		ImulX86RegToX86Reg(x86_EDI, x86_EBX);
		ImulX86RegToX86Reg(x86_ESI, x86_EBX);
		XorX86RegToX86Reg(x86_EDX, x86_EDX);

		MoveOffsetToX86reg((DWORD)&RSP_ACCUM[0].W[0], "RSP_ACCUM[0].W[0]", x86_EBP);

		MoveX86RegToX86regPointerDisp(x86_EDX, x86_EBP, 0);
		MoveX86RegToX86regPointerDisp(x86_EAX, x86_EBP, 4);
		MoveX86RegToX86regPointerDisp(x86_EDX, x86_EBP, 8);
		MoveX86RegToX86regPointerDisp(x86_ECX, x86_EBP, 12);
		MoveX86RegToX86regPointerDisp(x86_EDX, x86_EBP, 16);
		MoveX86RegToX86regPointerDisp(x86_EDI, x86_EBP, 20);
		MoveX86RegToX86regPointerDisp(x86_EDX, x86_EBP, 24);
		MoveX86RegToX86regPointerDisp(x86_ESI, x86_EBP, 28);

		/* 
		 * Pipe lined segment 1
		 */

		sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.rd);
		MoveOffsetToX86reg((DWORD)&RSP_Vect[RSPOpC.rd].HW[0], Reg, x86_EBP);

		MoveSxX86RegPtrDispToX86RegHalf(x86_EBP,  8, x86_EAX);
		MoveSxX86RegPtrDispToX86RegHalf(x86_EBP, 10, x86_ECX);
		MoveSxX86RegPtrDispToX86RegHalf(x86_EBP, 12, x86_EDI);
		MoveSxX86RegPtrDispToX86RegHalf(x86_EBP, 14, x86_ESI);

		ImulX86RegToX86Reg(x86_EAX, x86_EBX);
		ImulX86RegToX86Reg(x86_ECX, x86_EBX);
		ImulX86RegToX86Reg(x86_EDI, x86_EBX);
		ImulX86RegToX86Reg(x86_ESI, x86_EBX);
		XorX86RegToX86Reg(x86_EDX, x86_EDX);

		MoveOffsetToX86reg((DWORD)&RSP_ACCUM[0].W[0], "RSP_ACCUM[0].W[0]", x86_EBP);

		MoveX86RegToX86regPointerDisp(x86_EDX, x86_EBP, 32);
		MoveX86RegToX86regPointerDisp(x86_EAX, x86_EBP, 36);
		MoveX86RegToX86regPointerDisp(x86_EDX, x86_EBP, 40);
		MoveX86RegToX86regPointerDisp(x86_ECX, x86_EBP, 44);
		MoveX86RegToX86regPointerDisp(x86_EDX, x86_EBP, 48);
		MoveX86RegToX86regPointerDisp(x86_EDI, x86_EBP, 52);
		MoveX86RegToX86regPointerDisp(x86_EDX, x86_EBP, 56);
		MoveX86RegToX86regPointerDisp(x86_ESI, x86_EBP, 60);

		Pop(x86_EBP);
	} else {
		if (bOptimize == TRUE) {
			del = (RSPOpC.rs & 0x07) ^ 7;
			sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del);
			MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX);
		}
		if (bWriteToDest == TRUE) {
			/*
			 * Prepare for conditional moves
			 */
			MoveConstToX86reg(0x00007fff, x86_ESI);
			MoveConstToX86reg(0xFFFF8000, x86_EDI);
		}

		for (count = 0; count < 8; count++) {
			CPU_Message("     Iteration: %i", count);
			el = Indx[RSPOpC.rs].B[count];
			del = EleSpec[RSPOpC.rs].B[el];
		
			sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rd, el);
			MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].HW[el], Reg, x86_EAX);

			if (bOptimize == FALSE) {
				sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del);
				MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX);
			}
			imulX86reg(x86_EBX);
			
			if (bWriteToAccum == TRUE) {
				MoveX86regToVariable(x86_EAX, &RSP_ACCUM[el].W[1], "RSP_ACCUM[el].W[1]");
				MoveConstToVariable(0, &RSP_ACCUM[el].W[0], "RSP_ACCUM[el].W[0]");
			}
			
			if (bWriteToDest == TRUE) {
				CompX86RegToX86Reg(x86_EAX, x86_ESI);
				CondMoveGreater(x86_EAX, x86_ESI);
				CompX86RegToX86Reg(x86_EAX, x86_EDI);
				CondMoveLess(x86_EAX, x86_EDI);

				sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.sa, el);
				MoveX86regHalfToVariable(x86_EAX, &RSP_Vect[RSPOpC.sa].HW[el], Reg);
			}
		}
	}
}

void Compile_Vector_VMACF ( void ) {
	char Reg[256];
	int count, el, del;

	BOOL bOptimize = ((RSPOpC.rs & 0x0f) >= 8) ? TRUE : FALSE;
	BOOL bWriteToDest = WriteToVectorDest(RSPOpC.sa, CompilePC);

	#ifndef CompileVmacf
	Cheat_r4300iOpcode(RSP_Vector_VMACF,"RSP_Vector_VMACF"); return;
	#endif

	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));

	if (bWriteToDest == TRUE) {
		/*
		 * Prepare for conditional moves
		 */
		MoveConstToX86reg(0x00007fff, x86_ESI);
		MoveConstToX86reg(0xFFFF8000, x86_EDI);
	}
	if (bOptimize == TRUE) {
		del = (RSPOpC.rs & 0x07) ^ 7;
		sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del);
		MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX);
	}

	for (count = 0; count < 8; count++) {
		el = Indx[RSPOpC.rs].B[count];
		del = EleSpec[RSPOpC.rs].B[el];

		CPU_Message("     Iteration: %i", count);

		sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rd, el);
		MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].HW[el], Reg, x86_EAX);

		if (bOptimize == FALSE) {
			sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del);
			MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX);
		}

		imulX86reg(x86_EBX);

		MoveX86RegToX86Reg(x86_EAX, x86_EDX);
		ShiftRightSignImmed(x86_EDX, 15);
		ShiftLeftSignImmed(x86_EAX, 17);

		AddX86regToVariable(x86_EAX, &RSP_ACCUM[el].W[0], "RSP_ACCUM[el].W[0]");
		AdcX86regToVariable(x86_EDX, &RSP_ACCUM[el].W[1], "RSP_ACCUM[el].W[1]");

		if (bWriteToDest == TRUE) {
			MoveVariableToX86reg(&RSP_ACCUM[el].W[1], "RSP_ACCUM[el].W[1]", x86_EAX);

			CompX86RegToX86Reg(x86_EAX, x86_ESI);
			CondMoveGreater(x86_EAX, x86_ESI);
			CompX86RegToX86Reg(x86_EAX, x86_EDI);
			CondMoveLess(x86_EAX, x86_EDI);

			sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.sa, el);
			MoveX86regHalfToVariable(x86_EAX, &RSP_Vect[RSPOpC.sa].HW[el], Reg);
		}
	}
}

void Compile_Vector_VMACU ( void ) {
	Cheat_r4300iOpcode(RSP_Vector_VMACU,"RSP_Vector_VMACU");
}

void Compile_Vector_VMACQ ( void ) {
	Cheat_r4300iOpcode(RSP_Vector_VMACQ,"RSP_Vector_VMACQ");
}

void Compile_Vector_VMADL ( void ) {
	char Reg[256];
	int count, el, del;

	BOOL bOptimize = ((RSPOpC.rs & 0x0f) >= 8) ? TRUE : FALSE;
	BOOL bWriteToDest = WriteToVectorDest(RSPOpC.sa, CompilePC);

	#ifndef CompileVmadl
	Cheat_r4300iOpcode(RSP_Vector_VMADL,"RSP_Vector_VMADL"); return;
	#endif

	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));

	if (bOptimize == TRUE) {
		del = (RSPOpC.rs & 0x07) ^ 7;
		sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del);
		MoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX);
	}

	if (bWriteToDest == TRUE) {
		/*
		 * Prepare for conditional moves
		 */
		MoveConstToX86reg(0x00007FFF, x86_ESI);
		MoveConstToX86reg(0xFFFF8000, x86_EDI);

		Push(x86_EBP);
		MoveConstToX86reg(0x0000FFFF, x86_EBP);
	}

	for (count = 0; count < 8; count++) {
		CPU_Message("     Iteration: %i", count);
		el = Indx[RSPOpC.rs].B[count];
		del = EleSpec[RSPOpC.rs].B[el];

		sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rd, el);
		MoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].HW[el], Reg, x86_EAX);

		if (bOptimize == FALSE) {
			sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del);
			MoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX);
		}

		imulX86reg(x86_EBX);
		sprintf(Reg, "RSP_ACCUM[%i].W[0]", el);
		AddX86regToVariable(x86_EAX, &RSP_ACCUM[el].W[0], Reg);
		sprintf(Reg, "RSP_ACCUM[%i].W[1]", el);
		AdcConstToVariable(&RSP_ACCUM[el].W[1], Reg, 0);

		if (bWriteToDest != FALSE) {
			XorX86RegToX86Reg(x86_EDX, x86_EDX);
			MoveVariableToX86reg(&RSP_ACCUM[el].W[1], "RSP_ACCUM[el].W[1]", x86_EAX);
			MoveZxVariableToX86regHalf(&RSP_ACCUM[el].HW[1], "RSP_ACCUM[el].hW[1]", x86_ECX);

			CompX86RegToX86Reg(x86_EAX, x86_ESI);
			CondMoveGreater(x86_ECX, x86_EBP);
			CompX86RegToX86Reg(x86_EAX, x86_EDI);
			CondMoveLess(x86_ECX, x86_EDX);

			sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.sa, el);
			MoveX86regHalfToVariable(x86_ECX, &RSP_Vect[RSPOpC.sa].HW[el], Reg);
		}
	}

	if (bWriteToDest == TRUE) {
		Pop(x86_EBP);
	}
}

void Compile_Vector_VMADM ( void ) {
	char Reg[256];
	int count, el, del;

	BOOL bOptimize = ((RSPOpC.rs & 0x0f) >= 8) ? TRUE : FALSE;
	BOOL bWriteToDest = WriteToVectorDest(RSPOpC.sa, CompilePC);

	#ifndef CompileVmadm
	Cheat_r4300iOpcode(RSP_Vector_VMADM,"RSP_Vector_VMADM"); return;
	#endif

	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));

	if (bOptimize == TRUE) {
		del = (RSPOpC.rs & 0x07) ^ 7;
		sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del);
		MoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX);
	}
	if (bWriteToDest == TRUE) {
		/*
		 * Prepare for conditional moves
		 */
		MoveConstToX86reg(0x00007fff, x86_ESI);
		MoveConstToX86reg(0xFFFF8000, x86_EDI);
	}

	Push(x86_EBP);
	sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.rd);
	MoveOffsetToX86reg((DWORD)&RSP_Vect[RSPOpC.rd].HW[0], Reg, x86_EBP);

	if (bWriteToDest) {
		sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.sa);
		MoveOffsetToX86reg((DWORD)&RSP_Vect[RSPOpC.sa].HW[0], Reg, x86_ECX);
	} else if (!bOptimize) {
		sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.rt);
		MoveOffsetToX86reg((DWORD)&RSP_Vect[RSPOpC.rt].HW[0], Reg, x86_ECX);
	}

	for (count = 0; count < 8; count++) {
		CPU_Message("     Iteration: %i", count);
		el = Indx[RSPOpC.rs].B[count];
		del = EleSpec[RSPOpC.rs].B[el];
		
		/*sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rd, el);
		MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].HW[el], Reg, x86_EAX);*/
		MoveSxX86RegPtrDispToX86RegHalf(x86_EBP, (BYTE)(el * 2), x86_EAX);

		if (bOptimize == FALSE) {
			if (bWriteToDest == TRUE) {
				sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del);
				MoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], "RSP_Vect[RSPOpC.rt].HW[del]", x86_EBX);
			} else {
				MoveZxX86RegPtrDispToX86RegHalf(x86_ECX, (BYTE)(del * 2), x86_EBX);
			}
		}

		imulX86reg(x86_EBX);

		MoveX86RegToX86Reg(x86_EAX, x86_EDX);
		ShiftRightSignImmed(x86_EDX, 16);
		ShiftLeftSignImmed(x86_EAX, 16);
		AddX86regToVariable(x86_EAX, &RSP_ACCUM[el].W[0], "RSP_ACCUM[el].W[0]");
		AdcX86regToVariable(x86_EDX, &RSP_ACCUM[el].W[1], "RSP_ACCUM[el].W[1]");

		if (bWriteToDest == TRUE) {
			/* For compare */
			sprintf(Reg, "RSP_ACCUM[%i].W[1]", el);
			MoveVariableToX86reg(&RSP_ACCUM[el].W[1], "RSP_ACCUM[el].W[1]", x86_EAX);

			CompX86RegToX86Reg(x86_EAX, x86_ESI);
			CondMoveGreater(x86_EAX, x86_ESI);
			CompX86RegToX86Reg(x86_EAX, x86_EDI);
			CondMoveLess(x86_EAX, x86_EDI);

			/*sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.sa, el);
			MoveX86regHalfToVariable(x86_EAX, &RSP_Vect[RSPOpC.sa].HW[el], Reg);*/
			MoveX86regHalfToX86regPointerDisp(x86_EAX, x86_ECX, (BYTE)(el * 2));
		}
	}

	Pop(x86_EBP);
}

void Compile_Vector_VMADN ( void ) {
	char Reg[256];
	int count, el, del;
	
	BOOL bOptimize = ((RSPOpC.rs & 0x0f) >= 8) ? TRUE : FALSE;
	BOOL bWriteToDest = WriteToVectorDest(RSPOpC.sa, CompilePC);

	#ifndef CompileVmadn
	Cheat_r4300iOpcode(RSP_Vector_VMADN,"RSP_Vector_VMADN"); return;
	#endif
	
	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));

	if (bOptimize == TRUE) {
		del = (RSPOpC.rs & 0x07) ^ 7;
		sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del);
		MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX);
	} 
	if (bWriteToDest == TRUE) {
		/*
		 * Prepare for conditional moves
		 */
		MoveConstToX86reg(0x0000ffff, x86_ESI);
		MoveConstToX86reg(0x00000000, x86_EDI);
	}

	Push(x86_EBP);
	sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.rd);
	MoveOffsetToX86reg((DWORD)&RSP_Vect[RSPOpC.rd].HW[0], Reg, x86_EBP);

	for (count = 0; count < 8; count++) {
		CPU_Message("     Iteration: %i", count);
		el = Indx[RSPOpC.rs].B[count];
		del = EleSpec[RSPOpC.rs].B[el];

		/*sprintf(Reg, "RSP_Vect[%i].UHW[%i]", RSPOpC.rd, el);
		MoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].UHW[el], Reg, x86_EAX);*/
		MoveZxX86RegPtrDispToX86RegHalf(x86_EBP, (BYTE)(el * 2), x86_EAX);

		if (bOptimize == FALSE) {
			sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del);
			MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX);
		}

		imulX86reg(x86_EBX);

		MoveX86RegToX86Reg(x86_EAX, x86_EDX);
		ShiftRightSignImmed(x86_EDX, 16);
		ShiftLeftSignImmed(x86_EAX, 16);
		AddX86regToVariable(x86_EAX, &RSP_ACCUM[el].W[0], "RSP_ACCUM[el].W[0]");
		AdcX86regToVariable(x86_EDX, &RSP_ACCUM[el].W[1], "RSP_ACCUM[el].W[1]");

		if (bWriteToDest == TRUE) {
			/* For compare */
			sprintf(Reg, "RSP_ACCUM[%i].W[1]", el);
			MoveVariableToX86reg(&RSP_ACCUM[el].W[1], Reg, x86_EAX);

			/* For vector */
			sprintf(Reg, "RSP_ACCUM[%i].HW[1]", el);
			MoveVariableToX86regHalf(&RSP_ACCUM[el].HW[1], Reg, x86_ECX);

			/* Weird eh */
			CompConstToX86reg(x86_EAX, 0x7fff);
			CondMoveGreater(x86_ECX, x86_ESI);
			CompConstToX86reg(x86_EAX, (DWORD)(-0x8000));
			CondMoveLess(x86_ECX, x86_EDI);

			sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.sa, el);
			MoveX86regHalfToVariable(x86_ECX, &RSP_Vect[RSPOpC.sa].HW[el], Reg);
		}
	}
	Pop(x86_EBP);
}

void Compile_Vector_VMADH ( void ) {
	char Reg[256];
	int count, el, del;

	BOOL bOptimize = ((RSPOpC.rs & 0x0f) >= 8) ? TRUE : FALSE;
	BOOL bWriteToDest = WriteToVectorDest(RSPOpC.sa, CompilePC);

	#ifndef CompileVmadh
	Cheat_r4300iOpcode(RSP_Vector_VMADH,"RSP_Vector_VMADH"); return;
	#endif

	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));

	if (bOptimize == TRUE) {
		del = (RSPOpC.rs & 0x07) ^ 7;
		sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del);
		MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX);
	} 
	
	if (bWriteToDest == TRUE) {
		/*
		 * Prepare for conditional moves
		 */
		MoveConstToX86reg(0x00007fff, x86_ESI);
		MoveConstToX86reg(0xFFFF8000, x86_EDI);
	}

	if (bWriteToDest == FALSE && bOptimize == TRUE) {
		Push(x86_EBP);
		sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.rd);
		MoveOffsetToX86reg((DWORD)&RSP_Vect[RSPOpC.rd].HW[0], Reg, x86_EBP);

		/* 
		 * Pipe lined segment 0
		 */
		MoveSxX86RegPtrDispToX86RegHalf(x86_EBP, 0, x86_EAX);
		MoveSxX86RegPtrDispToX86RegHalf(x86_EBP, 2, x86_ECX);
		MoveSxX86RegPtrDispToX86RegHalf(x86_EBP, 4, x86_EDI);
		MoveSxX86RegPtrDispToX86RegHalf(x86_EBP, 6, x86_ESI);

		ImulX86RegToX86Reg(x86_EAX, x86_EBX);
		ImulX86RegToX86Reg(x86_ECX, x86_EBX);
		ImulX86RegToX86Reg(x86_EDI, x86_EBX);
		ImulX86RegToX86Reg(x86_ESI, x86_EBX);

		sprintf(Reg, "RSP_ACCUM[%i].W[1]", 0);
		AddX86regToVariable(x86_EAX, &RSP_ACCUM[0].W[1], Reg);
		sprintf(Reg, "RSP_ACCUM[%i].W[1]", 1);
		AddX86regToVariable(x86_ECX, &RSP_ACCUM[1].W[1], Reg);
		sprintf(Reg, "RSP_ACCUM[%i].W[1]", 2);
		AddX86regToVariable(x86_EDI, &RSP_ACCUM[2].W[1], Reg);
		sprintf(Reg, "RSP_ACCUM[%i].W[1]", 3);
		AddX86regToVariable(x86_ESI, &RSP_ACCUM[3].W[1], Reg);

		/* 
		 * Pipe lined segment 1
		 */
		MoveSxX86RegPtrDispToX86RegHalf(x86_EBP,  8, x86_EAX);
		MoveSxX86RegPtrDispToX86RegHalf(x86_EBP, 10, x86_ECX);
		MoveSxX86RegPtrDispToX86RegHalf(x86_EBP, 12, x86_EDI);
		MoveSxX86RegPtrDispToX86RegHalf(x86_EBP, 14, x86_ESI);

		ImulX86RegToX86Reg(x86_EAX, x86_EBX);
		ImulX86RegToX86Reg(x86_ECX, x86_EBX);
		ImulX86RegToX86Reg(x86_EDI, x86_EBX);
		ImulX86RegToX86Reg(x86_ESI, x86_EBX);

		sprintf(Reg, "RSP_ACCUM[%i].W[1]", 4);
		AddX86regToVariable(x86_EAX, &RSP_ACCUM[4].W[1], Reg);
		sprintf(Reg, "RSP_ACCUM[%i].W[1]", 5);
		AddX86regToVariable(x86_ECX, &RSP_ACCUM[5].W[1], Reg);
		sprintf(Reg, "RSP_ACCUM[%i].W[1]", 6);
		AddX86regToVariable(x86_EDI, &RSP_ACCUM[6].W[1], Reg);
		sprintf(Reg, "RSP_ACCUM[%i].W[1]", 7);
		AddX86regToVariable(x86_ESI, &RSP_ACCUM[7].W[1], Reg);

		Pop(x86_EBP);
	} else {
		Push(x86_EBP);
		sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.rd);
		MoveOffsetToX86reg((DWORD)&RSP_Vect[RSPOpC.rd].HW[0], Reg, x86_EBP);

		if (bWriteToDest) {
			sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.sa);
			MoveOffsetToX86reg((DWORD)&RSP_Vect[RSPOpC.sa].HW[0], Reg, x86_ECX);
		} else if (!bOptimize) {
			sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.rt);
			MoveOffsetToX86reg((DWORD)&RSP_Vect[RSPOpC.rt].HW[0], Reg, x86_ECX);
		}

		for (count = 0; count < 8; count++) {
			CPU_Message("     Iteration: %i", count);
			el = Indx[RSPOpC.rs].B[count];
			del = EleSpec[RSPOpC.rs].B[el];

			/*sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rd, el);
			MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].HW[el], Reg, x86_EAX);*/
			MoveSxX86RegPtrDispToX86RegHalf(x86_EBP, (BYTE)(el * 2), x86_EAX);

			if (bOptimize == FALSE) {
				if (bWriteToDest == TRUE) {
					sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del);
					MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX);
				} else {
					MoveSxX86RegPtrDispToX86RegHalf(x86_ECX, (BYTE)(del * 2), x86_EBX);
				}
			}

			imulX86reg(x86_EBX);
			sprintf(Reg, "RSP_ACCUM[%i].W[1]", el);
			AddX86regToVariable(x86_EAX, &RSP_ACCUM[el].W[1], Reg);

			if (bWriteToDest == TRUE) {
				MoveVariableToX86reg(&RSP_ACCUM[el].W[1], "RSP_ACCUM[el].W[1]", x86_EAX);

				CompX86RegToX86Reg(x86_EAX, x86_ESI);
				CondMoveGreater(x86_EAX, x86_ESI);
				CompX86RegToX86Reg(x86_EAX, x86_EDI);
				CondMoveLess(x86_EAX, x86_EDI);

				/*sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.sa, el);
				MoveX86regHalfToVariable(x86_EAX, &RSP_Vect[RSPOpC.sa].HW[el], Reg);*/
				MoveX86regHalfToX86regPointerDisp(x86_EAX, x86_ECX, (BYTE)(el * 2));
			}
		}
		Pop(x86_EBP);
	}
}

BOOL Compile_Vector_VADD_MMX ( void ) {
	char Reg[256];

	/* Do our MMX checks here */
	if (IsMmxEnabled == FALSE)
		return FALSE;
	if ((RSPOpC.rs & 0x0f) >= 2 && (RSPOpC.rs & 0x0f) <= 7 && IsMmx2Enabled == FALSE)
		return FALSE;

	sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.rd);
	MmxMoveQwordVariableToReg(x86_MM0, &RSP_Vect[RSPOpC.rd].UHW[0], Reg);
	sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.rd);
	MmxMoveQwordVariableToReg(x86_MM1, &RSP_Vect[RSPOpC.rd].UHW[4], Reg);

	if ((RSPOpC.rs & 15) >= 8) {
		RSP_Element2Mmx(x86_MM2);
		MmxPaddswRegToReg(x86_MM0, x86_MM2);
		MmxPaddswRegToReg(x86_MM1, x86_MM2);
	} else if ((RSPOpC.rs & 15) < 2) {
		if (RSPOpC.rd == RSPOpC.rt){
			MmxPaddswRegToReg(x86_MM0, x86_MM0);
			MmxPaddswRegToReg(x86_MM1, x86_MM1);
		} else{
			sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.rt);
			MmxPaddswVariableToReg(x86_MM0, &RSP_Vect[RSPOpC.rt].HW[0], Reg);
			sprintf(Reg, "RSP_Vect[%i].HW[4]", RSPOpC.rt);
			MmxPaddswVariableToReg(x86_MM1, &RSP_Vect[RSPOpC.rt].HW[4], Reg);
		}
	} else {
		RSP_MultiElement2Mmx(x86_MM2, x86_MM3);
		MmxPaddswRegToReg(x86_MM0, x86_MM2);
		MmxPaddswRegToReg(x86_MM1, x86_MM3);
	}

	sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.sa);
	MmxMoveQwordRegToVariable(x86_MM0, &RSP_Vect[RSPOpC.sa].UHW[0], Reg);
	sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.sa);
	MmxMoveQwordRegToVariable(x86_MM1, &RSP_Vect[RSPOpC.sa].UHW[4], Reg);
	
	if (IsNextInstructionMmx(CompilePC) != TRUE) {
		MmxEmptyMultimediaState();
	}

	return TRUE;
}

void Compile_Vector_VADD ( void ) {
	char Reg[256];
	int count, el, del;


	BOOL bWriteToDest = WriteToVectorDest(RSPOpC.sa, CompilePC);
	BOOL bElement = ((RSPOpC.rs & 0x0f) >= 8) ? TRUE : FALSE;
	BOOL bWriteToAccum = WriteToAccum(Low16BitAccum, CompilePC);
	BOOL bFlagUseage = UseRspFlags(CompilePC);

	#ifndef CompileVadd
	Cheat_r4300iOpcode(RSP_Vector_VADD,"RSP_Vector_VADD"); return;
	#endif

	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));

	if (bWriteToAccum == FALSE && bFlagUseage == FALSE) {
		if (TRUE == Compile_Vector_VADD_MMX())
			return;
	}

	if (bElement == TRUE) {
		del = (RSPOpC.rs & 0x07) ^ 7;
		sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del);
		MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX);
	}
	if (bWriteToDest == TRUE) {
		/*
		 * Prepare for conditional moves
		 */
		MoveConstToX86reg(0x00007fff, x86_ESI);
		MoveConstToX86reg(0xffff8000, x86_EDI);
	}
	
	/* Used for involking x86 carry flag */
	XorX86RegToX86Reg(x86_ECX, x86_ECX);
	Push(x86_EBP);
	MoveVariableToX86reg(&RSP_Flags[0].UW, "RSP_Flags[0].UW", x86_EBP);

	for (count = 0; count < 8; count++) {
		CPU_Message("     Iteration: %i", count);
		el = Indx[RSPOpC.rs].B[count];
		del = EleSpec[RSPOpC.rs].B[el];
	
		sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rd, el);
		MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].HW[el], Reg, x86_EAX);

		if (bElement == FALSE) {
			sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del);
			MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX);
		}
		
		MoveX86RegToX86Reg(x86_EBP, x86_EDX);
		AndConstToX86Reg(x86_EDX, 1 << (7 - el));
		CompX86RegToX86Reg(x86_ECX, x86_EDX);

		AdcX86RegToX86Reg(x86_EAX, x86_EBX);

		if (bWriteToAccum != FALSE) {
			sprintf(Reg, "RSP_ACCUM[%i].HW[1]", el);
			MoveX86regHalfToVariable(x86_EAX, &RSP_ACCUM[el].HW[1], Reg);
		}
		if (bWriteToDest != FALSE) {
			CompX86RegToX86Reg(x86_EAX, x86_ESI);
			CondMoveGreater(x86_EAX, x86_ESI);
			CompX86RegToX86Reg(x86_EAX, x86_EDI);
			CondMoveLess(x86_EAX, x86_EDI);

			sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.sa, el);
			MoveX86regHalfToVariable(x86_EAX, &RSP_Vect[RSPOpC.sa].HW[el], Reg);
		}
	}
	MoveConstToVariable(0, &RSP_Flags[0].UW, "RSP_Flags[0].UW");
	Pop(x86_EBP);
}

BOOL Compile_Vector_VSUB_MMX ( void ) {
	char Reg[256];

	/* Do our MMX checks here */
	if (IsMmxEnabled == FALSE)
		return FALSE;
	if ((RSPOpC.rs & 0x0f) >= 2 && (RSPOpC.rs & 0x0f) <= 7 && IsMmx2Enabled == FALSE)
		return FALSE;

	sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.rd);
	MmxMoveQwordVariableToReg(x86_MM0, &RSP_Vect[RSPOpC.rd].UHW[0], Reg);
	sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.rd);
	MmxMoveQwordVariableToReg(x86_MM1, &RSP_Vect[RSPOpC.rd].UHW[4], Reg);

	if ((RSPOpC.rs & 15) >= 8) {
		RSP_Element2Mmx(x86_MM2);
		MmxPsubswRegToReg(x86_MM0, x86_MM2);
		MmxPsubswRegToReg(x86_MM1, x86_MM2);
	} else if ((RSPOpC.rs & 15) < 2) {
		if (RSPOpC.rd == RSPOpC.rt){
			MmxPsubswRegToReg(x86_MM0, x86_MM0);
			MmxPsubswRegToReg(x86_MM1, x86_MM1);
		} else {
			sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.rt);
			MmxPsubswVariableToReg(x86_MM0, &RSP_Vect[RSPOpC.rt].HW[0], Reg);
			sprintf(Reg, "RSP_Vect[%i].HW[4]", RSPOpC.rt);
			MmxPsubswVariableToReg(x86_MM1, &RSP_Vect[RSPOpC.rt].HW[4], Reg);
		}
	} else {
		RSP_MultiElement2Mmx(x86_MM2, x86_MM3);
		MmxPsubswRegToReg(x86_MM0, x86_MM2);
		MmxPsubswRegToReg(x86_MM1, x86_MM3);
	}

	sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.sa);
	MmxMoveQwordRegToVariable(x86_MM0, &RSP_Vect[RSPOpC.sa].UHW[0], Reg);
	sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.sa);
	MmxMoveQwordRegToVariable(x86_MM1, &RSP_Vect[RSPOpC.sa].UHW[4], Reg);
	if (IsNextInstructionMmx(CompilePC) != TRUE) {
		MmxEmptyMultimediaState();
	}

	return TRUE;
}

void Compile_Vector_VSUB ( void ) {
	char Reg[256];
	int count, el, del;

	BOOL bWriteToDest = WriteToVectorDest(RSPOpC.sa, CompilePC);
	BOOL bOptimize = ((RSPOpC.rs & 0x0f) >= 8) ? TRUE : FALSE;
	BOOL bWriteToAccum = WriteToAccum(Low16BitAccum, CompilePC);
	BOOL bFlagUseage = UseRspFlags(CompilePC);

	#ifndef CompileVsub
	Cheat_r4300iOpcode(RSP_Vector_VSUB,"RSP_Vector_VSUB"); return;
	#endif

	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));

	if (bWriteToAccum == FALSE && bFlagUseage == FALSE) {
		if (TRUE == Compile_Vector_VSUB_MMX())
			return;
	}

	Push(x86_EBP);

	/* Used for involking the x86 carry flag */
	XorX86RegToX86Reg(x86_ECX, x86_ECX);
	MoveVariableToX86reg(&RSP_Flags[0].UW, "RSP_Flags[0].UW", x86_EBP);

	if (bOptimize == TRUE) {
		del = (RSPOpC.rs & 0x07) ^ 7;
		sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del);
		MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX);
	}

	if (bWriteToDest == TRUE) {
		/*
		 * Prepare for conditional moves
		 */
		MoveConstToX86reg(0x00007fff, x86_ESI);
		MoveConstToX86reg(0xffff8000, x86_EDI);
	}

	for (count = 0; count < 8; count++) {
		CPU_Message("     Iteration: %i", count);
		el = Indx[RSPOpC.rs].B[count];
		del = EleSpec[RSPOpC.rs].B[el];

		MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].HW[el], "RSP_Vect[RSPOpC.rd].HW[el]", x86_EAX);
		if (bOptimize == FALSE) {
			sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del);
			MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX);
		}
	
		MoveX86RegToX86Reg(x86_EBP, x86_EDX);
		AndConstToX86Reg(x86_EDX, 1 << (7 - el));
		CompX86RegToX86Reg(x86_ECX, x86_EDX);

		SbbX86RegToX86Reg(x86_EAX, x86_EBX);

		if (bWriteToAccum != FALSE) {
			sprintf(Reg, "RSP_ACCUM[%i].HW[1]", el);
			MoveX86regHalfToVariable(x86_EAX, &RSP_ACCUM[el].HW[1], Reg);
		}

		if (bWriteToDest != FALSE) {
			CompX86RegToX86Reg(x86_EAX, x86_ESI);
			CondMoveGreater(x86_EAX, x86_ESI);
			CompX86RegToX86Reg(x86_EAX, x86_EDI);
			CondMoveLess(x86_EAX, x86_EDI);

			sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.sa, el);
			MoveX86regHalfToVariable(x86_EAX, &RSP_Vect[RSPOpC.sa].HW[el], Reg);
		}
	}

	MoveConstToVariable(0, &RSP_Flags[0].UW, "RSP_Flags[0].UW");
	Pop(x86_EBP);
}

BOOL Compile_Vector_VABS_MMX ( void ) {
	char Reg[256];

	/* Do our MMX checks here */
	if (IsMmxEnabled == FALSE)
		return FALSE;
	if ((RSPOpC.rs & 0x0f) >= 2 && (RSPOpC.rs & 0x0f) <= 7 && IsMmx2Enabled == FALSE)
		return FALSE;

	sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.rd);
	MmxMoveQwordVariableToReg(x86_MM0, &RSP_Vect[RSPOpC.rd].UHW[0], Reg);
	sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.rd);
	MmxMoveQwordVariableToReg(x86_MM1, &RSP_Vect[RSPOpC.rd].UHW[4], Reg);

	if ((RSPOpC.rs & 15) >= 8) {
		RSP_Element2Mmx(x86_MM2);
		MmxMoveRegToReg(x86_MM3, x86_MM2);
	} else if ((RSPOpC.rs & 15) < 2) {
		if (RSPOpC.rd != RSPOpC.rt) {
			sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.rt);
			MmxMoveQwordVariableToReg(x86_MM2, &RSP_Vect[RSPOpC.rt].HW[0], Reg);
			sprintf(Reg, "RSP_Vect[%i].HW[4]", RSPOpC.rt);
			MmxMoveQwordVariableToReg(x86_MM3, &RSP_Vect[RSPOpC.rt].HW[4], Reg);
		} else {
			sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.rt);
			MmxMoveRegToReg(x86_MM2, x86_MM0);
			sprintf(Reg, "RSP_Vect[%i].HW[4]", RSPOpC.rt);
			MmxMoveRegToReg(x86_MM3, x86_MM1);
		}
	} else {
		RSP_MultiElement2Mmx(x86_MM2, x86_MM3);
	}

	if (RSPOpC.rd == RSPOpC.rt) {
		MmxPsrawImmed(x86_MM2, 15);
		MmxPsrawImmed(x86_MM3, 15);

		MmxXorRegToReg(x86_MM0, x86_MM2);
		MmxXorRegToReg(x86_MM1, x86_MM3);

		MmxPsubswRegToReg(x86_MM0, x86_MM2);
		MmxPsubswRegToReg(x86_MM1, x86_MM3);
	} else {
		MmxXorRegToReg(x86_MM7, x86_MM7);

		MmxMoveRegToReg(x86_MM4, x86_MM0);
		MmxMoveRegToReg(x86_MM5, x86_MM1);

		MmxPsrawImmed(x86_MM4, 15);
		MmxPsrawImmed(x86_MM5, 15);

		MmxPcmpeqwRegToReg(x86_MM0, x86_MM7);
		MmxPcmpeqwRegToReg(x86_MM1, x86_MM7);

		MmxXorRegToReg(x86_MM2, x86_MM4);
		MmxXorRegToReg(x86_MM3, x86_MM5);

		MmxPsubswRegToReg(x86_MM2, x86_MM4);
		MmxPsubswRegToReg(x86_MM3, x86_MM5);

		MmxPandnRegToReg(x86_MM0, x86_MM2);
		MmxPandnRegToReg(x86_MM1, x86_MM3);
	}

	sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.sa);
	MmxMoveQwordRegToVariable(x86_MM0, &RSP_Vect[RSPOpC.sa].UHW[0], Reg);
	sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.sa);
	MmxMoveQwordRegToVariable(x86_MM1, &RSP_Vect[RSPOpC.sa].UHW[4], Reg);

	if (IsNextInstructionMmx(CompilePC) != TRUE) {
		MmxEmptyMultimediaState();
	}

	return TRUE;
}

void Compile_Vector_VABS ( void ) {
	int count, el, del;
	char Reg[256];
	
	BOOL bWriteToDest = WriteToVectorDest(RSPOpC.sa, CompilePC);
	BOOL bWriteToAccum = WriteToAccum(Low16BitAccum, CompilePC);

	#ifndef CompileVabs
	Cheat_r4300iOpcode(RSP_Vector_VABS,"RSP_Vector_VABS"); return;
	#endif

	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));

	if (bWriteToAccum == FALSE) {
		if (TRUE == Compile_Vector_VABS_MMX())
			return;
	}
	
	for (count = 0; count < 8; count++) {
		CPU_Message("     Iteration: %i", count);
		el = Indx[RSPOpC.rs].B[count];
		del = EleSpec[RSPOpC.rs].B[el];

		if (RSPOpC.rd == RSPOpC.rt && (RSPOpC.rs & 0xF) < 2) {
			/**
			** Optimize: EDI/ESI unused, and ECX is const etc
			***/

			sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rd, el);
			MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].HW[el], Reg, x86_EAX);

			/*** Obtain the negative of the source ****/
			MoveX86RegToX86Reg(x86_EAX, x86_EBX);
			NegateX86reg(x86_EBX);
		
			/**
			** determine negative value, 
			** note: negate(FFFF8000h) == 00008000h 
			***/

			MoveConstToX86reg(0x7fff, x86_ECX);
			CompConstToX86reg(x86_EBX, 0x00008000);
			CondMoveEqual(x86_EBX, x86_ECX);

			/* sign clamp, dest = (eax >= 0) ? eax : ebx */
			CompConstToX86reg(x86_EAX, 0);
			CondMoveLess(x86_EAX, x86_EBX);

			if (bWriteToDest == TRUE) {
				sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.sa, el);
				MoveX86regHalfToVariable(x86_EAX, &RSP_Vect[RSPOpC.sa].HW[el], Reg);
			}
			if (bWriteToAccum == TRUE) {
				sprintf(Reg, "RSP_ACCUM[%i].HW[1]", el);
				MoveX86regHalfToVariable(x86_EAX, &RSP_ACCUM[el].HW[1], Reg);
			}
		} else {
			/**
			** Optimize: ESI unused, and EDX is const etc
			***/

			sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rd, el);
			MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].HW[el], Reg, x86_EAX);
			sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del);
			MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX);

			/*** Obtain the negative of the source ****/
			MoveX86RegToX86Reg(x86_EBX, x86_ECX);
			NegateX86reg(x86_EBX);

			/**
			** determine negative value, 
			** note: negate(FFFF8000h) == 00008000h 
			***/

			MoveConstToX86reg(0x7fff, x86_EDX);
			CompConstToX86reg(x86_EBX, 0x00008000);
			CondMoveEqual(x86_EBX, x86_EDX);

			/* sign clamp, dest = (eax >= 0) ? ecx : ebx */
			CompConstToX86reg(x86_EAX, 0);
			CondMoveGreaterEqual(x86_EDI, x86_ECX);
			CondMoveLess(x86_EDI, x86_EBX);

			if (bWriteToDest == TRUE) {
				sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.sa, el);
				MoveX86regHalfToVariable(x86_EDI, &RSP_Vect[RSPOpC.sa].HW[el], Reg);
			}
			if (bWriteToAccum == TRUE) {
				sprintf(Reg, "RSP_ACCUM[%i].HW[1]", el);
				MoveX86regHalfToVariable(x86_EDI, &RSP_ACCUM[el].HW[1], Reg);	
			}
		}
	}
}

void Compile_Vector_VADDC ( void ) {
	char Reg[256];
	int count, el, del;

	BOOL bWriteToDest = WriteToVectorDest(RSPOpC.sa, CompilePC);
	BOOL bWriteToAccum = WriteToAccum(Low16BitAccum, CompilePC);
	BOOL bElement = ((RSPOpC.rs & 0x0f) >= 8) ? TRUE : FALSE;
	
	#ifndef CompileVaddc
	Cheat_r4300iOpcode(RSP_Vector_VADDC,"RSP_Vector_VADDC"); return;
	#endif

	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));

	if (bElement == TRUE) {
		del = (RSPOpC.rs & 0x07) ^ 7;
		sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del);
		MoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX);
	}

	/* Initialize flag register */
	XorX86RegToX86Reg(x86_ECX, x86_ECX);

	Push(x86_EBP);
	sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.rd);
	MoveOffsetToX86reg((DWORD)&RSP_Vect[RSPOpC.rd].HW[0], Reg, x86_EBP);

	for (count = 0; count < 8; count++) {
		CPU_Message("     Iteration: %i", count);
		el = Indx[RSPOpC.rs].B[count];
		del = EleSpec[RSPOpC.rs].B[el];
	
		/*sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rd, el);
		MoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].HW[el], Reg, x86_EAX);*/
		MoveZxX86RegPtrDispToX86RegHalf(x86_EBP, (BYTE)(el * 2), x86_EAX);

		if (bElement == FALSE) {
			sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del);
			MoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX);
		}

		AddX86RegToX86Reg(x86_EAX, x86_EBX);

		XorX86RegToX86Reg(x86_EDX, x86_EDX);
		TestConstToX86Reg(0xFFFF0000, x86_EAX);
		Setnz(x86_EDX);
		if ((7 - el) != 0) {
			ShiftLeftSignImmed(x86_EDX, (BYTE)(7 - el));
		}
		OrX86RegToX86Reg(x86_ECX, x86_EDX);

		if (bWriteToAccum != FALSE) {
			sprintf(Reg, "RSP_ACCUM[%i].HW[1]", el);
			MoveX86regHalfToVariable(x86_EAX, &RSP_ACCUM[el].HW[1], Reg);
		}

		if (bWriteToDest != FALSE) {
			sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.sa, el);
			MoveX86regHalfToVariable(x86_EAX, &RSP_Vect[RSPOpC.sa].HW[el], Reg);
		}
	}
	MoveX86regToVariable(x86_ECX, &RSP_Flags[0].UW, "RSP_Flags[0].UW");
	Pop(x86_EBP);
}

void Compile_Vector_VSUBC ( void ) {
	char Reg[256];
	int count, el, del;

	BOOL bWriteToDest = WriteToVectorDest(RSPOpC.sa, CompilePC);
	BOOL bWriteToAccum = WriteToAccum(Low16BitAccum, CompilePC);
	BOOL bElement = ((RSPOpC.rs & 0x0f) >= 8) ? TRUE : FALSE;
	
	#ifndef CompileVsubc
	Cheat_r4300iOpcode(RSP_Vector_VSUBC,"RSP_Vector_VSUBC"); return;
	#endif

	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));

	if (bElement == TRUE) {
		del = (RSPOpC.rs & 0x07) ^ 7;
		sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del);
		MoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX);
	}

	/* Initialize flag register */
	XorX86RegToX86Reg(x86_ECX, x86_ECX);

	for (count = 0; count < 8; count++) {
		CPU_Message("     Iteration: %i", count);
		el = Indx[RSPOpC.rs].B[count];
		del = EleSpec[RSPOpC.rs].B[el];
	
		sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rd, el);
		MoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].HW[el], Reg, x86_EAX);

		if (bElement == FALSE) {
			sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del);
			MoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX);
		}

		SubX86RegToX86Reg(x86_EAX, x86_EBX);

		XorX86RegToX86Reg(x86_EDX, x86_EDX);
		TestConstToX86Reg(0x0000FFFF, x86_EAX);
		Setnz(x86_EDX);
		ShiftLeftSignImmed(x86_EDX, (BYTE)(15 - el));
		OrX86RegToX86Reg(x86_ECX, x86_EDX);

		XorX86RegToX86Reg(x86_EDX, x86_EDX);
		TestConstToX86Reg(0xFFFF0000, x86_EAX);
		Setnz(x86_EDX);
		ShiftLeftSignImmed(x86_EDX, (BYTE)(7 - el));
		OrX86RegToX86Reg(x86_ECX, x86_EDX);

		if (bWriteToAccum != FALSE) {
			sprintf(Reg, "RSP_ACCUM[%i].HW[1]", el);
			MoveX86regHalfToVariable(x86_EAX, &RSP_ACCUM[el].HW[1], Reg);
		}
		if (bWriteToDest != FALSE) {
			sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.sa, el);
			MoveX86regHalfToVariable(x86_EAX, &RSP_Vect[RSPOpC.sa].HW[el], Reg);
		}
	}
	MoveX86regToVariable(x86_ECX, &RSP_Flags[0].UW, "RSP_Flags[0].UW");
}

void Compile_Vector_VSAW ( void ) {
	char Reg[256];
	DWORD Word;

	#ifndef CompileVsaw
	Cheat_r4300iOpcode(RSP_Vector_VSAW,"RSP_Vector_VSAW"); return;
	#endif

	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));

	switch ((RSPOpC.rs & 0xF)) {
	case 8: Word = 3; break;
	case 9: Word = 2; break;
	case 10: Word = 1; break;
	default:
		MoveConstToVariable(0, &RSP_Vect[RSPOpC.sa].DW[1], "RSP_Vect[RSPOpC.sa].DW[1]");
		MoveConstToVariable(0, &RSP_Vect[RSPOpC.sa].DW[0], "RSP_Vect[RSPOpC.sa].DW[0]");
		return;
	}

	sprintf(Reg, "RSP_ACCUM[1].HW[%i]", Word);
	MoveVariableToX86regHalf(&RSP_ACCUM[1].HW[Word], Reg, x86_EAX);
	sprintf(Reg, "RSP_ACCUM[3].HW[%i]", Word);
	MoveVariableToX86regHalf(&RSP_ACCUM[3].HW[Word], Reg, x86_EBX);
	sprintf(Reg, "RSP_ACCUM[5].HW[%i]", Word);
	MoveVariableToX86regHalf(&RSP_ACCUM[5].HW[Word], Reg, x86_ECX);
	sprintf(Reg, "RSP_ACCUM[7].HW[%i]", Word);
	MoveVariableToX86regHalf(&RSP_ACCUM[7].HW[Word], Reg, x86_EDX);

	ShiftLeftSignImmed(x86_EAX, 16);
	ShiftLeftSignImmed(x86_EBX, 16);
	ShiftLeftSignImmed(x86_ECX, 16);
	ShiftLeftSignImmed(x86_EDX, 16);

	sprintf(Reg, "RSP_ACCUM[0].HW[%i]", Word);
	MoveVariableToX86regHalf(&RSP_ACCUM[0].HW[Word], Reg, x86_EAX);
	sprintf(Reg, "RSP_ACCUM[2].HW[%i]", Word);
	MoveVariableToX86regHalf(&RSP_ACCUM[2].HW[Word], Reg, x86_EBX);
	sprintf(Reg, "RSP_ACCUM[4].HW[%i]", Word);
	MoveVariableToX86regHalf(&RSP_ACCUM[4].HW[Word], Reg, x86_ECX);
	sprintf(Reg, "RSP_ACCUM[6].HW[%i]", Word);
	MoveVariableToX86regHalf(&RSP_ACCUM[6].HW[Word], Reg, x86_EDX);

	sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.sa);
	MoveX86regToVariable(x86_EAX, &RSP_Vect[RSPOpC.sa].HW[0], Reg);
	sprintf(Reg, "RSP_Vect[%i].HW[2]", RSPOpC.sa);
	MoveX86regToVariable(x86_EBX, &RSP_Vect[RSPOpC.sa].HW[2], Reg);
	sprintf(Reg, "RSP_Vect[%i].HW[4]", RSPOpC.sa);
	MoveX86regToVariable(x86_ECX, &RSP_Vect[RSPOpC.sa].HW[4], Reg);
	sprintf(Reg, "RSP_Vect[%i].HW[6]", RSPOpC.sa);
	MoveX86regToVariable(x86_EDX, &RSP_Vect[RSPOpC.sa].HW[6], Reg);
}

void Compile_Vector_VLT ( void ) {
	Cheat_r4300iOpcode(RSP_Vector_VLT,"RSP_Vector_VLT");
}

void Compile_Vector_VEQ ( void ) {
	Cheat_r4300iOpcode(RSP_Vector_VEQ,"RSP_Vector_VEQ");
}

void Compile_Vector_VNE ( void ) {
	Cheat_r4300iOpcode(RSP_Vector_VNE,"RSP_Vector_VNE");
}

BOOL Compile_Vector_VGE_MMX ( void ) {
	char Reg[256];

	if ((RSPOpC.rs & 0xF) >= 2 && (RSPOpC.rs & 0xF) <= 7 && IsMmx2Enabled == FALSE)
		return FALSE;

	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));
	MoveConstToVariable(0, &RSP_Flags[1].UW, "RSP_Flags[1].UW");

	sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.rd);
	MmxMoveQwordVariableToReg(x86_MM0, &RSP_Vect[RSPOpC.rd].HW[0], Reg);
	sprintf(Reg, "RSP_Vect[%i].HW[4]", RSPOpC.rd);
	MmxMoveQwordVariableToReg(x86_MM1, &RSP_Vect[RSPOpC.rd].HW[4], Reg);
	MmxMoveRegToReg(x86_MM2, x86_MM0);
	MmxMoveRegToReg(x86_MM3, x86_MM1);

	if ((RSPOpC.rs & 0x0f) < 2) {
		sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.rt);
		MmxMoveQwordVariableToReg(x86_MM4, &RSP_Vect[RSPOpC.rt].HW[0], Reg);
		sprintf(Reg, "RSP_Vect[%i].HW[4]", RSPOpC.rt);
		MmxMoveQwordVariableToReg(x86_MM5, &RSP_Vect[RSPOpC.rt].HW[4], Reg);
	} else if ((RSPOpC.rs & 0x0f) >= 8) {
		RSP_Element2Mmx(x86_MM4);
	} else {
		RSP_MultiElement2Mmx(x86_MM4, x86_MM5);
	}

	MmxCompareGreaterWordRegToReg(x86_MM2, x86_MM4);
	MmxCompareGreaterWordRegToReg(x86_MM3, ((RSPOpC.rs & 0x0f) >= 8) ? x86_MM4 : x86_MM5);

	MmxPandRegToReg(x86_MM0, x86_MM2);
	MmxPandRegToReg(x86_MM1, x86_MM3);
	MmxPandnRegToReg(x86_MM2, x86_MM4);
	MmxPandnRegToReg(x86_MM3, ((RSPOpC.rs & 0x0f) >= 8) ? x86_MM4 : x86_MM5);

	MmxPorRegToReg(x86_MM0, x86_MM2);
	MmxPorRegToReg(x86_MM1, x86_MM3);
	MoveConstToVariable(0, &RSP_Flags[0].UW, "RSP_Flags[0].UW");
	return TRUE;
}

void Compile_Vector_VGE ( void ) {
/*	BOOL bWriteToAccum = WriteToAccum(Low16BitAccum, CompilePC);

	/* FIXME: works ok, but needs careful flag analysis */
/*	#if defined (DLIST)
	if (bWriteToAccum == FALSE && TRUE == Compile_Vector_VGE_MMX()) {
		return;
	}
	#endif
*/
	Cheat_r4300iOpcode(RSP_Vector_VGE,"RSP_Vector_VGE");
}

void Compile_Vector_VCL ( void ) {
	Cheat_r4300iOpcode(RSP_Vector_VCL,"RSP_Vector_VCL");
}

void Compile_Vector_VCH ( void ) {
	Cheat_r4300iOpcode(RSP_Vector_VCH,"RSP_Vector_VCH");
}

void Compile_Vector_VCR ( void ) {
	Cheat_r4300iOpcode(RSP_Vector_VCR,"RSP_Vector_VCR");
}

void Compile_Vector_VMRG ( void ) {
	char Reg[256];
	int count, el, del;
	BOOL bWriteToAccum = WriteToAccum(Low16BitAccum, CompilePC);

	#ifndef CompileVmrg
	Cheat_r4300iOpcode(RSP_Vector_VMRG,"RSP_Vector_VMRG"); return;
	#endif

	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));
	MoveVariableToX86reg(&RSP_Flags[1].UW, "RSP_Flags[1].UW", x86_EDX);

	for (count = 0;count < 8; count++) {
		el = Indx[RSPOpC.rs].UB[count];
		del = EleSpec[RSPOpC.rs].UB[el];
		CPU_Message("     Iteration: %i", count);

		sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rd, el);
		MoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].HW[el], Reg, x86_EAX);
		sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del);
		MoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX);

		TestConstToX86Reg(1 << (7 - el), x86_EDX);
		CondMoveNotEqual(x86_ECX, x86_EAX);
		CondMoveEqual(x86_ECX, x86_EBX);

		if (bWriteToAccum == TRUE) {
			sprintf(Reg, "RSP_ACCUM[%i].HW[1]", el);
			MoveX86regHalfToVariable(x86_ECX, &RSP_ACCUM[el].HW[1], Reg);
		}
		sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.sa, el);
		MoveX86regHalfToVariable(x86_ECX, &RSP_Vect[RSPOpC.sa].HW[el], Reg);
	}
}

BOOL Compile_Vector_VAND_MMX ( void ) {
	char Reg[256];

	/* Do our MMX checks here */
	if (IsMmxEnabled == FALSE)
		return FALSE;
	if ((RSPOpC.rs & 0x0f) >= 2 && (RSPOpC.rs & 0x0f) <= 7 && IsMmx2Enabled == FALSE)
		return FALSE;

	sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.rd);
	MmxMoveQwordVariableToReg(x86_MM0, &RSP_Vect[RSPOpC.rd].UHW[0], Reg);
	sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.rd);
	MmxMoveQwordVariableToReg(x86_MM1, &RSP_Vect[RSPOpC.rd].UHW[4], Reg);

	if ((RSPOpC.rs & 0xF) >= 8) {
		RSP_Element2Mmx(x86_MM2);
		MmxPandRegToReg(x86_MM0, x86_MM2);
		MmxPandRegToReg(x86_MM1, x86_MM2);
	} else if ((RSPOpC.rs & 0xF) < 2) {
		sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.rt);
		MmxPandVariableToReg(&RSP_Vect[RSPOpC.rt].HW[0], Reg, x86_MM0);
		sprintf(Reg, "RSP_Vect[%i].HW[4]", RSPOpC.rt);
		MmxPandVariableToReg(&RSP_Vect[RSPOpC.rt].HW[4], Reg, x86_MM1);
	} else {
		RSP_MultiElement2Mmx(x86_MM2, x86_MM3);
		MmxPandRegToReg(x86_MM0, x86_MM2);
		MmxPandRegToReg(x86_MM1, x86_MM3);
	}

	sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.sa);
	MmxMoveQwordRegToVariable(x86_MM0, &RSP_Vect[RSPOpC.sa].UHW[0], Reg);
	sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.sa);
	MmxMoveQwordRegToVariable(x86_MM1, &RSP_Vect[RSPOpC.sa].UHW[4], Reg);

	if (IsNextInstructionMmx(CompilePC) == FALSE)
		MmxEmptyMultimediaState();

	return TRUE;
}

void Compile_Vector_VAND ( void ) {
	char Reg[256];
	int el, del, count;
	BOOL bWriteToDest = WriteToVectorDest(RSPOpC.sa, CompilePC);
	BOOL bElement = ((RSPOpC.rs & 0x0f) >= 8) ? TRUE : FALSE;
	BOOL bWriteToAccum = WriteToAccum(Low16BitAccum, CompilePC);

	#ifndef CompileVand
	Cheat_r4300iOpcode(RSP_Vector_VAND,"RSP_Vector_VAND"); return;
	#endif

	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));

	if (bWriteToAccum == FALSE) {
		if (TRUE == Compile_Vector_VAND_MMX())
			return;
	}
	
	if (bElement == TRUE) {
		del = (RSPOpC.rs & 0x07) ^ 7;
		sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del);
		MoveVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX);
	}

	for (count = 0; count < 8; count++) {
		el = Indx[RSPOpC.rs].B[count];
		del = EleSpec[RSPOpC.rs].B[el];

		CPU_Message("     Iteration: %i", count);

		sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rd, el);
		MoveVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].HW[el], Reg, x86_EAX);
		
		if (bElement == FALSE) {
			sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del);
			AndVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EAX);
		} else {
			AndX86RegHalfToX86RegHalf(x86_EAX, x86_EBX);
		}

		if (bWriteToDest != FALSE) {
			sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.sa, el);
			MoveX86regHalfToVariable(x86_EAX, &RSP_Vect[RSPOpC.sa].HW[el], Reg);
		}

		if (bWriteToAccum != FALSE) {
			sprintf(Reg, "RSP_ACCUM[%i].HW[1]", el);
			MoveX86regHalfToVariable(x86_EAX, &RSP_ACCUM[el].HW[1], Reg);
		}
	}
}

BOOL Compile_Vector_VNAND_MMX ( void ) {
	char Reg[256];

	/* Do our MMX checks here */
	if (IsMmxEnabled == FALSE)
		return FALSE;
	if ((RSPOpC.rs & 0x0f) >= 2 && (RSPOpC.rs & 0x0f) <= 7 && IsMmx2Enabled == FALSE)
		return FALSE;

	sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.rd);
	MmxMoveQwordVariableToReg(x86_MM0, &RSP_Vect[RSPOpC.rd].UHW[0], Reg);
	sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.rd);
	MmxMoveQwordVariableToReg(x86_MM1, &RSP_Vect[RSPOpC.rd].UHW[4], Reg);
	MmxPcmpeqwRegToReg(x86_MM7, x86_MM7);

	if ((RSPOpC.rs & 0xF) >= 8) {
		RSP_Element2Mmx(x86_MM2);
		MmxPandRegToReg(x86_MM0, x86_MM2);
		MmxPandRegToReg(x86_MM1, x86_MM2);
	} else if ((RSPOpC.rs & 0xF) < 2) {
		sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.rt);
		MmxPandVariableToReg(&RSP_Vect[RSPOpC.rt].HW[0], Reg, x86_MM0);
		sprintf(Reg, "RSP_Vect[%i].HW[4]", RSPOpC.rt);
		MmxPandVariableToReg(&RSP_Vect[RSPOpC.rt].HW[4], Reg, x86_MM1);
	} else {
		RSP_MultiElement2Mmx(x86_MM2, x86_MM3);
		MmxPandRegToReg(x86_MM0, x86_MM2);
		MmxPandRegToReg(x86_MM1, x86_MM3);
	}

	MmxXorRegToReg(x86_MM0, x86_MM7);
	MmxXorRegToReg(x86_MM1, x86_MM7);
	sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.sa);
	MmxMoveQwordRegToVariable(x86_MM0, &RSP_Vect[RSPOpC.sa].UHW[0], Reg);
	sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.sa);
	MmxMoveQwordRegToVariable(x86_MM1, &RSP_Vect[RSPOpC.sa].UHW[4], Reg);

	if (IsNextInstructionMmx(CompilePC) == FALSE)
		MmxEmptyMultimediaState();

	return TRUE;
}

void Compile_Vector_VNAND ( void ) {
	char Reg[256];
	int el, del, count;
	BOOL bWriteToDest = WriteToVectorDest(RSPOpC.sa, CompilePC);
	BOOL bElement = ((RSPOpC.rs & 0x0f) >= 8) ? TRUE : FALSE;
	BOOL bWriteToAccum = WriteToAccum(Low16BitAccum, CompilePC);

#ifndef CompileVnand
	Cheat_r4300iOpcode(RSP_Vector_VNAND, "RSP_Vector_VNAND"); return;
#endif

	CPU_Message("  %X %s", CompilePC, RSPOpcodeName(RSPOpC.Hex, CompilePC));

	if (bWriteToAccum == FALSE) {
		if (TRUE == Compile_Vector_VNAND_MMX())
			return;
	}

	if (bElement == TRUE) {
		del = (RSPOpC.rs & 0x07) ^ 7;
		sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del);
		MoveVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX);
	}

	for (count = 0; count < 8; count++) {
		el = Indx[RSPOpC.rs].B[count];
		del = EleSpec[RSPOpC.rs].B[el];

		CPU_Message("     Iteration: %i", count);

		sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rd, el);
		MoveVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].HW[el], Reg, x86_EAX);

		if (bElement == FALSE) {
			sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del);
			AndVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EAX);
		} else {
			AndX86RegHalfToX86RegHalf(x86_EAX, x86_EBX);
		}

		NotX86reg(x86_EAX);

		if (bWriteToDest != FALSE) {
			sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.sa, el);
			MoveX86regHalfToVariable(x86_EAX, &RSP_Vect[RSPOpC.sa].HW[el], Reg);
		}

		if (bWriteToAccum != FALSE) {
			sprintf(Reg, "RSP_ACCUM[%i].HW[1]", el);
			MoveX86regHalfToVariable(x86_EAX, &RSP_ACCUM[el].HW[1], Reg);
		}
	}
}

BOOL Compile_Vector_VOR_MMX ( void ) {
	char Reg[256];

	/* Do our MMX checks here */
	if (IsMmxEnabled == FALSE)
		return FALSE;
	if ((RSPOpC.rs & 0x0f) >= 2 && (RSPOpC.rs & 0x0f) <= 7 && IsMmx2Enabled == FALSE)
		return FALSE;

	sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.rd);
	MmxMoveQwordVariableToReg(x86_MM0, &RSP_Vect[RSPOpC.rd].UHW[0], Reg);
	sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.rd);
	MmxMoveQwordVariableToReg(x86_MM1, &RSP_Vect[RSPOpC.rd].UHW[4], Reg);

	if ((RSPOpC.rs & 0xF) < 2 && (RSPOpC.rd == RSPOpC.rt)) {

	} else if ((RSPOpC.rs & 0xF) >= 8) {
		RSP_Element2Mmx(x86_MM2);
		MmxPorRegToReg(x86_MM0, x86_MM2);
		MmxPorRegToReg(x86_MM1, x86_MM2);
	} else if ((RSPOpC.rs & 0xF) < 2) {
		sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.rt);
		MmxPorVariableToReg(&RSP_Vect[RSPOpC.rt].HW[0], Reg, x86_MM0);
		sprintf(Reg, "RSP_Vect[%i].HW[4]", RSPOpC.rt);
		MmxPorVariableToReg(&RSP_Vect[RSPOpC.rt].HW[4], Reg, x86_MM1);
	} else {
		RSP_MultiElement2Mmx(x86_MM2, x86_MM3);
		MmxPorRegToReg(x86_MM0, x86_MM2);
		MmxPorRegToReg(x86_MM1, x86_MM3);
	}

	sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.sa);
	MmxMoveQwordRegToVariable(x86_MM0, &RSP_Vect[RSPOpC.sa].UHW[0], Reg);
	sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.sa);
	MmxMoveQwordRegToVariable(x86_MM1, &RSP_Vect[RSPOpC.sa].UHW[4], Reg);

	if (IsNextInstructionMmx(CompilePC) == FALSE)
		MmxEmptyMultimediaState();

	return TRUE;
}

void Compile_Vector_VOR ( void ) {
	char Reg[256];
	int el, del, count;
	BOOL bElement = ((RSPOpC.rs & 0x0f) >= 8) ? TRUE : FALSE;
	BOOL bWriteToAccum = WriteToAccum(Low16BitAccum, CompilePC);

#ifndef CompileVor
	Cheat_r4300iOpcode(RSP_Vector_VOR, "RSP_Vector_VOR"); return;
#endif

	CPU_Message("  %X %s", CompilePC, RSPOpcodeName(RSPOpC.Hex, CompilePC));

	if (bWriteToAccum == FALSE) {
		if (TRUE == Compile_Vector_VOR_MMX())
			return;
	}

	if (bElement == TRUE) {
		del = (RSPOpC.rs & 0x07) ^ 7;
		sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del);
		MoveVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX);
	}

	for (count = 0; count < 8; count++) {
		el = Indx[RSPOpC.rs].B[count];
		del = EleSpec[RSPOpC.rs].B[el];

		CPU_Message("     Iteration: %i", count);

		sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rd, el);
		MoveVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].HW[el], Reg, x86_EAX);

		if (bElement == FALSE) {
			sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del);
			OrVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EAX);
		} else {
			OrX86RegToX86Reg(x86_EAX, x86_EBX);
		}

		if (bWriteToAccum != FALSE) {
			sprintf(Reg, "RSP_ACCUM[%i].HW[1]", el);
			MoveX86regHalfToVariable(x86_EAX, &RSP_ACCUM[el].HW[1], Reg);
		}
		sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.sa, el);
		MoveX86regHalfToVariable(x86_EAX, &RSP_Vect[RSPOpC.sa].HW[el], Reg);
	}
}

BOOL Compile_Vector_VNOR_MMX ( void ) {
	char Reg[256];

	/* Do our MMX checks here */
	if (IsMmxEnabled == FALSE)
		return FALSE;
	if ((RSPOpC.rs & 0x0f) >= 2 && (RSPOpC.rs & 0x0f) <= 7 && IsMmx2Enabled == FALSE)
		return FALSE;

	sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.rd);
	MmxMoveQwordVariableToReg(x86_MM0, &RSP_Vect[RSPOpC.rd].UHW[0], Reg);
	sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.rd);
	MmxMoveQwordVariableToReg(x86_MM1, &RSP_Vect[RSPOpC.rd].UHW[4], Reg);
	MmxPcmpeqwRegToReg(x86_MM7, x86_MM7);

	if ((RSPOpC.rs & 0xF) >= 8) {
		RSP_Element2Mmx(x86_MM2);
		MmxPorRegToReg(x86_MM0, x86_MM2);
		MmxPorRegToReg(x86_MM1, x86_MM2);
	} else if ((RSPOpC.rs & 0xF) < 2) {
		sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.rt);
		MmxPorVariableToReg(&RSP_Vect[RSPOpC.rt].HW[0], Reg, x86_MM0);
		sprintf(Reg, "RSP_Vect[%i].HW[4]", RSPOpC.rt);
		MmxPorVariableToReg(&RSP_Vect[RSPOpC.rt].HW[4], Reg, x86_MM1);
	} else {
		RSP_MultiElement2Mmx(x86_MM2, x86_MM3);
		MmxPorRegToReg(x86_MM0, x86_MM2);
		MmxPorRegToReg(x86_MM1, x86_MM3);
	}

	MmxXorRegToReg(x86_MM0, x86_MM7);
	MmxXorRegToReg(x86_MM1, x86_MM7);
	sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.sa);
	MmxMoveQwordRegToVariable(x86_MM0, &RSP_Vect[RSPOpC.sa].UHW[0], Reg);
	sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.sa);
	MmxMoveQwordRegToVariable(x86_MM1, &RSP_Vect[RSPOpC.sa].UHW[4], Reg);

	if (IsNextInstructionMmx(CompilePC) == FALSE)
		MmxEmptyMultimediaState();

	return TRUE;
}

void Compile_Vector_VNOR ( void ) {
	char Reg[256];
	int el, del, count;
	BOOL bElement = ((RSPOpC.rs & 0x0f) >= 8) ? TRUE : FALSE;
	BOOL bWriteToAccum = WriteToAccum(Low16BitAccum, CompilePC);

#ifndef CompileVnor
	Cheat_r4300iOpcode(RSP_Vector_VNOR, "RSP_Vector_VNOR"); return;
#endif

	CPU_Message("  %X %s", CompilePC, RSPOpcodeName(RSPOpC.Hex, CompilePC));

	if (bWriteToAccum == FALSE) {
		if (TRUE == Compile_Vector_VNOR_MMX())
			return;
	}

	if (bElement == TRUE) {
		del = (RSPOpC.rs & 0x07) ^ 7;
		sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del);
		MoveVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX);
	}

	for (count = 0; count < 8; count++) {
		el = Indx[RSPOpC.rs].B[count];
		del = EleSpec[RSPOpC.rs].B[el];

		CPU_Message("     Iteration: %i", count);

		sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rd, el);
		MoveVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].HW[el], Reg, x86_EAX);

		if (bElement == FALSE) {
			sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del);
			OrVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EAX);
		} else {
			OrX86RegToX86Reg(x86_EAX, x86_EBX);
		}

		NotX86reg(x86_EAX);

		if (bWriteToAccum != FALSE) {
			sprintf(Reg, "RSP_ACCUM[%i].HW[1]", el);
			MoveX86regHalfToVariable(x86_EAX, &RSP_ACCUM[el].HW[1], Reg);
		}
		sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.sa, el);
		MoveX86regHalfToVariable(x86_EAX, &RSP_Vect[RSPOpC.sa].HW[el], Reg);
	}
}

BOOL Compile_Vector_VXOR_MMX ( void ) {
	char Reg[256];

	/* Do our MMX checks here */
	if (IsMmxEnabled == FALSE)
		return FALSE;
	if ((RSPOpC.rs & 0x0f) >= 2 && (RSPOpC.rs & 0x0f) <= 7 && IsMmx2Enabled == FALSE)
		return FALSE;

	if ((RSPOpC.rs & 0xF) < 2 && (RSPOpC.rd == RSPOpC.rt)) {
		static DWORD VXOR_DynaRegCount = 0;
		MmxXorRegToReg(VXOR_DynaRegCount, VXOR_DynaRegCount);

		sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.sa);
		MmxMoveQwordRegToVariable(VXOR_DynaRegCount, &RSP_Vect[RSPOpC.sa].UHW[0], Reg);
		sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.sa);
		MmxMoveQwordRegToVariable(VXOR_DynaRegCount, &RSP_Vect[RSPOpC.sa].UHW[4], Reg);
		VXOR_DynaRegCount = (VXOR_DynaRegCount + 1) & 7;
	} else {
		sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.rd);
		MmxMoveQwordVariableToReg(x86_MM0, &RSP_Vect[RSPOpC.rd].UHW[0], Reg);
		sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.rd);
		MmxMoveQwordVariableToReg(x86_MM1, &RSP_Vect[RSPOpC.rd].UHW[4], Reg);

		if ((RSPOpC.rs & 0xF) >= 8) {
			RSP_Element2Mmx(x86_MM2);
			MmxXorRegToReg(x86_MM0, x86_MM2);
			MmxXorRegToReg(x86_MM1, x86_MM2);
		} else if ((RSPOpC.rs & 0xF) < 2) {
			sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.rt);
			MmxMoveQwordVariableToReg(x86_MM2, &RSP_Vect[RSPOpC.rt].HW[0], Reg);
			sprintf(Reg, "RSP_Vect[%i].HW[4]", RSPOpC.rt);
			MmxMoveQwordVariableToReg(x86_MM3, &RSP_Vect[RSPOpC.rt].HW[4], Reg);

			MmxXorRegToReg(x86_MM0, x86_MM2);
			MmxXorRegToReg(x86_MM1, x86_MM3);
		} else {
			RSP_MultiElement2Mmx(x86_MM2, x86_MM3);
			MmxXorRegToReg(x86_MM0, x86_MM2);
			MmxXorRegToReg(x86_MM1, x86_MM3);
		}

		sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.sa);
		MmxMoveQwordRegToVariable(x86_MM0, &RSP_Vect[RSPOpC.sa].UHW[0], Reg);
		sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.sa);
		MmxMoveQwordRegToVariable(x86_MM1, &RSP_Vect[RSPOpC.sa].UHW[4], Reg);
	}

	if (IsNextInstructionMmx(CompilePC) == FALSE)
		MmxEmptyMultimediaState();

	return TRUE;
}

void Compile_Vector_VXOR ( void ) {
	#ifdef CompileVxor
		char Reg[256];
		DWORD count;
		BOOL bWriteToAccum = WriteToAccum(Low16BitAccum, CompilePC);

		CPU_Message("  %X %s", CompilePC, RSPOpcodeName(RSPOpC.Hex, CompilePC));

		if (!bWriteToAccum || ((RSPOpC.rs & 0xF) < 2 && RSPOpC.rd == RSPOpC.rt)) {
			if (TRUE == Compile_Vector_VXOR_MMX()) {
				if (bWriteToAccum == TRUE) {
					XorX86RegToX86Reg(x86_EAX, x86_EAX);
					for (count = 0; count < 8; count++) {
						sprintf(Reg, "RSP_ACCUM[%i].HW[1]", count);
						MoveX86regHalfToVariable(x86_EAX, &RSP_ACCUM[count].HW[1], Reg);
					}
				}
				return;
			}
		}
	#endif

	Cheat_r4300iOpcodeNoMessage(RSP_Vector_VXOR, "RSP_Vector_VXOR");
}

BOOL Compile_Vector_VNXOR_MMX ( void ) {
	char Reg[256];

	/* Do our MMX checks here */
	if (IsMmxEnabled == FALSE)
		return FALSE;
	if ((RSPOpC.rs & 0x0f) >= 2 && (RSPOpC.rs & 0x0f) <= 7 && IsMmx2Enabled == FALSE)
		return FALSE;

	if ((RSPOpC.rs & 0xF) < 2 && (RSPOpC.rd == RSPOpC.rt)) {
		static DWORD VNXOR_DynaRegCount = 0;
		MmxPcmpeqwRegToReg(VNXOR_DynaRegCount, VNXOR_DynaRegCount);

		sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.sa);
		MmxMoveQwordRegToVariable(VNXOR_DynaRegCount, &RSP_Vect[RSPOpC.sa].UHW[0], Reg);
		sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.sa);
		MmxMoveQwordRegToVariable(VNXOR_DynaRegCount, &RSP_Vect[RSPOpC.sa].UHW[4], Reg);
		VNXOR_DynaRegCount = (VNXOR_DynaRegCount + 1) & 7;
	} else {
		sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.rd);
		MmxMoveQwordVariableToReg(x86_MM0, &RSP_Vect[RSPOpC.rd].UHW[0], Reg);
		sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.rd);
		MmxMoveQwordVariableToReg(x86_MM1, &RSP_Vect[RSPOpC.rd].UHW[4], Reg);
		MmxPcmpeqwRegToReg(x86_MM7, x86_MM7);

		if ((RSPOpC.rs & 0xF) >= 8) {
			RSP_Element2Mmx(x86_MM2);
			MmxXorRegToReg(x86_MM0, x86_MM2);
			MmxXorRegToReg(x86_MM1, x86_MM2);
		} else if ((RSPOpC.rs & 0xF) < 2) {
			sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.rt);
			MmxMoveQwordVariableToReg(x86_MM2, &RSP_Vect[RSPOpC.rt].HW[0], Reg);
			sprintf(Reg, "RSP_Vect[%i].HW[4]", RSPOpC.rt);
			MmxMoveQwordVariableToReg(x86_MM3, &RSP_Vect[RSPOpC.rt].HW[4], Reg);

			MmxXorRegToReg(x86_MM0, x86_MM2);
			MmxXorRegToReg(x86_MM1, x86_MM3);
		} else {
			RSP_MultiElement2Mmx(x86_MM2, x86_MM3);
			MmxXorRegToReg(x86_MM0, x86_MM2);
			MmxXorRegToReg(x86_MM1, x86_MM3);
		}

		MmxXorRegToReg(x86_MM0, x86_MM7);
		MmxXorRegToReg(x86_MM1, x86_MM7);
		sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.sa);
		MmxMoveQwordRegToVariable(x86_MM0, &RSP_Vect[RSPOpC.sa].UHW[0], Reg);
		sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.sa);
		MmxMoveQwordRegToVariable(x86_MM1, &RSP_Vect[RSPOpC.sa].UHW[4], Reg);
	}

	if (IsNextInstructionMmx(CompilePC) == FALSE)
		MmxEmptyMultimediaState();

	return TRUE;
}

void Compile_Vector_VNXOR ( void ) {
	#ifdef CompileVnxor
		char Reg[256];
		DWORD count;
		BOOL bWriteToAccum = WriteToAccum(Low16BitAccum, CompilePC);

		CPU_Message("  %X %s", CompilePC, RSPOpcodeName(RSPOpC.Hex, CompilePC));

		if (!bWriteToAccum || ((RSPOpC.rs & 0xF) < 2 && RSPOpC.rd == RSPOpC.rt)) {
			if (TRUE == Compile_Vector_VNXOR_MMX()) {
				if (bWriteToAccum == TRUE) {
					OrConstToX86Reg(0xFFFFFFFF, x86_EAX);
					for (count = 0; count < 8; count++) {
						sprintf(Reg, "RSP_ACCUM[%i].HW[1]", count);
						MoveX86regHalfToVariable(x86_EAX, &RSP_ACCUM[count].HW[1], Reg);
					}
				}
				return;
			}
		}
	#endif

	Cheat_r4300iOpcode(RSP_Vector_VNXOR, "RSP_Vector_VNXOR");
}

void Compile_Vector_VRCP ( void ) {
	Cheat_r4300iOpcode(RSP_Vector_VRCP,"RSP_Vector_VRCP");
}

void Compile_Vector_VRCPL ( void ) {
	Cheat_r4300iOpcode(RSP_Vector_VRCPL,"RSP_Vector_VRCPL");
}

void Compile_Vector_VRCPH ( void ) {
	char Reg[256];
	int count, el, last = -1;
	BOOL bWriteToAccum = WriteToAccum(Low16BitAccum, CompilePC);

	#ifndef CompileVrcph
	Cheat_r4300iOpcode(RSP_Vector_VRCPH,"RSP_Vector_VRCPH"); return;
	#endif

	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));

	el = EleSpec[RSPOpC.rs].B[(RSPOpC.rd & 0x7)];
	sprintf(Reg, "RSP_Vect[%i].UHW[%i]", RSPOpC.rt, el);
	MoveVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].UHW[el], Reg, x86_EDX);
	MoveX86regHalfToVariable(x86_EDX, &Recp.UHW[1], "Recp.UHW[1]");
	
	MoveConstHalfToVariable(0, &Recp.UHW[0], "Recp.UHW[0]");
	
	MoveVariableToX86regHalf(&RecpResult.UHW[1], "RecpResult.UHW[1]", x86_ECX);
	el = 7 - (RSPOpC.rd & 0x7);
	sprintf(Reg, "RSP_Vect[%i].UHW[%i]", RSPOpC.sa, el);
	MoveX86regHalfToVariable(x86_ECX, &RSP_Vect[RSPOpC.sa].UHW[el], Reg);

	if (bWriteToAccum == FALSE) return;

	for (count = 0; count < 8; count++) {
		el = EleSpec[RSPOpC.rs].B[count];

		if (el != last) {
			sprintf(Reg, "RSP_Vect[%i].UHW[%i]", RSPOpC.rt, el);
			MoveVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].UHW[el], Reg, x86_EAX);
			last = el;
		}

		sprintf(Reg, "RSP_ACCUM[%i].HW[1]", count);
		MoveX86regHalfToVariable(x86_EAX, &RSP_ACCUM[count].HW[1], Reg);
	}
}

void Compile_Vector_VMOV ( void ) {
	char Reg[256];
	int el, count;
	BOOL bWriteToAccum = WriteToAccum(Low16BitAccum, CompilePC);
#ifndef CompileVmov
	Cheat_r4300iOpcode(RSP_Vector_VMOV, "RSP_Vector_VMOV"); return;
#endif

	CPU_Message("  %X %s", CompilePC, RSPOpcodeName(RSPOpC.Hex, CompilePC));

	if (bWriteToAccum){
		for (count = 0; count < 8; count++) {
			sprintf(Reg, "RSP_Vect[%i].UHW[%i]", RSPOpC.rt, EleSpec[RSPOpC.rs].B[count]);
			MoveVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].UHW[EleSpec[RSPOpC.rs].B[count]], Reg, x86_EAX);
			sprintf(Reg, "RSP_ACCUM[%i].HW[1]", count);
			MoveX86regHalfToVariable(x86_EAX, &RSP_ACCUM[count].HW[1], Reg);
		}
	}

	el = EleSpec[RSPOpC.rs].B[(RSPOpC.rd & 0x7)];
	sprintf(Reg, "RSP_Vect[%i].UHW[%i]", RSPOpC.rt, el);

	MoveVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].UHW[el], Reg, x86_ECX);

	el = 7 - (RSPOpC.rd & 0x7);
	sprintf(Reg, "RSP_Vect[%i].UHW[%i]", RSPOpC.sa, el);

	MoveX86regHalfToVariable(x86_ECX, &RSP_Vect[RSPOpC.sa].UHW[el], Reg);
}

void Compile_Vector_VRSQ ( void ) {
	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));
	Cheat_r4300iOpcodeNoMessage(RSP_Vector_VRSQ,"RSP_Vector_VRSQ");
}

void Compile_Vector_VRSQL ( void ) {
	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));
	Cheat_r4300iOpcodeNoMessage(RSP_Vector_VRSQL,"RSP_Vector_VRSQL");
}

void Compile_Vector_VRSQH ( void ) {
	char Reg[256];
	int count, el;

	#ifndef CompileVrsqh
	Cheat_r4300iOpcode(RSP_Vector_VRSQH,"RSP_Vector_VRSQH"); return;
	#endif

	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));
	
	el = EleSpec[RSPOpC.rs].B[(RSPOpC.rd & 0x7)];
	sprintf(Reg, "RSP_Vect[%i].UHW[%i]", RSPOpC.rt, el);
	MoveVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].UHW[el], Reg, x86_EDX);
	MoveX86regHalfToVariable(x86_EDX, &SQroot.UHW[1], "SQroot.UHW[1]");

	MoveVariableToX86regHalf(&SQrootResult.UHW[1], "SQrootResult.UHW[1]", x86_ECX);
	el = 7 - (RSPOpC.rd & 0x7);
	sprintf(Reg, "RSP_Vect[%i].UHW[%i]", RSPOpC.sa, el);
	MoveX86regHalfToVariable(x86_ECX, &RSP_Vect[RSPOpC.sa].UHW[el], Reg);

	for (count = 0; count < 8; count++) {
		el = EleSpec[RSPOpC.rs].B[count];
		sprintf(Reg, "RSP_Vect[%i].UHW[%i]", RSPOpC.rt, el);
		MoveVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].UHW[el], Reg, x86_EAX);

		sprintf(Reg, "RSP_ACCUM[%i].HW[1]", count);
		MoveX86regHalfToVariable(x86_EAX, &RSP_ACCUM[count].HW[1], Reg);
	}
}

void Compile_Vector_VNOOP ( void ) {

}

/************************** lc2 functions **************************/

void Compile_Opcode_LBV ( void ) {
	Cheat_r4300iOpcode(RSP_Opcode_LBV,"RSP_Opcode_LBV");
}

void Compile_Opcode_LSV ( void ) {
	char Reg[256];
	int offset = (RSPOpC.voffset << 1);

	if (RSPOpC.del > 14) {
		rsp_UnknownOpcode();
		return;
	}

	#ifndef CompileLsv
	Cheat_r4300iOpcode(RSP_Opcode_LSV,"RSP_Opcode_LSV"); return;
	#endif

	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));
	
	if (IsRegConst(RSPOpC.base) == TRUE) {
		DWORD Addr = (MipsRegConst(RSPOpC.base) + offset) & 0xfff;

		if ((Addr & 1) != 0) {
			sprintf(Reg, "Dmem + %Xh", (Addr + 0) ^ 3);
			MoveVariableToX86regByte(RSPInfo.DMEM + ((Addr + 0) ^ 3), Reg, x86_ECX);
			sprintf(Reg, "Dmem + %Xh", (Addr + 1) ^ 3);
			MoveVariableToX86regByte(RSPInfo.DMEM + ((Addr + 1) ^ 3), Reg, x86_EDX);

			sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rt, 15 - (RSPOpC.del + 0));
			MoveX86regByteToVariable(x86_ECX, &RSP_Vect[RSPOpC.rt].B[15 - (RSPOpC.del + 0)], Reg);
			sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rt, 15 - (RSPOpC.del + 1));
			MoveX86regByteToVariable(x86_EDX, &RSP_Vect[RSPOpC.rt].B[15 - (RSPOpC.del + 1)], Reg);
		} else {
			sprintf(Reg, "Dmem + %Xh", Addr ^ 2);
			MoveVariableToX86regHalf(RSPInfo.DMEM + (Addr ^ 2), Reg, x86_EDX);
			sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rt, 15 - (RSPOpC.del + 1));
			MoveX86regHalfToVariable(x86_EDX, &RSP_Vect[RSPOpC.rt].B[15 - (RSPOpC.del + 1)], Reg);
		}
		return;
	}
	
	MoveVariableToX86reg(&RSP_GPR[RSPOpC.base].UW, GPR_Name(RSPOpC.base), x86_EBX);
	if (offset != 0) AddConstToX86Reg(x86_EBX, offset);
	AndConstToX86Reg(x86_EBX, 0x0FFF);

	if (Compiler.bAlignVector == TRUE) {
		XorConstToX86Reg(x86_EBX, 2);
		MoveN64MemToX86regHalf(x86_ECX, x86_EBX);
		sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rt, 15 - (RSPOpC.del + 1));
		MoveX86regHalfToVariable(x86_ECX, &RSP_Vect[RSPOpC.rt].B[15 - (RSPOpC.del + 1)], Reg);
	} else {
		LeaSourceAndOffset(x86_EAX, x86_EBX, 1);
		XorConstToX86Reg(x86_EBX, 3);
		XorConstToX86Reg(x86_EAX, 3);

		MoveN64MemToX86regByte(x86_ECX, x86_EBX);
		MoveN64MemToX86regByte(x86_EDX, x86_EAX);

		sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rt, 15 - (RSPOpC.del + 0));
		MoveX86regByteToVariable(x86_ECX, &RSP_Vect[RSPOpC.rt].B[15 - (RSPOpC.del + 0)], Reg);

		sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rt, 15 - (RSPOpC.del + 1));
		MoveX86regByteToVariable(x86_EDX, &RSP_Vect[RSPOpC.rt].B[15 - (RSPOpC.del + 1)], Reg);
	}
}

void Compile_Opcode_LLV ( void ) {
	char Reg[256];
	int offset = (RSPOpC.voffset << 2);
	BYTE * Jump[2];

	#ifndef CompileLlv
	Cheat_r4300iOpcode(RSP_Opcode_LLV,"RSP_Opcode_LLV"); return;
	#endif
	
	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));

	if ((RSPOpC.del & 0x3) != 0) {
		Cheat_r4300iOpcode(RSP_Opcode_LLV,"RSP_Opcode_LLV"); return;
		return;
	}

 	if (IsRegConst(RSPOpC.base) == TRUE) {
		DWORD Addr = (MipsRegConst(RSPOpC.base) + offset) & 0xfff;

		if ((Addr & 3) != 0) {
			CompilerWarning("Unaligned LLV at constant address");
			Cheat_r4300iOpcodeNoMessage(RSP_Opcode_LLV,"RSP_Opcode_LLV");
			return;
		}

		sprintf(Reg, "Dmem + %Xh", Addr);
		MoveVariableToX86reg(RSPInfo.DMEM + Addr, Reg, x86_EAX);
		sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rt, 16 - RSPOpC.del - 4);
		MoveX86regToVariable(x86_EAX, &RSP_Vect[RSPOpC.rt].B[16 - RSPOpC.del - 4], Reg);
		return;
	}
	
	MoveVariableToX86reg(&RSP_GPR[RSPOpC.base].UW, GPR_Name(RSPOpC.base), x86_EBX);
	if (offset != 0) AddConstToX86Reg(x86_EBX, offset);
	
	TestConstToX86Reg(3, x86_EBX);
	JneLabel32("Unaligned", 0);
	Jump[0] = RecompPos - 4;

	/*
	 * Unaligned
	 */
	CompilerToggleBuffer();

	CPU_Message("   Unaligned:");
	*((DWORD *)(Jump[0]))=(DWORD)(RecompPos - Jump[0] - 4);
	Cheat_r4300iOpcodeNoMessage(RSP_Opcode_LLV,"RSP_Opcode_LLV");
	JmpLabel32("Done", 0);
	Jump[1] = RecompPos - 4;

	CompilerToggleBuffer();

	/*
	 * Aligned
	 */
	AndConstToX86Reg(x86_EBX, 0x0fff);
	MoveN64MemToX86reg(x86_EAX, x86_EBX);
	/* Because of byte swapping this swizzle works nicely */
	sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rt, 16 - RSPOpC.del - 4);
	MoveX86regToVariable(x86_EAX, &RSP_Vect[RSPOpC.rt].B[16 - RSPOpC.del - 4], Reg);

	CPU_Message("   Done:");
	*((DWORD *)(Jump[1]))=(DWORD)(RecompPos - Jump[1] - 4);
}

void Compile_Opcode_LDV ( void ) {
	char Reg[256];
	int offset = (RSPOpC.voffset << 3), length;
	BYTE * Jump[2], * LoopEntry;

	#ifndef CompileLdv
	Cheat_r4300iOpcode(RSP_Opcode_LDV,"RSP_Opcode_LDV"); return;
	#endif

	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));

	/* FIXME: Conker's hits this */
	//if ((RSPOpC.del & 0x7) != 0) {
	//	rsp_UnknownOpcode();
	//	return;
	//}
	if ((RSPOpC.del & 0x3) != 0) {
		CompilerWarning("LDV's element = %X, PC = %04X", RSPOpC.del, CompilePC);
		Cheat_r4300iOpcodeNoMessage(RSP_Opcode_LDV,"RSP_Opcode_LDV");
		return;
	}

	if (IsRegConst(RSPOpC.base) == TRUE) {
		DWORD Addr = (MipsRegConst(RSPOpC.base) + offset) & 0xfff;

		if ((Addr & 3) != 0) {
			CompilerWarning("Unaligned LDV at constant address PC = %04X", CompilePC);
			Cheat_r4300iOpcodeNoMessage(RSP_Opcode_LDV,"RSP_Opcode_LDV");
			return;
		}

		sprintf(Reg, "Dmem + %Xh", Addr);
		MoveVariableToX86reg(RSPInfo.DMEM + Addr + 0, Reg, x86_EAX);
		sprintf(Reg, "Dmem + %Xh", Addr + 4);
		MoveVariableToX86reg(RSPInfo.DMEM + Addr + 4, Reg, x86_ECX);

		sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rt, 16 - RSPOpC.del - 4);
		MoveX86regToVariable(x86_EAX, &RSP_Vect[RSPOpC.rt].B[16 - RSPOpC.del - 4], Reg);
		if(RSPOpC.del != 12){
			sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rt, 16 - RSPOpC.del - 8);
			MoveX86regToVariable(x86_ECX, &RSP_Vect[RSPOpC.rt].B[16 - RSPOpC.del - 8], Reg);
		}
		return;
	}
	
	MoveVariableToX86reg(&RSP_GPR[RSPOpC.base].UW, GPR_Name(RSPOpC.base), x86_EBX);
	if (offset != 0) {
		AddConstToX86Reg(x86_EBX, offset);
	}
	AndConstToX86Reg(x86_EBX, 0x0fff);
	TestConstToX86Reg(3, x86_EBX);
	JneLabel32("Unaligned", 0);
	Jump[0] = RecompPos - 4;

	CompilerToggleBuffer();
	CPU_Message("   Unaligned:");
	x86_SetBranch32b(Jump[0], RecompPos);
	sprintf(Reg, "RSP_Vect[%i].UB[%i]", RSPOpC.rt, 15 - RSPOpC.del);
	MoveOffsetToX86reg((DWORD)&RSP_Vect[RSPOpC.rt].UB[15 - RSPOpC.del], Reg, x86_EDI);
	length = 8;
	if(RSPOpC.del == 12){
		length = 4;
	}
	MoveConstToX86reg(length, x86_ECX);

/*    mov eax, ebx
      dec edi
      xor eax, 3h
      inc ebx
      mov dl, byte ptr [eax+Dmem]
      dec ecx
      mov byte ptr [edi+1], dl      
      jne $Loop */

	LoopEntry = RecompPos;
	CPU_Message("   Loop:");	
	MoveX86RegToX86Reg(x86_EBX, x86_EAX);
	XorConstToX86Reg(x86_EAX, 3);
	MoveN64MemToX86regByte(x86_EDX, x86_EAX);
	MoveX86regByteToX86regPointer(x86_EDX, x86_EDI);
	IncX86reg(x86_EBX); /* address constant */
	DecX86reg(x86_EDI); /* vector pointer */
	DecX86reg(x86_ECX); /* counter */
	JneLabel8("Loop", 0);
	x86_SetBranch8b(RecompPos - 1, LoopEntry);

	JmpLabel32("Done", 0);
	Jump[1] = RecompPos - 4;
	CompilerToggleBuffer();

	MoveN64MemToX86reg(x86_EAX, x86_EBX);
	MoveN64MemDispToX86reg(x86_ECX, x86_EBX, 4);
	
	/* Because of byte swapping this swizzle works nicely */
	sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rt, 16 - RSPOpC.del - 4);
	MoveX86regToVariable(x86_EAX, &RSP_Vect[RSPOpC.rt].B[16 - RSPOpC.del - 4], Reg);
	if(RSPOpC.del != 12){
		sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rt, 16 - RSPOpC.del - 8);
		MoveX86regToVariable(x86_ECX, &RSP_Vect[RSPOpC.rt].B[16 - RSPOpC.del - 8], Reg);
	}
	CPU_Message("   Done:");
	x86_SetBranch32b(Jump[1], RecompPos);
}

void Compile_Opcode_LQV ( void ) {
	char Reg[256];
	int offset = (RSPOpC.voffset << 4);
	BYTE * Jump[2];

	#ifndef CompileLqv
	Cheat_r4300iOpcode(RSP_Opcode_LQV,"RSP_Opcode_LQV"); return;
	#endif
	
	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));

	if (RSPOpC.del != 0) {
		Cheat_r4300iOpcode(RSP_Opcode_LQV,"RSP_Opcode_LQV"); return;
		return;
	}

	if (IsRegConst(RSPOpC.base) == TRUE) {
		DWORD Addr = (MipsRegConst(RSPOpC.base) + offset) & 0xfff;

		if (Addr & 15) {
			CompilerWarning("Unaligned LQV at constant address PC = %04X", CompilePC);
			Cheat_r4300iOpcodeNoMessage(RSP_Opcode_LQV,"RSP_Opcode_LQV");
			return;
		}
	
		/*
		 * Aligned store
		 */

		if (IsSseEnabled == FALSE) {
			sprintf(Reg, "Dmem+%Xh+0", Addr);
			MoveVariableToX86reg(RSPInfo.DMEM + Addr + 0, Reg, x86_EAX);
			sprintf(Reg, "Dmem+%Xh+4", Addr);
			MoveVariableToX86reg(RSPInfo.DMEM + Addr + 4, Reg, x86_EBX);
			sprintf(Reg, "Dmem+%Xh+8", Addr);
			MoveVariableToX86reg(RSPInfo.DMEM + Addr + 8, Reg, x86_ECX);
			sprintf(Reg, "Dmem+%Xh+C", Addr);
			MoveVariableToX86reg(RSPInfo.DMEM + Addr + 12, Reg, x86_EDX);

			sprintf(Reg, "RSP_Vect[%i].B[12]", RSPOpC.rt);
			MoveX86regToVariable(x86_EAX, &RSP_Vect[RSPOpC.rt].B[12], Reg);
			sprintf(Reg, "RSP_Vect[%i].B[8]", RSPOpC.rt);
			MoveX86regToVariable(x86_EBX, &RSP_Vect[RSPOpC.rt].B[8], Reg);
			sprintf(Reg, "RSP_Vect[%i].B[4]", RSPOpC.rt);
			MoveX86regToVariable(x86_ECX, &RSP_Vect[RSPOpC.rt].B[4], Reg);
			sprintf(Reg, "RSP_Vect[%i].B[0]", RSPOpC.rt);
			MoveX86regToVariable(x86_EDX, &RSP_Vect[RSPOpC.rt].B[0], Reg);
		} else {
			sprintf(Reg, "Dmem+%Xh", Addr);
			SseMoveUnalignedVariableToReg(RSPInfo.DMEM + Addr, Reg, x86_XMM0);
			SseShuffleReg(x86_XMM0, x86_MM0, 0x1b);
			sprintf(Reg, "RSP_Vect[%i].B[0]", RSPOpC.rt);
			SseMoveAlignedRegToVariable(x86_XMM0, &RSP_Vect[RSPOpC.rt].B[0], Reg);
		}
		return;
	}

	MoveVariableToX86reg(&RSP_GPR[RSPOpC.base].UW, GPR_Name(RSPOpC.base), x86_EBX);
	if (offset != 0) {
		AddConstToX86Reg(x86_EBX, offset);
	}
	TestConstToX86Reg(15, x86_EBX);
	JneLabel32("Unaligned", 0);
	Jump[0] = RecompPos - 4;

	CompilerToggleBuffer();
	CPU_Message("   Unaligned:");
	x86_SetBranch32b(Jump[0], RecompPos);

	Cheat_r4300iOpcodeNoMessage(RSP_Opcode_LQV,"RSP_Opcode_LQV");
	JmpLabel32("Done", 0);
	Jump[1] = RecompPos - 4;
	CompilerToggleBuffer();

	AndConstToX86Reg(x86_EBX, 0x0fff);
	if (IsSseEnabled == FALSE) {
		MoveN64MemDispToX86reg(x86_EAX, x86_EBX, 0);
		MoveN64MemDispToX86reg(x86_ECX, x86_EBX, 4);
		MoveN64MemDispToX86reg(x86_EDX, x86_EBX, 8);
		MoveN64MemDispToX86reg(x86_EDI, x86_EBX, 12);

		sprintf(Reg, "RSP_Vect[%i].B[12]", RSPOpC.rt);
		MoveX86regToVariable(x86_EAX, &RSP_Vect[RSPOpC.rt].B[12], Reg);
		sprintf(Reg, "RSP_Vect[%i].B[8]", RSPOpC.rt);
		MoveX86regToVariable(x86_ECX, &RSP_Vect[RSPOpC.rt].B[8], Reg);
		sprintf(Reg, "RSP_Vect[%i].B[4]", RSPOpC.rt);
		MoveX86regToVariable(x86_EDX, &RSP_Vect[RSPOpC.rt].B[4], Reg);
		sprintf(Reg, "RSP_Vect[%i].B[0]", RSPOpC.rt);
		MoveX86regToVariable(x86_EDI, &RSP_Vect[RSPOpC.rt].B[0], Reg);
	} else {
		SseMoveUnalignedN64MemToReg(x86_XMM0, x86_EBX);
		SseShuffleReg(x86_XMM0, x86_MM0, 0x1b);
		sprintf(Reg, "RSP_Vect[%i].B[0]", RSPOpC.rt);
		SseMoveAlignedRegToVariable(x86_XMM0, &RSP_Vect[RSPOpC.rt].B[0], Reg);
	}
	CPU_Message("   Done:");
	x86_SetBranch32b((DWORD*)Jump[1], (DWORD*)RecompPos);
}

void Compile_Opcode_LRV ( void ) {
	int offset = (RSPOpC.voffset << 4);
	BYTE * Loop, * Jump[2];

	#ifndef CompileLrv
	Cheat_r4300iOpcode(RSP_Opcode_LRV,"RSP_Opcode_LRV"); return;
	#endif

	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));

	if (RSPOpC.del != 0) {
		rsp_UnknownOpcode();
		return;
	}

	MoveVariableToX86reg(&RSP_GPR[RSPOpC.base].UW, GPR_Name(RSPOpC.base), x86_EBX);
	if (offset != 0) AddConstToX86Reg(x86_EBX, offset);

	if (Compiler.bAlignVector == FALSE) {
		TestConstToX86Reg(1, x86_EBX);
		JneLabel32("Unaligned", 0);
		Jump[0] = RecompPos - 4;

		/* Unaligned */
		CompilerToggleBuffer();

		CPU_Message(" Unaligned:");
		x86_SetBranch32b(Jump[0], RecompPos);

		Cheat_r4300iOpcodeNoMessage(RSP_Opcode_LRV,"RSP_Opcode_LRV");
		JmpLabel32("Done", 0);
		Jump[1] = RecompPos - 4;

		CompilerToggleBuffer();
	}

	/* Aligned */
	MoveX86RegToX86Reg(x86_EBX, x86_EAX);
	AndConstToX86Reg(x86_EAX, 0x0F);
	AndConstToX86Reg(x86_EBX, 0x0ff0);

	MoveX86RegToX86Reg(x86_EAX, x86_ECX);
	ShiftRightUnsignImmed(x86_ECX, 1);

	JeLabel8("Done", 0);
	Jump[0] = RecompPos - 1;
/*
	DecX86reg(x86_EAX);
	LeaSourceAndOffset(x86_EAX, x86_EAX, (DWORD) &RSP_Vect[RSPOpC.rt].B[0]);
	DecX86reg(x86_EAX);
*/
	AddConstToX86Reg(x86_EAX, ((DWORD)&RSP_Vect[RSPOpC.rt].UB[0]) - 2);

	CPU_Message("   Loop:");
	Loop = RecompPos;

	MoveX86RegToX86Reg(x86_EBX, x86_ESI);
	XorConstToX86Reg(x86_ESI, 2);
	MoveN64MemToX86regHalf(x86_EDX, x86_ESI);
	MoveX86regHalfToX86regPointer(x86_EDX, x86_EAX);

	AddConstToX86Reg(x86_EBX, 2);	/* Dmem pointer	*/
	SubConstFromX86Reg(x86_EAX, 2);	/* Vector pointer */	
	DecX86reg(x86_ECX);				/* Loop counter	*/
	JneLabel8("Loop", 0);
	x86_SetBranch8b(RecompPos - 1, Loop);

	if (Compiler.bAlignVector == FALSE) {
		CPU_Message("   Done:");
		x86_SetBranch32b((DWORD*)Jump[1], (DWORD*)RecompPos);
	}

	x86_SetBranch8b(Jump[0], RecompPos);
}

void Compile_Opcode_LPV ( void ) {
	Cheat_r4300iOpcode(RSP_Opcode_LPV,"RSP_Opcode_LPV");
}

void Compile_Opcode_LUV ( void ) {
	Cheat_r4300iOpcode(RSP_Opcode_LUV,"RSP_Opcode_LUV");
}


void Compile_Opcode_LHV ( void ) {
	Cheat_r4300iOpcode(RSP_Opcode_LHV,"RSP_Opcode_LHV");
}


void Compile_Opcode_LFV ( void ) {
	Cheat_r4300iOpcode(RSP_Opcode_LFV,"RSP_Opcode_LFV");
}

void Compile_Opcode_LTV ( void ) {
	Cheat_r4300iOpcode(RSP_Opcode_LTV,"RSP_Opcode_LTV");
}

/************************** sc2 functions **************************/

void Compile_Opcode_SBV ( void ) {
	Cheat_r4300iOpcode(RSP_Opcode_SBV,"RSP_Opcode_SBV");
}

void Compile_Opcode_SSV ( void ) {
	char Reg[256];
	int offset = (RSPOpC.voffset << 1);

	if (RSPOpC.del > 14) {
		rsp_UnknownOpcode();
		return;
	}

	#ifndef CompileSsv
	Cheat_r4300iOpcode(RSP_Opcode_SSV,"RSP_Opcode_SSV"); return;
	#endif
	
	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));

	if (IsRegConst(RSPOpC.base) == TRUE) {
		DWORD Addr = (MipsRegConst(RSPOpC.base) + offset) & 0xfff;

		if ((Addr & 1) != 0) {
			sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rt, 15 - (RSPOpC.del + 0));
			MoveVariableToX86regByte(&RSP_Vect[RSPOpC.rt].B[15 - (RSPOpC.del + 0)], Reg, x86_ECX);
			sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rt, 15 - (RSPOpC.del + 1));
			MoveVariableToX86regByte(&RSP_Vect[RSPOpC.rt].B[15 - (RSPOpC.del + 1)], Reg, x86_EDX);

			sprintf(Reg, "Dmem + %Xh", (Addr + 0) ^ 3);
			MoveX86regByteToVariable(x86_ECX, RSPInfo.DMEM + ((Addr + 0) ^ 3), Reg);
			sprintf(Reg, "Dmem + %Xh", (Addr + 1) ^ 3);
			MoveX86regByteToVariable(x86_EDX, RSPInfo.DMEM + ((Addr + 1) ^ 3), Reg);
		} else {
			sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rt, 15 - (RSPOpC.del + 1));
			MoveVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].B[15 - (RSPOpC.del + 1)], Reg, x86_ECX);
			sprintf(Reg, "Dmem + %Xh", Addr ^ 2);
			MoveX86regHalfToVariable(x86_ECX, RSPInfo.DMEM + (Addr ^ 2), Reg);
		}
		return;
	}

	MoveVariableToX86reg(&RSP_GPR[RSPOpC.base].UW, GPR_Name(RSPOpC.base), x86_EBX);
	if (offset != 0) AddConstToX86Reg(x86_EBX, offset);
	AndConstToX86Reg(x86_EBX, 0x0FFF);

	if (Compiler.bAlignVector == TRUE) {
		sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rt, 15 - (RSPOpC.del + 1));
		MoveVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].B[15 - (RSPOpC.del + 1)], Reg, x86_ECX);
		XorConstToX86Reg(x86_EBX, 2);
		MoveX86regHalfToN64Mem(x86_ECX, x86_EBX);		
	} else {
		LeaSourceAndOffset(x86_EAX, x86_EBX, 1);
		XorConstToX86Reg(x86_EBX, 3);
		XorConstToX86Reg(x86_EAX, 3);

		sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rt, 15 - (RSPOpC.del + 0));
		MoveVariableToX86regByte(&RSP_Vect[RSPOpC.rt].B[15 - (RSPOpC.del + 0)], Reg, x86_ECX);
		sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rt, 15 - (RSPOpC.del + 1));
		MoveVariableToX86regByte(&RSP_Vect[RSPOpC.rt].B[15 - (RSPOpC.del + 1)], Reg, x86_EDX);

		MoveX86regByteToN64Mem(x86_ECX, x86_EBX);
		MoveX86regByteToN64Mem(x86_EDX, x86_EAX);
	}
}

void Compile_Opcode_SLV ( void ) {
	char Reg[256];
	int offset = (RSPOpC.voffset << 2);
	BYTE * Jump[2];

	#ifndef CompileSlv
	Cheat_r4300iOpcode(RSP_Opcode_SLV,"RSP_Opcode_SLV"); return;
	#endif

	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));

//	if ((RSPOpC.del & 0x3) != 0) {
//		rsp_UnknownOpcode();
//		return;
//	}

 	if (IsRegConst(RSPOpC.base) == TRUE) {
		DWORD Addr = (MipsRegConst(RSPOpC.base) + offset) & 0xfff;

		if ((Addr & 3) != 0) {
			CompilerWarning("Unaligned SLV at constant address");
			Cheat_r4300iOpcodeNoMessage(RSP_Opcode_SLV,"RSP_Opcode_SLV");
			return;
		}

		sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rt, 16 - RSPOpC.del - 4);
		MoveVariableToX86reg(&RSP_Vect[RSPOpC.rt].B[16 - RSPOpC.del - 4], Reg, x86_EAX);
		sprintf(Reg, "Dmem + %Xh", Addr);
		MoveX86regToVariable(x86_EAX, RSPInfo.DMEM + Addr, Reg);
		return;
	}
	
	MoveVariableToX86reg(&RSP_GPR[RSPOpC.base].UW, GPR_Name(RSPOpC.base), x86_EBX);
	if (offset != 0) AddConstToX86Reg(x86_EBX, offset);
	
	TestConstToX86Reg(3, x86_EBX);
	JneLabel32("Unaligned", 0);
	Jump[0] = RecompPos - 4;

	/*
	 * Unaligned
	 */
	CompilerToggleBuffer();

	CPU_Message("   Unaligned:");
	*((DWORD *)(Jump[0]))=(DWORD)(RecompPos - Jump[0] - 4);
	Cheat_r4300iOpcodeNoMessage(RSP_Opcode_SLV,"RSP_Opcode_SLV");
	JmpLabel32("Done", 0);
	Jump[1] = RecompPos - 4;

	CompilerToggleBuffer();

	/*
	 * Aligned
	 */

	/* Because of byte swapping this swizzle works nicely */
	sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rt, 16 - RSPOpC.del - 4);
	MoveVariableToX86reg(&RSP_Vect[RSPOpC.rt].B[16 - RSPOpC.del - 4], Reg, x86_EAX);
	
	AndConstToX86Reg(x86_EBX, 0x0fff);
	MoveX86regToN64Mem(x86_EAX, x86_EBX);

	CPU_Message("   Done:");
	*((DWORD *)(Jump[1]))=(DWORD)(RecompPos - Jump[1] - 4);
}

void Compile_Opcode_SDV ( void ) {
	char Reg[256];
	int offset = (RSPOpC.voffset << 3);
	BYTE * Jump[2], * LoopEntry;

	//if ((RSPOpC.del & 0x7) != 0) {
	//	rsp_UnknownOpcode();
	//	return;
	//}

#ifndef CompileSdv
	Cheat_r4300iOpcode(RSP_Opcode_SDV, "RSP_Opcode_SDV"); return;
#endif

	CPU_Message("  %X %s", CompilePC, RSPOpcodeName(RSPOpC.Hex, CompilePC));

	if (IsRegConst(RSPOpC.base) == TRUE) {
		DWORD Addr = (MipsRegConst(RSPOpC.base) + offset) & 0xfff;

		if ((Addr & 3) != 0) {
			CompilerWarning("Unaligned SDV at constant address PC = %04X", CompilePC);
			Cheat_r4300iOpcodeNoMessage(RSP_Opcode_SDV, "RSP_Opcode_SDV");
			return;
		}

		sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rt, (16 - RSPOpC.del - 4) & 0xF);
		MoveVariableToX86reg(&RSP_Vect[RSPOpC.rt].B[(16 - RSPOpC.del - 4) & 0xF], Reg, x86_EAX);
		sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rt, (16 - RSPOpC.del - 8) & 0xF);
		MoveVariableToX86reg(&RSP_Vect[RSPOpC.rt].B[(16 - RSPOpC.del - 8) & 0xF], Reg, x86_EBX);

		sprintf(Reg, "Dmem + %Xh", Addr);
		MoveX86regToVariable(x86_EAX, RSPInfo.DMEM + Addr, Reg);
		sprintf(Reg, "Dmem + %Xh", Addr + 4);
		MoveX86regToVariable(x86_EBX, RSPInfo.DMEM + Addr + 4, Reg);
		return;
	}

	MoveVariableToX86reg(&RSP_GPR[RSPOpC.base].UW, GPR_Name(RSPOpC.base), x86_EBX);
	if (offset != 0) {
		AddConstToX86Reg(x86_EBX, offset);
	}
	AndConstToX86Reg(x86_EBX, 0x0fff);
	TestConstToX86Reg(3, x86_EBX);
	JneLabel32("Unaligned", 0);
	Jump[0] = RecompPos - 4;

	CompilerToggleBuffer();
	CPU_Message("   Unaligned:");
	x86_SetBranch32b((DWORD*)Jump[0], (DWORD*)RecompPos);

	sprintf(Reg, "RSP_Vect[%i].UB[%i]", RSPOpC.rt, 15 - RSPOpC.del);
	MoveOffsetToX86reg((DWORD)&RSP_Vect[RSPOpC.rt].UB[15 - RSPOpC.del], Reg, x86_EDI);
	MoveConstToX86reg(8, x86_ECX);

	CPU_Message("   Loop:");
	LoopEntry = RecompPos;
	MoveX86RegToX86Reg(x86_EBX, x86_EAX);
	XorConstToX86Reg(x86_EAX, 3);
	MoveX86regPointerToX86regByte(x86_EDX, x86_EDI);
	MoveX86regByteToN64Mem(x86_EDX, x86_EAX);
	IncX86reg(x86_EBX); /* address constant */
	DecX86reg(x86_EDI); /* vector pointer */
	DecX86reg(x86_ECX); /* counter */
	JneLabel8("Loop", 0);
	x86_SetBranch8b(RecompPos - 1, LoopEntry);

	JmpLabel32("Done", 0);
	Jump[1] = RecompPos - 4;
	CompilerToggleBuffer();

	sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rt, (16 - RSPOpC.del - 4) & 0xF);
	MoveVariableToX86reg(&RSP_Vect[RSPOpC.rt].B[(16 - RSPOpC.del - 4) & 0xF], Reg, x86_EAX);
	sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rt, (16 - RSPOpC.del - 8) & 0xF);
	MoveVariableToX86reg(&RSP_Vect[RSPOpC.rt].B[(16 - RSPOpC.del - 8) & 0xF], Reg, x86_ECX);
	MoveX86regToN64Mem(x86_EAX, x86_EBX);
	MoveX86regToN64MemDisp(x86_ECX, x86_EBX, 4);

	CPU_Message("   Done:");
	x86_SetBranch32b((DWORD*)Jump[1], (DWORD*)RecompPos);
}

void Compile_Opcode_SQV ( void ) {
	char Reg[256];
	int offset = (RSPOpC.voffset << 4);
	BYTE * Jump[2];

	#ifndef CompileSqv
 	Cheat_r4300iOpcode(RSP_Opcode_SQV,"RSP_Opcode_SQV"); return;
	#endif

	CPU_Message("  %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC));

	if (RSPOpC.del != 0 && RSPOpC.del != 12) {
		rsp_UnknownOpcode();
		return;
	}

	if (IsRegConst(RSPOpC.base) == TRUE) {
		DWORD Addr = (MipsRegConst(RSPOpC.base) + offset) & 0xfff;

		if (Addr & 15) {
			CompilerWarning("Unaligned SQV at constant address %04X", CompilePC);
			Cheat_r4300iOpcodeNoMessage(RSP_Opcode_SQV,"RSP_Opcode_SQV");
			return;
		}
	
		/*
		 * Aligned store
		 */

		if (IsSseEnabled == FALSE) {
			if (RSPOpC.del == 12) {
				sprintf(Reg, "RSP_Vect[%i].B[0]", RSPOpC.rt);
				MoveVariableToX86reg(&RSP_Vect[RSPOpC.rt].B[0], Reg, x86_EAX);
				sprintf(Reg, "RSP_Vect[%i].B[12]", RSPOpC.rt);
				MoveVariableToX86reg(&RSP_Vect[RSPOpC.rt].B[12], Reg, x86_EBX);
				sprintf(Reg, "RSP_Vect[%i].B[8]", RSPOpC.rt);
				MoveVariableToX86reg(&RSP_Vect[RSPOpC.rt].B[8], Reg, x86_ECX);
				sprintf(Reg, "RSP_Vect[%i].B[4]", RSPOpC.rt);
				MoveVariableToX86reg(&RSP_Vect[RSPOpC.rt].B[4], Reg, x86_EDX);
			} else {
				sprintf(Reg, "RSP_Vect[%i].B[12]", RSPOpC.rt);
				MoveVariableToX86reg(&RSP_Vect[RSPOpC.rt].B[12], Reg, x86_EAX);
				sprintf(Reg, "RSP_Vect[%i].B[8]", RSPOpC.rt);
				MoveVariableToX86reg(&RSP_Vect[RSPOpC.rt].B[8], Reg, x86_EBX);
				sprintf(Reg, "RSP_Vect[%i].B[4]", RSPOpC.rt);
				MoveVariableToX86reg(&RSP_Vect[RSPOpC.rt].B[4], Reg, x86_ECX);
				sprintf(Reg, "RSP_Vect[%i].B[0]", RSPOpC.rt);
				MoveVariableToX86reg(&RSP_Vect[RSPOpC.rt].B[0], Reg, x86_EDX);
			}

			sprintf(Reg, "Dmem+%Xh+0", Addr);
			MoveX86regToVariable(x86_EAX, RSPInfo.DMEM + Addr + 0, Reg);
			sprintf(Reg, "Dmem+%Xh+4", Addr);
			MoveX86regToVariable(x86_EBX, RSPInfo.DMEM + Addr + 4, Reg);
			sprintf(Reg, "Dmem+%Xh+8", Addr);
			MoveX86regToVariable(x86_ECX, RSPInfo.DMEM + Addr + 8, Reg);
			sprintf(Reg, "Dmem+%Xh+C", Addr);
			MoveX86regToVariable(x86_EDX, RSPInfo.DMEM + Addr + 12, Reg);
		} else {
			sprintf(Reg, "RSP_Vect[%i].B[0]", RSPOpC.rt);
			SseMoveAlignedVariableToReg(&RSP_Vect[RSPOpC.rt].B[0], Reg, x86_XMM0);
			if (RSPOpC.del == 12) {
				SseShuffleReg(x86_XMM0, x86_MM0, 0x6c);
			} else {
				SseShuffleReg(x86_XMM0, x86_MM0, 0x1b);
			}
			sprintf(Reg, "Dmem+%Xh", Addr);
			SseMoveUnalignedRegToVariable(x86_XMM0, RSPInfo.DMEM + Addr, Reg);
		}
		return;
	}
	
	MoveVariableToX86reg(&RSP_GPR[RSPOpC.base].UW, GPR_Name(RSPOpC.base), x86_EBX);
	if (offset != 0) {
		AddConstToX86Reg(x86_EBX, offset);
	}
	TestConstToX86Reg(15, x86_EBX);
	JneLabel32("Unaligned", 0);
	Jump[0] = RecompPos - 4;

	CompilerToggleBuffer();
	CPU_Message("   Unaligned:");
	x86_SetBranch32b((DWORD*)Jump[0], (DWORD*)RecompPos);
	Cheat_r4300iOpcodeNoMessage(RSP_Opcode_SQV,"RSP_Opcode_SQV");
	JmpLabel32("Done", 0);
	Jump[1] = RecompPos - 4;
	CompilerToggleBuffer();

	AndConstToX86Reg(x86_EBX, 0x0fff);
	if (IsSseEnabled == FALSE) {
		if (RSPOpC.del == 12) {
			sprintf(Reg, "RSP_Vect[%i].B[0]", RSPOpC.rt);
			MoveVariableToX86reg(&RSP_Vect[RSPOpC.rt].B[0], Reg, x86_EAX);
			sprintf(Reg, "RSP_Vect[%i].B[12]", RSPOpC.rt);
			MoveVariableToX86reg(&RSP_Vect[RSPOpC.rt].B[12], Reg, x86_ECX);
			sprintf(Reg, "RSP_Vect[%i].B[8]", RSPOpC.rt);
			MoveVariableToX86reg(&RSP_Vect[RSPOpC.rt].B[8], Reg, x86_EDX);
			sprintf(Reg, "RSP_Vect[%i].B[4]", RSPOpC.rt);
			MoveVariableToX86reg(&RSP_Vect[RSPOpC.rt].B[4], Reg, x86_EDI);
		} else {
			sprintf(Reg, "RSP_Vect[%i].B[12]", RSPOpC.rt);
			MoveVariableToX86reg(&RSP_Vect[RSPOpC.rt].B[12], Reg, x86_EAX);
			sprintf(Reg, "RSP_Vect[%i].B[8]", RSPOpC.rt);
			MoveVariableToX86reg(&RSP_Vect[RSPOpC.rt].B[8], Reg, x86_ECX);
			sprintf(Reg, "RSP_Vect[%i].B[4]", RSPOpC.rt);
			MoveVariableToX86reg(&RSP_Vect[RSPOpC.rt].B[4], Reg, x86_EDX);
			sprintf(Reg, "RSP_Vect[%i].B[0]", RSPOpC.rt);
			MoveVariableToX86reg(&RSP_Vect[RSPOpC.rt].B[0], Reg, x86_EDI);
		}

		MoveX86regToN64MemDisp(x86_EAX, x86_EBX, 0);
		MoveX86regToN64MemDisp(x86_ECX, x86_EBX, 4);
		MoveX86regToN64MemDisp(x86_EDX, x86_EBX, 8);
		MoveX86regToN64MemDisp(x86_EDI, x86_EBX, 12);
	} else {
		sprintf(Reg, "RSP_Vect[%i].B[0]", RSPOpC.rt);
		SseMoveAlignedVariableToReg(&RSP_Vect[RSPOpC.rt].B[0], Reg, x86_XMM0);
		if (RSPOpC.del == 12) {
			SseShuffleReg(x86_XMM0, x86_MM0, 0x6c);
		} else {
			SseShuffleReg(x86_XMM0, x86_MM0, 0x1b);
		}
		SseMoveUnalignedRegToN64Mem(x86_XMM0, x86_EBX);
	}
	CPU_Message("   Done:");
	x86_SetBranch32b((DWORD*)Jump[1], (DWORD*)RecompPos);
}

void Compile_Opcode_SRV ( void ) {
	Cheat_r4300iOpcode(RSP_Opcode_SRV,"RSP_Opcode_SRV");
}

void Compile_Opcode_SPV ( void ) {
	Cheat_r4300iOpcode(RSP_Opcode_SPV,"RSP_Opcode_SPV");
}

void Compile_Opcode_SUV ( void ) {
	Cheat_r4300iOpcode(RSP_Opcode_SUV,"RSP_Opcode_SUV");
}

void Compile_Opcode_SHV ( void ) {
	Cheat_r4300iOpcode(RSP_Opcode_SHV,"RSP_Opcode_SHV");
}

void Compile_Opcode_SFV ( void ) {
	Cheat_r4300iOpcode(RSP_Opcode_SFV,"RSP_Opcode_SFV");
}

void Compile_Opcode_STV ( void ) {
	Cheat_r4300iOpcode(RSP_Opcode_STV,"RSP_Opcode_STV");
}

void Compile_Opcode_SWV ( void ) {
	Cheat_r4300iOpcode(RSP_Opcode_SWV,"RSP_Opcode_SWV");
}

/************************** Other functions **************************/

void Compile_UnknownOpcode (void) {
	CPU_Message("  %X Unhandled Opcode: %s",CompilePC, RSPOpcodeName(RSPOpC.Hex,CompilePC) );	
	NextInstruction = FINISH_BLOCK;
	MoveConstToVariable(CompilePC,PrgCount,"RSP PC");
	MoveConstToVariable(RSPOpC.Hex,&RSPOpC.Hex, "RSPOpC.Hex");
	Call_Direct(rsp_UnknownOpcode, "rsp_UnknownOpcode" );
	Ret();
}
