Beispiel #1
0
// ------------------------------------------------------------------------
// Writes a jump at the current x86Ptr, which targets a pre-established target address.
// (usually a backwards jump)
//
// slideForward - used internally by xSmartJump to indicate that the jump target is going
// to slide forward in the event of an 8 bit displacement.
//
__emitinline void xJccKnownTarget(JccComparisonType comparison, const void *target, bool slideForward)
{
    // Calculate the potential j8 displacement first, assuming an instruction length of 2:
    sptr displacement8 = (sptr)target - (sptr)(xGetPtr() + 2);

    const int slideVal = slideForward ? ((comparison == Jcc_Unconditional) ? 3 : 4) : 0;
    displacement8 -= slideVal;

    if (slideForward) {
        pxAssertDev(displacement8 >= 0, "Used slideForward on a backward jump; nothing to slide!");
    }

    if (is_s8(displacement8))
        xJcc8(comparison, displacement8);
    else {
        // Perform a 32 bit jump instead. :(
        s32 *bah = xJcc32(comparison);
        sptr distance = (sptr)target - (sptr)xGetPtr();

#ifdef __x86_64__
        // This assert won't physically happen on x86 targets
        pxAssertDev(distance >= -0x80000000LL && distance < 0x80000000LL, "Jump target is too far away, needs an indirect register");
#endif

        *bah = (s32)distance;
    }
}
Beispiel #2
0
static void recRecompile()
{
	// Look up the block...
	// (Mask the IOP address accordingly to account for the many various segments and
	//  mirrors).

	u32 masked_pc = iopRegs.pc & IopMemory::AddressMask;
	if( masked_pc < 0x800000 )
		masked_pc &= Ps2MemSize::IopRam-1;
	
	xBlocksMap::Blockmap_iterator blowme( g_PersState.xBlockMap.Map.find( masked_pc ) );

	memzero_obj( g_BlockState );
	//g_BlockState.pc = iopRegs.pc;

	if( blowme == g_PersState.xBlockMap.Map.end() )
	{
		//Console::WriteLn( "IOP First-pass block at PC: 0x%08x  (total blocks=%d)", params masked_pc, g_PersState.xBlockMap.Blocks.GetLength() );
		recIR_FirstPassInterpreter();

		jASSUME( iopRegs.evtCycleCountdown <= iopRegs.evtCycleDuration );
		if( iopRegs.evtCycleCountdown <= 0 )
			iopRegs.ExecutePendingEvents();

		//if( !IsIopRamPage( masked_pc ) )	// disable block checking for non-ram (rom, rom1, etc)
		//	m_blockspace.ramlen = 0;
		
		g_PersState.xBlockMap.Map[masked_pc] = g_PersState.xBlockMap.Blocks.GetLength();
		g_PersState.xBlockMap.Blocks.New().Assign( m_blockspace );
	}
	else
	{
		recBlockItem& mess( g_PersState.xBlockMap.Blocks[blowme->second] );

		if( !mess.InstOptInfo.IsDisposed() )
		{
			//Console::WriteLn( "IOP Second-pass block at PC: 0x%08x  (total blocks=%d)", params masked_pc, g_PersState.xBlockMap.Blocks.GetLength() );

			m_tempIR.GenerateIR( mess );
			mess.InstOptInfo.Dispose();

			m_x86blockstate.AssignBlock( m_tempIR );
			m_x86blockstate.RegisterMapper();

			g_BlockState.xBlockPtr = m_xBlock_CurPtr;
			m_x86blockstate.EmitSomeExecutableGoodness();
			m_xBlock_CurPtr = xGetPtr();
			
			uptr temp = m_tbl_TranslatePC[masked_pc>>XlatePC_PageBitShift];
			uptr* dispatch_ptr = (uptr*)(temp + (masked_pc & XlatePC_PageMask));
			*dispatch_ptr = (uptr)g_BlockState.xBlockPtr;
		}
	}
Beispiel #3
0
// ------------------------------------------------------------------------
// Emits a 32 bit jump, and returns a pointer to the 32 bit displacement.
// (displacements should be assigned relative to the end of the jump instruction,
// or in other words *(retval+1) )
__emitinline s32 *xJcc32(JccComparisonType comparison, s32 displacement)
{
    if (comparison == Jcc_Unconditional)
        xWrite8(0xe9);
    else {
        xWrite8(0x0f);
        xWrite8(0x80 | comparison);
    }
    xWrite<s32>(displacement);

    return ((s32 *)xGetPtr()) - 1;
}
Beispiel #4
0
void xSmartJump::SetTarget()
{
	u8* target = xGetPtr();
	if( m_baseptr == NULL ) return;

	xSetPtr( m_baseptr );
	u8* const saveme = m_baseptr + GetMaxInstructionSize();
	xJccKnownTarget( m_cc, target, true );

	// Copy recompiled data inward if the jump instruction didn't fill the
	// alloted buffer (means that we optimized things to a j8!)

	const int spacer = (sptr)saveme - (sptr)xGetPtr();
	if( spacer != 0 )
	{
		u8* destpos = xGetPtr();
		const int copylen = (sptr)target - (sptr)saveme;

		memcpy_fast( destpos, saveme, copylen );
		xSetPtr( target - spacer );
	}
}
Beispiel #5
0
// ------------------------------------------------------------------------
// Writes a jump at the current x86Ptr, which targets a pre-established target address.
// (usually a backwards jump)
//
// slideForward - used internally by xSmartJump to indicate that the jump target is going
// to slide forward in the event of an 8 bit displacement.
//
__emitinline void xJccKnownTarget( JccComparisonType comparison, const void* target, bool slideForward )
{
	// Calculate the potential j8 displacement first, assuming an instruction length of 2:
	sptr displacement8 = (sptr)target - (sptr)(xGetPtr() + 2);

	const int slideVal = slideForward ? ((comparison == Jcc_Unconditional) ? 3 : 4) : 0;
	displacement8 -= slideVal;

	if( slideForward )
	{
		pxAssertDev( displacement8 >= 0, "Used slideForward on a backward jump; nothing to slide!" );
	}

	if( is_s8( displacement8 ) )
		xJcc8( comparison, displacement8 );
	else
	{
		// Perform a 32 bit jump instead. :(
		s32* bah = xJcc32( comparison );
		*bah = (s32)target - (s32)xGetPtr();
	}
}
Beispiel #6
0
// ------------------------------------------------------------------------
//
void xBlocksMap::AddLink( u32 pc, JccComparisonType cctype )
{
	recBlockItem& destItem( _getItem( pc ) );

	const xJumpLink& newlink( destItem.DependentLinks.AddNew( xJumpLink( xGetPtr(), cctype ) ) );
	newlink.SetTarget( m_xBlockLut[pc / 4] );

	if( destItem.x86len != 0 )
	{
		// Sanity Check: if block is already compiled, then the BlockPtr should *not* be dispatcher.
		jASSUME( m_xBlockLut[pc / 4] != DynFunc::Dispatcher );
	}
}
Beispiel #7
0
void xForwardJumpBase::_setTarget(uint opsize) const
{
    pxAssertDev(BasePtr != NULL, "");

    sptr displacement = (sptr)xGetPtr() - (sptr)BasePtr;
    if (opsize == 1) {
        pxAssertDev(is_s8(displacement), "Emitter Error: Invalid short jump displacement.");
        BasePtr[-1] = (s8)displacement;
    } else {
        // full displacement, no sanity checks needed :D
        ((s32 *)BasePtr)[-1] = displacement;
    }
}
Beispiel #8
0
xForwardJumpBase::xForwardJumpBase(uint opsize, JccComparisonType cctype)
{
    pxAssert(opsize == 1 || opsize == 4);
    pxAssertDev(cctype != Jcc_Unknown, "Invalid ForwardJump conditional type.");

    BasePtr = (s8 *)xGetPtr() +
              ((opsize == 1) ? 2 :                           // j8's are always 2 bytes.
                   ((cctype == Jcc_Unconditional) ? 5 : 6)); // j32's are either 5 or 6 bytes

    if (opsize == 1)
        xWrite8((cctype == Jcc_Unconditional) ? 0xeb : (0x70 | cctype));
    else {
        if (cctype == Jcc_Unconditional)
            xWrite8(0xe9);
        else {
            xWrite8(0x0f);
            xWrite8(0x80 | cctype);
        }
    }

    xAdvancePtr(opsize);
}
Beispiel #9
0
// ------------------------------------------------------------------------
// Emits a 32 bit jump, and returns a pointer to the 8 bit displacement.
// (displacements should be assigned relative to the end of the jump instruction,
// or in other words *(retval+1) )
__emitinline s8* xJcc8( JccComparisonType comparison, s8 displacement )
{
	xWrite8( (comparison == Jcc_Unconditional) ? 0xeb : (0x70 | comparison) );
	xWrite<s8>( displacement );
	return (s8*)xGetPtr() - 1;
}