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

  1. //========== Copyright � Valve Corporation, All rights reserved. ========
  2. // Easy ("tier0") implementations of simple GCM contexts
  3. //
  4. #ifndef PS3_SPUGCM_LSRING0_HDR
  5. #define PS3_SPUGCM_LSRING0_HDR
  6. class CSpuGcmMeasureBuffer: public CellGcmContextData
  7. {
  8. public:
  9. CSpuGcmMeasureBuffer( )
  10. {
  11. this->begin = 0;
  12. this->end = 0;
  13. this->current = 0;
  14. this->callback = CallbackDelegator;
  15. }
  16. uint GetSizeBytes()const
  17. {
  18. return uintp( this->end );
  19. }
  20. uint GetSizeWords()const
  21. {
  22. return this->end - this->begin;
  23. }
  24. protected:
  25. void Callback( uint nCount )
  26. {
  27. this->end = ( uint32* )AlignValue( uintp( this->current + nCount ), 16 );
  28. }
  29. static int32_t CallbackDelegator( struct CellGcmContextData *pContext, uint32_t nCount )
  30. {
  31. static_cast<CSpuGcmMeasureBuffer*>( pContext )->Callback( nCount );
  32. return CELL_OK;
  33. }
  34. };
  35. class CSpuGcmAlignedBuffer: public CellGcmContextData
  36. {
  37. public:
  38. void Init( void * lsBuffer, uint lsBufferSize, uint eaBegin, uint nIoOffsetDelta )
  39. {
  40. uint nShift = ( eaBegin - uint( lsBuffer ) ) & 0x7F;
  41. this->begin = ( uint32* )( uintp( lsBuffer ) + nShift );
  42. m_eaBuffer = eaBegin;
  43. m_nIoOffsetDelta = nIoOffsetDelta;
  44. this->end = ( uint32* )( uintp( this->begin ) + lsBufferSize );
  45. this->current = this->begin;
  46. this->callback = CallbackDelegator;
  47. Assert( uint( this->begin ) >= uint( lsBuffer ) && !( 0x7F & ( uint( this->begin ) ^ eaBegin ) ) );
  48. }
  49. uint LsToLocalOffset( uint32 * lsCommand )
  50. {
  51. return EaToLocalOffset( LsToEa( lsCommand ) );
  52. }
  53. uint LsToEa( uint32 * lsCommand )
  54. {
  55. return uintp( lsCommand ) - uintp( this->begin ) + m_eaBuffer;
  56. }
  57. uint32 * EaToLs( uint32 eaCommand )
  58. {
  59. return ( uint32* )( ( eaCommand - m_eaBuffer ) + uintp( this->begin ) );
  60. }
  61. uint EaToLocalOffset( uint eaCommand )
  62. {
  63. return eaCommand + m_nIoOffsetDelta;
  64. }
  65. void AlignWithNops()
  66. {
  67. while ( 0xF & uintp( this->current ) )
  68. {
  69. *( this->current++ ) = CELL_GCM_METHOD_NOP;
  70. }
  71. }
  72. void AppendJumpToNext()
  73. {
  74. *( this->current++ ) = CELL_GCM_JUMP( LsToLocalOffset( this->current + 1 ) );
  75. }
  76. void AppendJumpToNextIfNeededForDmaPutJtn()
  77. {
  78. // the JTN is not needed if the whole buffer fits into 128-byte cache line
  79. Assert( this->current < this->end );
  80. if( ( uintp( this->current ) ^ ( uintp( this->end ) - 1 ) ) & -128 )
  81. {
  82. // the first and the last bytes are in separate cache lines; we need to insert JTN at the beginning
  83. AppendJumpToNext();
  84. }
  85. }
  86. void Append( const SetLabelAlignedCommand_t & cmd )
  87. {
  88. AlignWithNops();
  89. *( vector unsigned int * )( this->current ) = cmd.m_cmd.m_vuCmd;
  90. this->current += 4;
  91. }
  92. // 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
  93. void DmaPutJtn()
  94. {
  95. Assert( this->current <= this->end && !( 0x7F & ( uintp( this->begin ) ^ m_eaBuffer ) ) );
  96. while ( this->current < this->end )
  97. {
  98. *( this->current ++ ) = CELL_GCM_METHOD_NOP;
  99. }
  100. // skip the first 16 bytes where JTN resides; skip the whole cache line, while we're at it
  101. Assert( this->current <= this->end );
  102. uint32 * pRest = ( uint32* )( ( uintp( this->begin ) + 128 ) & -128 );
  103. Assert( pRest > this->begin );
  104. if ( pRest < this->end )
  105. {
  106. //VjobSpuLog( "lsring0 put %p..%p->%X tag:%d\n", pRest, this->end, LsToEa( pRest ), VJOB_IOBUFFER_DMATAG );
  107. Assert( !( 0x7F & LsToEa( pRest ) ) );
  108. VjobDmaPut( pRest, LsToEa( pRest ), uintp( this->end ) - uintp( pRest ), VJOB_IOBUFFER_DMATAG, 0, 0 );
  109. //VjobSpuLog( "lsring0 putf (JTN %X) %p..%p->%X tag:%d\n", *this->begin, this->begin, pRest, m_eaBuffer, VJOB_IOBUFFER_DMATAG );
  110. VjobDmaPutf( this->begin, m_eaBuffer, uintp( pRest ) - uintp( this->begin ), VJOB_IOBUFFER_DMATAG, 0, 0 );
  111. }
  112. else
  113. {
  114. // this case is pretty simple and doesn't require JTN at the beginning of the memory block , because it will be DMA'd atomically
  115. // check that we really start the block with JTN
  116. //Assert( CELL_GCM_JUMP( EaToLocalOffset( m_eaBuffer ) + 4 ) == *this->begin );
  117. // overwrite JTN with NOP as we won't need JTN
  118. //*this->begin = CELL_GCM_METHOD_NOP;
  119. Assert( pRest >= this->end && this->end - this->begin <= 128 / 4 );
  120. VjobDmaPutf( this->begin, m_eaBuffer, uintp( this->end ) - uintp( this->begin ), VJOB_IOBUFFER_DMATAG, 0, 0 );
  121. }
  122. }
  123. protected:
  124. uint m_eaBuffer;
  125. uint m_nIoOffsetDelta;
  126. protected:
  127. void Callback( uint nCount )
  128. {
  129. DebuggerBreak();
  130. }
  131. static int32_t CallbackDelegator( struct CellGcmContextData *pContext, uint32_t nCount )
  132. {
  133. static_cast<CSpuGcmAlignedBuffer*>( pContext )->Callback( nCount );
  134. return CELL_ERROR_ERROR_FLAG;
  135. }
  136. };
  137. #endif