Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

151 lines
4.5 KiB

//========== Copyright © Valve Corporation, All rights reserved. ========
// Easy ("tier0") implementations of simple GCM contexts
//
#ifndef PS3_SPUGCM_LSRING0_HDR
#define PS3_SPUGCM_LSRING0_HDR
class CSpuGcmMeasureBuffer: public CellGcmContextData
{
public:
CSpuGcmMeasureBuffer( )
{
this->begin = 0;
this->end = 0;
this->current = 0;
this->callback = CallbackDelegator;
}
uint GetSizeBytes()const
{
return uintp( this->end );
}
uint GetSizeWords()const
{
return this->end - this->begin;
}
protected:
void Callback( uint nCount )
{
this->end = ( uint32* )AlignValue( uintp( this->current + nCount ), 16 );
}
static int32_t CallbackDelegator( struct CellGcmContextData *pContext, uint32_t nCount )
{
static_cast<CSpuGcmMeasureBuffer*>( pContext )->Callback( nCount );
return CELL_OK;
}
};
class CSpuGcmAlignedBuffer: public CellGcmContextData
{
public:
void Init( void * lsBuffer, uint lsBufferSize, uint eaBegin, uint nIoOffsetDelta )
{
uint nShift = ( eaBegin - uint( lsBuffer ) ) & 0x7F;
this->begin = ( uint32* )( uintp( lsBuffer ) + nShift );
m_eaBuffer = eaBegin;
m_nIoOffsetDelta = nIoOffsetDelta;
this->end = ( uint32* )( uintp( this->begin ) + lsBufferSize );
this->current = this->begin;
this->callback = CallbackDelegator;
Assert( uint( this->begin ) >= uint( lsBuffer ) && !( 0x7F & ( uint( this->begin ) ^ eaBegin ) ) );
}
uint LsToLocalOffset( uint32 * lsCommand )
{
return EaToLocalOffset( LsToEa( lsCommand ) );
}
uint LsToEa( uint32 * lsCommand )
{
return uintp( lsCommand ) - uintp( this->begin ) + m_eaBuffer;
}
uint32 * EaToLs( uint32 eaCommand )
{
return ( uint32* )( ( eaCommand - m_eaBuffer ) + uintp( this->begin ) );
}
uint EaToLocalOffset( uint eaCommand )
{
return eaCommand + m_nIoOffsetDelta;
}
void AlignWithNops()
{
while ( 0xF & uintp( this->current ) )
{
*( this->current++ ) = CELL_GCM_METHOD_NOP;
}
}
void AppendJumpToNext()
{
*( this->current++ ) = CELL_GCM_JUMP( LsToLocalOffset( this->current + 1 ) );
}
void AppendJumpToNextIfNeededForDmaPutJtn()
{
// the JTN is not needed if the whole buffer fits into 128-byte cache line
Assert( this->current < this->end );
if( ( uintp( this->current ) ^ ( uintp( this->end ) - 1 ) ) & -128 )
{
// the first and the last bytes are in separate cache lines; we need to insert JTN at the beginning
AppendJumpToNext();
}
}
void Append( const SetLabelAlignedCommand_t & cmd )
{
AlignWithNops();
*( vector unsigned int * )( this->current ) = cmd.m_cmd.m_vuCmd;
this->current += 4;
}
// DMA put a segment of command buffer using JTN method. The start of the buffer shall be JTN, unless the buffer is small enough to be DMA'd
void DmaPutJtn()
{
Assert( this->current <= this->end && !( 0x7F & ( uintp( this->begin ) ^ m_eaBuffer ) ) );
while ( this->current < this->end )
{
*( this->current ++ ) = CELL_GCM_METHOD_NOP;
}
// skip the first 16 bytes where JTN resides; skip the whole cache line, while we're at it
Assert( this->current <= this->end );
uint32 * pRest = ( uint32* )( ( uintp( this->begin ) + 128 ) & -128 );
Assert( pRest > this->begin );
if ( pRest < this->end )
{
//VjobSpuLog( "lsring0 put %p..%p->%X tag:%d\n", pRest, this->end, LsToEa( pRest ), VJOB_IOBUFFER_DMATAG );
Assert( !( 0x7F & LsToEa( pRest ) ) );
VjobDmaPut( pRest, LsToEa( pRest ), uintp( this->end ) - uintp( pRest ), VJOB_IOBUFFER_DMATAG, 0, 0 );
//VjobSpuLog( "lsring0 putf (JTN %X) %p..%p->%X tag:%d\n", *this->begin, this->begin, pRest, m_eaBuffer, VJOB_IOBUFFER_DMATAG );
VjobDmaPutf( this->begin, m_eaBuffer, uintp( pRest ) - uintp( this->begin ), VJOB_IOBUFFER_DMATAG, 0, 0 );
}
else
{
// this case is pretty simple and doesn't require JTN at the beginning of the memory block , because it will be DMA'd atomically
// check that we really start the block with JTN
//Assert( CELL_GCM_JUMP( EaToLocalOffset( m_eaBuffer ) + 4 ) == *this->begin );
// overwrite JTN with NOP as we won't need JTN
//*this->begin = CELL_GCM_METHOD_NOP;
Assert( pRest >= this->end && this->end - this->begin <= 128 / 4 );
VjobDmaPutf( this->begin, m_eaBuffer, uintp( this->end ) - uintp( this->begin ), VJOB_IOBUFFER_DMATAG, 0, 0 );
}
}
protected:
uint m_eaBuffer;
uint m_nIoOffsetDelta;
protected:
void Callback( uint nCount )
{
DebuggerBreak();
}
static int32_t CallbackDelegator( struct CellGcmContextData *pContext, uint32_t nCount )
{
static_cast<CSpuGcmAlignedBuffer*>( pContext )->Callback( nCount );
return CELL_ERROR_ERROR_FLAG;
}
};
#endif