Example #1
0
// rd = rs op rt
void eeRecompileCodeConst0(R5900FNPTR constcode, R5900FNPTR_INFO constscode, R5900FNPTR_INFO consttcode, R5900FNPTR_INFO noconstcode)
{
	if ( ! _Rd_ ) return;

	// for now, don't support xmm

	_deleteGPRtoXMMreg(_Rs_, 1);
	_deleteGPRtoXMMreg(_Rt_, 1);
	_deleteGPRtoXMMreg(_Rd_, 0);
	_deleteMMXreg(MMX_GPR+_Rs_, 1);
	_deleteMMXreg(MMX_GPR+_Rt_, 1);
	_deleteMMXreg(MMX_GPR+_Rd_, 0);

	if( GPR_IS_CONST2(_Rs_, _Rt_) ) {
		GPR_SET_CONST(_Rd_);
		constcode();
		return;
	}

	if( GPR_IS_CONST1(_Rs_) ) {
		constscode(0);
		GPR_DEL_CONST(_Rd_);
		return;
	}

	if( GPR_IS_CONST1(_Rt_) ) {
		consttcode(0);
		GPR_DEL_CONST(_Rd_);
		return;
	}

	noconstcode(0);
	GPR_DEL_CONST(_Rd_);
}
Example #2
0
// rd = rt MULT rs  (SPECIAL)
void eeRecompileCodeConstSPECIAL(R5900FNPTR constcode, R5900FNPTR_INFO multicode, int MULT)
{
	pxFail( "Unfinished code reached." );

	// for now, don't support xmm
	if( MULT ) {
		_deleteGPRtoXMMreg(_Rd_, 0);
	}

	_deleteGPRtoXMMreg(_Rs_, 1);
	_deleteGPRtoXMMreg(_Rt_, 1);

	if( GPR_IS_CONST2(_Rs_, _Rt_) ) {
		if( MULT && _Rd_ ) GPR_SET_CONST(_Rd_);
		constcode();
		return;
	}

	if( GPR_IS_CONST1(_Rs_) ) {
		//multicode(PROCESS_EE_CONSTS);
		if( MULT && _Rd_ ) GPR_DEL_CONST(_Rd_);
		return;
	}

	if( GPR_IS_CONST1(_Rt_) ) {
		//multicode(PROCESS_EE_CONSTT);
		if( MULT && _Rd_ ) GPR_DEL_CONST(_Rd_);
		return;
	}

	multicode(0);
	if( MULT && _Rd_ ) GPR_DEL_CONST(_Rd_);
}
Example #3
0
// rt op rs
void eeRecompileCode3(R5900FNPTR constcode, R5900FNPTR_INFO multicode)
{
	pxFail( "Unfinished code reached." );

	// for now, don't support xmm
	_deleteEEreg(_Rs_, 0);
	_deleteEEreg(_Rt_, 1);

	if( GPR_IS_CONST2(_Rs_, _Rt_) ) {
		constcode();
		return;
	}

	if( GPR_IS_CONST1(_Rs_) ) {
		//multicode(PROCESS_EE_CONSTT);
		return;
	}

	if( GPR_IS_CONST1(_Rt_) ) {
		//multicode(PROCESS_EE_CONSTT);
		return;
	}

	multicode(0);
}
Example #4
0
// rd = rt op sa
void eeRecompileCode2(R5900FNPTR constcode, R5900FNPTR_INFO noconstcode)
{
	int mmreg1, mmreg2;
	if ( ! _Rd_ ) return;

	if( GPR_IS_CONST1(_Rt_) ) {
		_deleteMMXreg(MMX_GPR+_Rd_, 2);
		_deleteGPRtoXMMreg(_Rd_, 2);
		GPR_SET_CONST(_Rd_);
		constcode();
		return;
	}

	// test if should write xmm, mirror to mmx code
	if( g_pCurInstInfo->info & EEINST_XMM ) {

		// no const regs
		mmreg1 = _allocCheckGPRtoXMM(g_pCurInstInfo, _Rt_, MODE_READ);

		if( mmreg1 >= 0 ) {
			int info = PROCESS_EE_XMM|PROCESS_EE_SETMODET(mmreg1);

			// check for last used, if so don't alloc a new XMM reg
			_addNeededGPRtoXMMreg(_Rd_);
			mmreg2 = _checkXMMreg(XMMTYPE_GPRREG, _Rd_, MODE_WRITE);

			if( mmreg2 < 0 ) {
				if( (g_pCurInstInfo->regs[_Rt_] & EEINST_LASTUSE) || !EEINST_ISLIVE64(_Rt_) ) {
					_freeXMMreg(mmreg1);
					info &= ~PROCESS_EE_MODEWRITET;
					_deleteMMXreg(MMX_GPR+_Rd_, 2);
					xmmregs[mmreg1].inuse = 1;
					xmmregs[mmreg1].reg = _Rd_;
					xmmregs[mmreg1].mode = MODE_WRITE|MODE_READ;
					mmreg2 = mmreg1;
				}
				else mmreg2 = _allocGPRtoXMMreg(-1, _Rd_, MODE_WRITE);
			}

			noconstcode(info|PROCESS_EE_SET_T(mmreg1)|PROCESS_EE_SET_D(mmreg2));
			_clearNeededXMMregs();
			GPR_DEL_CONST(_Rd_);
			return;
		}

		_clearNeededXMMregs();
	}

	// regular x86
	_deleteGPRtoXMMreg(_Rt_, 1);
	_deleteGPRtoXMMreg(_Rd_, 2);
	_deleteMMXreg(MMX_GPR+_Rt_, 1);
	_deleteMMXreg(MMX_GPR+_Rd_, 2);

	noconstcode(0);
	GPR_DEL_CONST(_Rd_);
}
Example #5
0
void _flushEEreg(int reg)
{
	if (!reg) return;
	if (GPR_IS_CONST1(reg)) {
		_flushConstReg(reg);
		return;
	}
	_deleteGPRtoXMMreg(reg, 1);
	_deleteMMXreg(MMX_GPR + reg, 1);
}
Example #6
0
void _deleteEEreg(int reg, int flush)
{
	if( !reg ) return;
	if( flush && GPR_IS_CONST1(reg) ) {
		_flushConstReg(reg);
	}
	GPR_DEL_CONST(reg);
	_deleteGPRtoXMMreg(reg, flush ? 0 : 2);
	_deleteMMXreg(MMX_GPR+reg, flush ? 0 : 2);
}
Example #7
0
void recMTSAB()
{
	if( GPR_IS_CONST1(_Rs_) ) {
		xMOV(ptr32[&cpuRegs.sa], ((g_cpuConstRegs[_Rs_].UL[0] & 0xF) ^ (_Imm_ & 0xF)) );
	}
	else {
		_eeMoveGPRtoR(eax, _Rs_);
		xAND(eax, 0xF);
		xXOR(eax, _Imm_&0xf);
		xMOV(ptr[&cpuRegs.sa], eax);
	}
}
Example #8
0
void recMTSAB( void )
{
	if( GPR_IS_CONST1(_Rs_) ) {
		MOV32ItoM((uptr)&cpuRegs.sa, ((g_cpuConstRegs[_Rs_].UL[0] & 0xF) ^ (_Imm_ & 0xF)) );
	}
	else {
		_eeMoveGPRtoR(EAX, _Rs_);
		AND32ItoR(EAX, 0xF);
		XOR32ItoR(EAX, _Imm_&0xf);
		MOV32RtoM((uptr)&cpuRegs.sa, EAX);
	}
}
Example #9
0
// SA is 4-bit and contains the amount of bytes to shift
void recMTSA()
{
	if( GPR_IS_CONST1(_Rs_) ) {
		xMOV(ptr32[&cpuRegs.sa], g_cpuConstRegs[_Rs_].UL[0] & 0xf );
	}
	else {
		int mmreg;

		if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rs_, MODE_READ)) >= 0 ) {
			xMOVSS(ptr[&cpuRegs.sa], xRegisterSSE(mmreg));
		}
		else if( (mmreg = _checkMMXreg(MMX_GPR+_Rs_, MODE_READ)) >= 0 ) {
			xMOVD(ptr[&cpuRegs.sa], xRegisterMMX(mmreg));
			SetMMXstate();
		}
		else {
			xMOV(eax, ptr[&cpuRegs.GPR.r[_Rs_].UL[0]]);
			xMOV(ptr[&cpuRegs.sa], eax);
		}
		xAND(ptr32[&cpuRegs.sa], 0xf);
	}
}
Example #10
0
// SA is 4-bit and contains the amount of bytes to shift
void recMTSA( void )
{
	if( GPR_IS_CONST1(_Rs_) ) {
		MOV32ItoM((uptr)&cpuRegs.sa, g_cpuConstRegs[_Rs_].UL[0] & 0xf );
	}
	else {
		int mmreg;

		if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rs_, MODE_READ)) >= 0 ) {
			SSE_MOVSS_XMM_to_M32((uptr)&cpuRegs.sa, mmreg);
		}
		else if( (mmreg = _checkMMXreg(MMX_GPR+_Rs_, MODE_READ)) >= 0 ) {
			MOVDMMXtoM((uptr)&cpuRegs.sa, mmreg);
			SetMMXstate();
		}
		else {
			MOV32MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rs_].UL[0]);
			MOV32RtoM((uptr)&cpuRegs.sa, EAX);
		}
		AND32ItoM((uptr)&cpuRegs.sa, 0xf);
	}
}
Example #11
0
void recMTC0()
{
	if( GPR_IS_CONST1(_Rt_) )
	{
		switch (_Rd_)
		{
			case 12:
				iFlushCall(FLUSH_INTERPRETER);
				xFastCall(WriteCP0Status, g_cpuConstRegs[_Rt_].UL[0] );
			break;

			case 9:
				xMOV(ecx, ptr[&cpuRegs.cycle]);
				xMOV(ptr[&s_iLastCOP0Cycle], ecx);
				xMOV(ptr32[&cpuRegs.CP0.r[9]], g_cpuConstRegs[_Rt_].UL[0]);
			break;

			case 25:
				switch(_Imm_ & 0x3F)
				{
					case 0:
						iFlushCall(FLUSH_INTERPRETER);
						xFastCall(COP0_UpdatePCCR );
						xMOV( ptr32[&cpuRegs.PERF.n.pccr], g_cpuConstRegs[_Rt_].UL[0] );
						xFastCall(COP0_DiagnosticPCCR );
					break;

					case 1:
						xMOV(eax, ptr[&cpuRegs.cycle]);
						xMOV(ptr32[&cpuRegs.PERF.n.pcr0], g_cpuConstRegs[_Rt_].UL[0]);
						xMOV(ptr[&s_iLastPERFCycle[0]], eax);
					break;

					case 3:
						xMOV(eax, ptr[&cpuRegs.cycle]);
						xMOV(ptr32[&cpuRegs.PERF.n.pcr1], g_cpuConstRegs[_Rt_].UL[0]);
						xMOV(ptr[&s_iLastPERFCycle[1]], eax);
					break;
				}
			break;

			case 24:
				COP0_LOG("MTC0 Breakpoint debug Registers code = %x\n", cpuRegs.code & 0x3FF);
			break;

			default:
				xMOV(ptr32[&cpuRegs.CP0.r[_Rd_]], g_cpuConstRegs[_Rt_].UL[0]);
			break;
		}
	}
	else
	{
		switch (_Rd_)
		{
			case 12:
				iFlushCall(FLUSH_INTERPRETER);
				_eeMoveGPRtoR(ecx, _Rt_);
				xFastCall(WriteCP0Status, ecx );
			break;

			case 9:
				xMOV(ecx, ptr[&cpuRegs.cycle]);
				_eeMoveGPRtoM((uptr)&cpuRegs.CP0.r[9], _Rt_);
				xMOV(ptr[&s_iLastCOP0Cycle], ecx);
			break;

			case 25:
				switch(_Imm_ & 0x3F)
				{
					case 0:
						iFlushCall(FLUSH_INTERPRETER);
						xFastCall(COP0_UpdatePCCR );
						_eeMoveGPRtoM((uptr)&cpuRegs.PERF.n.pccr, _Rt_);
						xFastCall(COP0_DiagnosticPCCR );
					break;

					case 1:
						xMOV(ecx, ptr[&cpuRegs.cycle]);
						_eeMoveGPRtoM((uptr)&cpuRegs.PERF.n.pcr0, _Rt_);
						xMOV(ptr[&s_iLastPERFCycle[0]], ecx);
					break;

					case 3:
						xMOV(ecx, ptr[&cpuRegs.cycle]);
						_eeMoveGPRtoM((uptr)&cpuRegs.PERF.n.pcr1, _Rt_);
						xMOV(ptr[&s_iLastPERFCycle[1]], ecx);
					break;
				}
			break;

			case 24:
				COP0_LOG("MTC0 Breakpoint debug Registers code = %x\n", cpuRegs.code & 0x3FF);
			break;

			default:
				_eeMoveGPRtoM((uptr)&cpuRegs.CP0.r[_Rd_], _Rt_);
			break;
		}
	}
}
Example #12
0
// ignores XMMINFO_READS, XMMINFO_READT, and XMMINFO_READD_LO from xmminfo
// core of reg caching
void eeRecompileCode0(R5900FNPTR constcode, R5900FNPTR_INFO constscode, R5900FNPTR_INFO consttcode, R5900FNPTR_INFO noconstcode, int xmminfo)
{
	int mmreg1, mmreg2, mmreg3, mmtemp, moded;

	if ( ! _Rd_ && (xmminfo&XMMINFO_WRITED) ) return;

	if( GPR_IS_CONST2(_Rs_, _Rt_) ) {
		if( xmminfo & XMMINFO_WRITED ) {
			_deleteMMXreg(MMX_GPR+_Rd_, 2);
			_deleteGPRtoXMMreg(_Rd_, 2);
		}
		if( xmminfo&XMMINFO_WRITED ) GPR_SET_CONST(_Rd_);
		constcode();
		return;
	}

	moded = MODE_WRITE|((xmminfo&XMMINFO_READD)?MODE_READ:0);

	// test if should write xmm, mirror to mmx code
	if( g_pCurInstInfo->info & EEINST_XMM ) {

		if( xmminfo & (XMMINFO_READLO|XMMINFO_WRITELO) ) _addNeededGPRtoXMMreg(XMMGPR_LO);
		if( xmminfo & (XMMINFO_READHI|XMMINFO_WRITEHI) ) _addNeededGPRtoXMMreg(XMMGPR_HI);
		_addNeededGPRtoXMMreg(_Rs_);
		_addNeededGPRtoXMMreg(_Rt_);

		if( GPR_IS_CONST1(_Rs_) || GPR_IS_CONST1(_Rt_) ) {
			int creg = GPR_IS_CONST1(_Rs_) ? _Rs_ : _Rt_;
			int vreg = creg == _Rs_ ? _Rt_ : _Rs_;

//			if(g_pCurInstInfo->regs[vreg]&EEINST_XMM) {
//				mmreg1 = _allocGPRtoXMMreg(-1, vreg, MODE_READ);
//				_addNeededGPRtoXMMreg(vreg);
//			}
			mmreg1 = _allocCheckGPRtoXMM(g_pCurInstInfo, vreg, MODE_READ);

			if( mmreg1 >= 0 ) {
				int info = PROCESS_EE_XMM;

				if( GPR_IS_CONST1(_Rs_) ) info |= PROCESS_EE_SETMODET(mmreg1);
				else info |= PROCESS_EE_SETMODES(mmreg1);

				if( xmminfo & XMMINFO_WRITED ) {

					_addNeededGPRtoXMMreg(_Rd_);
					mmreg3 = _checkXMMreg(XMMTYPE_GPRREG, _Rd_, MODE_WRITE);

					if( !(xmminfo&XMMINFO_READD) && mmreg3 < 0 && ((g_pCurInstInfo->regs[vreg] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(vreg)) ) {
						_freeXMMreg(mmreg1);
						if( GPR_IS_CONST1(_Rs_) ) info &= ~PROCESS_EE_MODEWRITET;
						else info &= ~PROCESS_EE_MODEWRITES;
						_deleteMMXreg(MMX_GPR+_Rd_, 2);
						xmmregs[mmreg1].inuse = 1;
						xmmregs[mmreg1].reg = _Rd_;
						xmmregs[mmreg1].mode = moded;
						mmreg3 = mmreg1;
					}
					else if( mmreg3 < 0 ) mmreg3 = _allocGPRtoXMMreg(-1, _Rd_, moded);

					info |= PROCESS_EE_SET_D(mmreg3);
				}

				if( xmminfo & (XMMINFO_READLO|XMMINFO_WRITELO) ) {
					mmtemp = eeProcessHILO(XMMGPR_LO, ((xmminfo&XMMINFO_READLO)?MODE_READ:0)|((xmminfo&XMMINFO_WRITELO)?MODE_WRITE:0), 0);
					if( mmtemp >= 0 ) info |= PROCESS_EE_SET_LO(mmtemp);
				}
				if( xmminfo & (XMMINFO_READHI|XMMINFO_WRITEHI) ) {
					mmtemp = eeProcessHILO(XMMGPR_HI, ((xmminfo&XMMINFO_READLO)?MODE_READ:0)|((xmminfo&XMMINFO_WRITELO)?MODE_WRITE:0), 0);
					if( mmtemp >= 0 ) info |= PROCESS_EE_SET_HI(mmtemp);
				}

				if( creg == _Rs_ ) constscode(info|PROCESS_EE_SET_T(mmreg1));
				else consttcode(info|PROCESS_EE_SET_S(mmreg1));
				_clearNeededXMMregs();
				if( xmminfo & XMMINFO_WRITED ) GPR_DEL_CONST(_Rd_);
				return;
			}
		}
		else {
			// no const regs
			mmreg1 = _allocCheckGPRtoXMM(g_pCurInstInfo, _Rs_, MODE_READ);
			mmreg2 = _allocCheckGPRtoXMM(g_pCurInstInfo, _Rt_, MODE_READ);

			if( mmreg1 >= 0 || mmreg2 >= 0 ) {
				int info = PROCESS_EE_XMM;

				// do it all in xmm
				if( mmreg1 < 0 ) mmreg1 = _allocGPRtoXMMreg(-1, _Rs_, MODE_READ);
				if( mmreg2 < 0 ) mmreg2 = _allocGPRtoXMMreg(-1, _Rt_, MODE_READ);

				info |= PROCESS_EE_SETMODES(mmreg1)|PROCESS_EE_SETMODET(mmreg2);

				if( xmminfo & XMMINFO_WRITED ) {
					// check for last used, if so don't alloc a new XMM reg
					_addNeededGPRtoXMMreg(_Rd_);
					mmreg3 = _checkXMMreg(XMMTYPE_GPRREG, _Rd_, moded);

					if( mmreg3 < 0 ) {
						if( !(xmminfo&XMMINFO_READD) && ((g_pCurInstInfo->regs[_Rt_] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(_Rt_)) ) {
							_freeXMMreg(mmreg2);
							info &= ~PROCESS_EE_MODEWRITET;
							_deleteMMXreg(MMX_GPR+_Rd_, 2);
							xmmregs[mmreg2].inuse = 1;
							xmmregs[mmreg2].reg = _Rd_;
							xmmregs[mmreg2].mode = moded;
							mmreg3 = mmreg2;
						}
						else if( !(xmminfo&XMMINFO_READD) && ((g_pCurInstInfo->regs[_Rs_] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(_Rs_)) ) {
							_freeXMMreg(mmreg1);
							info &= ~PROCESS_EE_MODEWRITES;
							_deleteMMXreg(MMX_GPR+_Rd_, 2);
							xmmregs[mmreg1].inuse = 1;
							xmmregs[mmreg1].reg = _Rd_;
							xmmregs[mmreg1].mode = moded;
							mmreg3 = mmreg1;
						}
						else mmreg3 = _allocGPRtoXMMreg(-1, _Rd_, moded);
					}

					info |= PROCESS_EE_SET_D(mmreg3);
				}

				if( xmminfo & (XMMINFO_READLO|XMMINFO_WRITELO) ) {
					mmtemp = eeProcessHILO(XMMGPR_LO, ((xmminfo&XMMINFO_READLO)?MODE_READ:0)|((xmminfo&XMMINFO_WRITELO)?MODE_WRITE:0), 0);
					if( mmtemp >= 0 ) info |= PROCESS_EE_SET_LO(mmtemp);
				}
				if( xmminfo & (XMMINFO_READHI|XMMINFO_WRITEHI) ) {
					mmtemp = eeProcessHILO(XMMGPR_HI, ((xmminfo&XMMINFO_READLO)?MODE_READ:0)|((xmminfo&XMMINFO_WRITELO)?MODE_WRITE:0), 0);
					if( mmtemp >= 0 ) info |= PROCESS_EE_SET_HI(mmtemp);
				}

				noconstcode(info|PROCESS_EE_SET_S(mmreg1)|PROCESS_EE_SET_T(mmreg2));
				_clearNeededXMMregs();
				if( xmminfo & XMMINFO_WRITED ) GPR_DEL_CONST(_Rd_);
				return;
			}
		}

		_clearNeededXMMregs();
	}

	// regular x86
	_deleteGPRtoXMMreg(_Rs_, 1);
	_deleteGPRtoXMMreg(_Rt_, 1);
	if( xmminfo&XMMINFO_WRITED )
		_deleteGPRtoXMMreg(_Rd_, (xmminfo&XMMINFO_READD)?0:2);
	_deleteMMXreg(MMX_GPR+_Rs_, 1);
	_deleteMMXreg(MMX_GPR+_Rt_, 1);
	if( xmminfo&XMMINFO_WRITED )
		_deleteMMXreg(MMX_GPR+_Rd_, (xmminfo&XMMINFO_READD)?0:2);

	// don't delete, fn will take care of them
//	if( xmminfo & (XMMINFO_READLO|XMMINFO_WRITELO) ) {
//		_deleteGPRtoXMMreg(XMMGPR_LO, (xmminfo&XMMINFO_READLO)?1:0);
//		_deleteMMXreg(MMX_GPR+MMX_LO, (xmminfo&XMMINFO_READLO)?1:0);
//	}
//	if( xmminfo & (XMMINFO_READHI|XMMINFO_WRITEHI) ) {
//		_deleteGPRtoXMMreg(XMMGPR_HI, (xmminfo&XMMINFO_READHI)?1:0);
//		_deleteMMXreg(MMX_GPR+MMX_HI, (xmminfo&XMMINFO_READHI)?1:0);
//	}

	if( GPR_IS_CONST1(_Rs_) ) {
		constscode(0);
		if( xmminfo&XMMINFO_WRITED ) GPR_DEL_CONST(_Rd_);
		return;
	}

	if( GPR_IS_CONST1(_Rt_) ) {
		consttcode(0);
		if( xmminfo&XMMINFO_WRITED ) GPR_DEL_CONST(_Rd_);
		return;
	}

	noconstcode(0);
	if( xmminfo&XMMINFO_WRITED ) GPR_DEL_CONST(_Rd_);
}
Example #13
0
// EE XMM allocation code
int eeRecompileCodeXMM(int xmminfo)
{
	int info = PROCESS_EE_XMM;

	// flush consts
	if( xmminfo & XMMINFO_READT ) {
		if( GPR_IS_CONST1( _Rt_ ) && !(g_cpuFlushedConstReg&(1<<_Rt_)) ) {
			MOV32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], g_cpuConstRegs[_Rt_].UL[0]);
			MOV32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], g_cpuConstRegs[_Rt_].UL[1]);
			g_cpuFlushedConstReg |= (1<<_Rt_);
		}
	}
	if( xmminfo & XMMINFO_READS) {
		if( GPR_IS_CONST1( _Rs_ ) && !(g_cpuFlushedConstReg&(1<<_Rs_)) ) {
			MOV32ItoM((int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], g_cpuConstRegs[_Rs_].UL[0]);
			MOV32ItoM((int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], g_cpuConstRegs[_Rs_].UL[1]);
			g_cpuFlushedConstReg |= (1<<_Rs_);
		}
	}

	if( xmminfo & XMMINFO_WRITED ) {
		GPR_DEL_CONST(_Rd_);
	}

	// add needed
	if( xmminfo & (XMMINFO_READLO|XMMINFO_WRITELO) ) {
		_addNeededGPRtoXMMreg(XMMGPR_LO);
	}
	if( xmminfo & (XMMINFO_READHI|XMMINFO_WRITEHI) ) {
		_addNeededGPRtoXMMreg(XMMGPR_HI);
	}
	if( xmminfo & XMMINFO_READS) _addNeededGPRtoXMMreg(_Rs_);
	if( xmminfo & XMMINFO_READT) _addNeededGPRtoXMMreg(_Rt_);
	if( xmminfo & XMMINFO_WRITED ) _addNeededGPRtoXMMreg(_Rd_);

	// allocate
	if( xmminfo & XMMINFO_READS) {
		int reg = _allocGPRtoXMMreg(-1, _Rs_, MODE_READ);
		info |= PROCESS_EE_SET_S(reg)|PROCESS_EE_SETMODES(reg);
	}
	if( xmminfo & XMMINFO_READT) {
		int reg = _allocGPRtoXMMreg(-1, _Rt_, MODE_READ);
		info |= PROCESS_EE_SET_T(reg)|PROCESS_EE_SETMODET(reg);
	}

	if( xmminfo & XMMINFO_WRITED ) {
		int readd = MODE_WRITE|((xmminfo&XMMINFO_READD)?((xmminfo&XMMINFO_READD_LO)?(MODE_READ|MODE_READHALF):MODE_READ):0);

		int regd = _checkXMMreg(XMMTYPE_GPRREG, _Rd_, readd);

		if( regd < 0 ) {
			if( !(xmminfo&XMMINFO_READD) && (xmminfo & XMMINFO_READT) && (_Rt_ == 0 || (g_pCurInstInfo->regs[_Rt_] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(_Rt_)) ) {
				_freeXMMreg(EEREC_T);
				_deleteMMXreg(MMX_GPR+_Rd_, 2);
				xmmregs[EEREC_T].inuse = 1;
				xmmregs[EEREC_T].reg = _Rd_;
				xmmregs[EEREC_T].mode = readd;
				regd = EEREC_T;
			}
			else if( !(xmminfo&XMMINFO_READD) && (xmminfo & XMMINFO_READS) && (_Rs_ == 0 || (g_pCurInstInfo->regs[_Rs_] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(_Rs_)) ) {
				_freeXMMreg(EEREC_S);
				_deleteMMXreg(MMX_GPR+_Rd_, 2);
				xmmregs[EEREC_S].inuse = 1;
				xmmregs[EEREC_S].reg = _Rd_;
				xmmregs[EEREC_S].mode = readd;
				regd = EEREC_S;
			}
			else regd = _allocGPRtoXMMreg(-1, _Rd_, readd);
		}

		info |= PROCESS_EE_SET_D(regd);
	}
	if( xmminfo & (XMMINFO_READLO|XMMINFO_WRITELO) ) {
		info |= PROCESS_EE_SET_LO(_allocGPRtoXMMreg(-1, XMMGPR_LO, ((xmminfo&XMMINFO_READLO)?MODE_READ:0)|((xmminfo&XMMINFO_WRITELO)?MODE_WRITE:0)));
		info |= PROCESS_EE_LO;
	}
	if( xmminfo & (XMMINFO_READHI|XMMINFO_WRITEHI) ) {
		info |= PROCESS_EE_SET_HI(_allocGPRtoXMMreg(-1, XMMGPR_HI, ((xmminfo&XMMINFO_READHI)?MODE_READ:0)|((xmminfo&XMMINFO_WRITEHI)?MODE_WRITE:0)));
		info |= PROCESS_EE_HI;
	}
	return info;
}