예제 #1
0
파일: iCOP0.cpp 프로젝트: Aced14/pcsx2
void recMFC0()
{
	if( _Rd_ == 9 )
	{
		// This case needs to be handled even if the write-back is ignored (_Rt_ == 0 )
        xMOV(ecx, ptr[&cpuRegs.cycle]);
        xMOV(eax, ecx);
		xSUB(eax, ptr[&s_iLastCOP0Cycle]);
		u8* skipInc = JNZ8( 0 );
		xINC(eax);
		x86SetJ8( skipInc );
        xADD(ptr[&cpuRegs.CP0.n.Count], eax);
		xMOV(ptr[&s_iLastCOP0Cycle], ecx);
        xMOV(eax, ptr[&cpuRegs.CP0.r[ _Rd_ ] ]);

		if( !_Rt_ ) return;

		_deleteEEreg(_Rt_, 0);
		xMOV(ptr[&cpuRegs.GPR.r[_Rt_].UL[0]], eax);

		xCDQ();
		xMOV(ptr[&cpuRegs.GPR.r[_Rt_].UL[1]], edx);
		return;
	}

	if ( !_Rt_ ) return;

	if( _Rd_ == 25 )
	{
		switch(_Imm_ & 0x3F)
		{
			case 0:
				xMOV(eax, ptr[&cpuRegs.PERF.n.pccr]);
			break;

			case 1:
				iFlushCall(FLUSH_INTERPRETER);
				xFastCall(COP0_UpdatePCCR );
				xMOV(eax, ptr[&cpuRegs.PERF.n.pcr0]);
				break;
			case 3:
				iFlushCall(FLUSH_INTERPRETER);
				xFastCall(COP0_UpdatePCCR );
				xMOV(eax, ptr[&cpuRegs.PERF.n.pcr1]);
			break;
		}
		_deleteEEreg(_Rt_, 0);
		xMOV(ptr[&cpuRegs.GPR.r[_Rt_].UL[0]], eax);

		xCDQ();
		xMOV(ptr[&cpuRegs.GPR.r[_Rt_].UL[1]], edx);

		return;
	}
	else if(_Rd_ == 24){
		COP0_LOG("MFC0 Breakpoint debug Registers code = %x\n", cpuRegs.code & 0x3FF);
        return;
	}
	_eeOnWriteReg(_Rt_, 1);
	_deleteEEreg(_Rt_, 0);
	xMOV(eax, ptr[&cpuRegs.CP0.r[ _Rd_ ]]);
	xCDQ();
	xMOV(ptr[&cpuRegs.GPR.r[_Rt_].UL[0]], eax);
	xMOV(ptr[&cpuRegs.GPR.r[_Rt_].UL[1]], edx);
}
예제 #2
0
// ------------------------------------------------------------------------
// Internal implementation of EmitSibMagic which has been custom tailored
// to optimize special forms of the Lea instructions accordingly, such
// as when a LEA can be replaced with a "MOV reg,imm" or "MOV reg,reg".
//
// preserve_flags - set to ture to disable use of SHL on [Index*Base] forms
// of LEA, which alters flags states.
//
static void EmitLeaMagic( const xRegisterInt& to, const xIndirectVoid& src, bool preserve_flags )
{
	int displacement_size = (src.Displacement == 0) ? 0 :
		( ( src.IsByteSizeDisp() ) ? 1 : 2 );

	// See EmitSibMagic for commenting on SIB encoding.

	if( !NeedsSibMagic( src ) )
	{
		// LEA Land: means we have either 1-register encoding or just an offset.
		// offset is encodable as an immediate MOV, and a register is encodable
		// as a register MOV.

		if( src.Index.IsEmpty() )
		{
			xMOV( to, src.Displacement );
			return;
		}
		else if( displacement_size == 0 )
		{
			_xMovRtoR( to, src.Index );
			return;
		}
		else
		{
			if( !preserve_flags )
			{
				// encode as MOV and ADD combo.  Make sure to use the immediate on the
				// ADD since it can encode as an 8-bit sign-extended value.

				_xMovRtoR( to, src.Index );
				xADD( to, src.Displacement );
				return;
			}
			else
			{
				// note: no need to do ebp+0 check since we encode all 0 displacements as
				// register assignments above (via MOV)

				xWrite8( 0x8d );
				ModRM( displacement_size, to.Id, src.Index.Id );
			}
		}
	}
	else
	{
		if( src.Base.IsEmpty() )
		{
			if( !preserve_flags && (displacement_size == 0) )
			{
				// Encode [Index*Scale] as a combination of Mov and Shl.
				// This is more efficient because of the bloated LEA format which requires
				// a 32 bit displacement, and the compact nature of the alternative.
				//
				// (this does not apply to older model P4s with the broken barrel shifter,
				//  but we currently aren't optimizing for that target anyway).

				_xMovRtoR( to, src.Index );
				xSHL( to, src.Scale );
				return;
			}
			xWrite8( 0x8d );
			ModRM( 0, to.Id, ModRm_UseSib );
			SibSB( src.Scale, src.Index.Id, ModRm_UseDisp32 );
			xWrite32( src.Displacement );
			return;
		}
		else
		{
			if( src.Scale == 0 )
			{
				if( !preserve_flags )
				{
					if( src.Index == esp )
					{
						// ESP is not encodable as an index (ix86 ignores it), thus:
						_xMovRtoR( to, src.Base );	// will do the trick!
						if( src.Displacement ) xADD( to, src.Displacement );
						return;
					}
					else if( src.Displacement == 0 )
					{
						_xMovRtoR( to, src.Base );
						_g1_EmitOp( G1Type_ADD, to, src.Index );
						return;
					}
				}
				else if( (src.Index == esp) && (src.Displacement == 0) )
				{
					// special case handling of ESP as Index, which is replaceable with
					// a single MOV even when preserve_flags is set! :D

					_xMovRtoR( to, src.Base );
					return;
				}
			}

			if( src.Base == ebp && displacement_size == 0 )
				displacement_size = 1;		// forces [ebp] to be encoded as [ebp+0]!

			xWrite8( 0x8d );
			ModRM( displacement_size, to.Id, ModRm_UseSib );
			SibSB( src.Scale, src.Index.Id, src.Base.Id );
		}
	}

	if( displacement_size != 0 )
	{
		if( displacement_size == 1 )
			xWrite<s8>( src.Displacement );
		else
			xWrite<s32>( src.Displacement );
	}
}