📄 arrays.hhf
字号:
// Index: Compute the row-major index into an array // given a list of indexes. // // Handles both normal arrays and dynamically // declared arrays. #macro index( _register_, _arrayVar_, _indicies_[] ): _numDims_, _i_, _elementSize_, _tempid_, _pType_; #if( !@IsReg32( _register_ )) #error( "index: First parameter must be a 32-bit register" ); #elseif( array.isItDynamic( _arrayVar_ )) // We've probably got a dynamic array at this point. // (there is the slight chance the user declared a // record containing these fields, but this is highly // unlikely. #if ( @elements( _arrayVar_.dopeVector ) <> @elements( _indicies_ ) ) #error ( @tostring:_arrayVar_ + " has " + string( _numDims_ ) + " dimensions, you provided " + string( @elements( _indicies_ )) + " dimensions" ); #else ?_i_ := 1; mov( @text( _indicies_[0] ), _register_ ); #if( array.boundsChk ) if( _register_ < @dim( _arrayVar_ )[0] ) then raise( ex.ArrayBounds ); endif; #endif #while( _i_ < @elements( _arrayVar_.dopeVector )) intmul( _arrayVar_.dopeVector[ _i_*4 ], _register_ ); add( @text( _indicies_[_i_] ), _register_ ); #if( array.boundsChk ) #if( @isConst( @text( _indicies_[_i_] ) )) #if ( @text( _indicies_[_i_] ) < @dim(_arrayVar_)[_i_] ) #error( "Constant array index out of bounds" ) #print( "index = ", @text( _indicies_[_i_] )) #print( "bound = ", @dim(_arrayVar_)[_i_] ) #endif #else if ( @text( _indicies_[_i_] ) < @dim(_arrayVar_)[_i_] ) then raise( ex.ArrayBounds ); endif; #endif #endif ?_i_:=_i_+1; #endwhile ?_elementSize_ := @Size( @text( @TypeName( _arrayVar_.elementType ))); #if( _elementSize_ = 1 ) // Do nothing #elseif( _elementSize_ = 2 ) shl( 1, _register_ ); #elseif( _elementSize_ = 4 ) shl( 2, _register_ ); #elseif( _elementSize_ = 8 ) shl( 3, _register_ ); #elseif( _elementSize_ = 16 ) shl( 4, _register_ ); #else intmul( _elementSize_, _register_ ); #endif add( _arrayVar_.dataPtr, _register_ ); #endif #else // Assume we've got a standard array. ?_numDims_:uns32 := @arity( _arrayVar_ ); #if( _numDims_ <> @elements( _indicies_ )) #error ( @tostring:_arrayVar_ + " has " + string( _numDims_ ) + " dimensions, you provided " + string( @elements( _indicies_ )) + " dimensions" ); #else ?_i_ := 1; mov( @text( _indicies_[0] ), _register_ ); #if( array.boundsChk ) if( _register_ >= @dim(_arrayVar_)[0] ) then raise( ex.ArrayBounds ); endif; #endif #while( _i_ < @arity( _arrayVar_ )) #if( array.boundsChk ) if( @text( _indicies_[_i_] ) >= @dim(_arrayVar_)[_i_] ) then raise( ex.ArrayBounds ); endif; #endif intmul( @dim(_arrayVar_)[_i_], _register_ ); add( @text( _indicies_[_i_] ), _register_ ); ?_i_:=_i_+1; #endwhile // Locate the base type of this array. ?_pType_ := @pType( @text( @TypeName( _arrayVar_ ))); ?_tempid_ := @TypeName( _arrayVar_ ); #while( _pType_ = hla.ptArray ) ?_tempid_ := @typename( @text( _tempid_ )); ?_pType_ := @pType( @text( _tempid_ )); #endwhile ?_elementSize_ := @Size( @text( _tempid_ )); #if( _elementSize_ = 1 ) lea( _register_, _arrayVar_[ _register_ ] ); #elseif( _elementSize_ = 2 ) lea( _register_, _arrayVar_[ _register_*2 ] ); #elseif( _elementSize_ = 4 ) lea( _register_, _arrayVar_[ _register_*4 ] ); #elseif( _elementSize_ = 8 ) lea( _register_, _arrayVar_[ _register_*8 ] ); #elseif( _elementSize_ = 16 ) shl( 4, _register_ ); lea( _register_, _arrayVar_[ _register_ ] ); #else intmul( _elementSize_, _register_ ); lea( _register_, _arrayVar_[ _register_ ] ); #endif #endif #endif #endmacro/*************************************************************************/ // Utility macros used by some of the following routines: #macro _getArity_( _GAarrayVar_ ); #if( array.isItDynamic( _GAarrayVar_ )) // Okay, it's a dynamic array. // The arity is equal to the number of dopeVector elements. @elements( _GAarrayVar_.dopeVector ) #else // It's not a dynamic array, just return the arity value. @arity( _GAarrayVar_ ) #endif #endmacro // _copyArray_ // // This macro is used by _cpy_ to emit the correct MOVS instruction. #macro _copyArray_( _elementSize_ ); #if( _elementSize_ = 16 ) shl( 2, ecx ); rep.movsd(); #elseif( _elementSize_ = 8 ) shl( 1, ecx ); rep.movsd(); #elseif( _elementSize_ = 4 ) rep.movsd(); #elseif( _elementSize_ = 2 ) shr( 1, ecx ); // Compute # of dwords. pushfd(); rep.movsd(); popfd(); if( @c ) movsw(); endif; #elseif( _elementSize_ = 1 ) rep.movsb(); #else #if( (_elementSize_ & %11) = 0 ) intmul( _elementSize_ div 4, ecx ); rep.movsd(); #elseif( (_elementSize_ & %1) = 0 ) intmul( _elementSize_ shr 1, ecx ); rep.movsw(); #else intmul( _elementSize_, ecx ); rep.movsb(); #endif #endif #endmacro // cpy- // // This copies the data in one array to another: #macro cpy( _src_, _dest_ ): _aritySrc_, _arityDest_, _cpyIndex_, _cpyElements_, _srcType_, _destType_; #if( @defined( _src_.elementType )) ?_srcType_ := @type( _src_.elementType ); #else ?_srcType_ := @type( _src_ ); #endif #if( @defined( _dest_.elementType )) ?_destType_ := @type( _dest_.elementType ); #else ?_destType_ := @type( _dest_ ); #endif ?_aritySrc_ := array._getArity_( @text( @string:_src_) ); ?_arityDest_ := array._getArity_( @text( @string:_dest_) ); #if( _aritySrc_ <> _arityDest_ ) #error( "The shape and sizes of the two arrays must be the same" ); #elseif( _srcType_ <> _destType_ ) #error( "The base types of the two arrays must be the same" ); #else // Verify that the two arrays have the same dimensions: #if( array.isItDynamic( _src_ ) & array.isItDynamic( _dest_ ) ) // Both arrays are dynamic, compare their // bounds at run-time. push( ecx ); push( esi ); push( edi ); ?_cpyIndex_ := 0; mov( 1, ecx ); if (#{ #while( _cpyIndex_ < _aritySrc_ ) mov( _src_.dopeVector[ _cpyIndex_*4 ], edi ); intmul( edi, ecx ); cmp( edi, _dest_.dopeVector[ _cpyIndex_*4 ] ); #if( _cpyIndex_ != _aritySrc_ - 1 ) jne true; #else je false; #endif ?_cpyIndex_ := _cpyIndex_ + 1; #endwhile }#) then raise( ex.ArrayShapeViolation ); endif; // Emit an appropriate memory move instruction: cld(); mov( _src_.dataPtr, esi ); mov( _dest_.dataPtr, edi ); array._copyArray_( @size( _src_.elementType ) ) pop( edi ); pop( esi ); pop( ecx ); #elseif ( array.isItDynamic( _src_ ) & !array.isItDynamic( _dest_ ) ) // The src array is a dynamic array, the // dest array is a static array. Compare // their bounds at run-time push( ecx ); push( esi ); push( edi ); ?_cpyIndex_ := 0; ?_cpyElements_ := 1; if (#{ #while( _cpyIndex_ < _aritySrc_ ) ?_cpyElements_ := _cpyElements_ * @dim( _dest_ )[ _cpyIndex_ ]; cmp ( _src_.dopeVector[ _cpyIndex_*4 ], @dim( _dest_ )[ _cpyIndex_ ] ); #if( _cpyIndex_ != _aritySrc_ - 1 ) jne true; #else je false; #endif ?_cpyIndex_ := _cpyIndex_ + 1; #endwhile }#) then raise( ex.ArrayShapeViolation ); endif; // Emit an appropriate memory move instruction: cld(); mov( _src_.dataPtr, esi ); lea( edi, _dest_ ); mov( _cpyElements_, ecx ); array._copyArray_( @size( _src_.elementType ) ) pop( edi ); pop( esi ); pop( ecx ); #elseif ( !array.isItDynamic( _src_ ) & array.isItDynamic( _dest_ ) ) // The src array is a static array, the // dest array is a dynamic array. Compare // their bounds at run-time. push( ecx ); push( esi ); push( edi ); ?_cpyIndex_ := 0; ?_cpyElements_ := 1; if (#{ #while( _cpyIndex_ < _aritySrc_ ) ?_cpyElements_ := _cpyElements_ * @dim( _src_ )[ _cpyIndex_ ]; cmp ( _dest_.dopeVector[ _cpyIndex_*4 ], @dim( _src_ )[ _cpyIndex_ ] ); #if( _cpyIndex_ != _aritySrc_ - 1 ) jne true; #else je false; #endif ?_cpyIndex_ := _cpyIndex_ + 1; #endwhile }# )then raise( ex.ArrayShapeViolation ); endif; // Emit an appropriate memory move instruction: cld(); mov( _dest_.dataPtr, edi ); lea( esi, _src_ ); mov( _cpyElements_, ecx ); array._copyArray_( @size( _dest_.elementType ) ) pop( edi ); pop( esi ); pop( ecx ); #else // Both arrays are static arrays. Compare // their bounds at compile-time. push( ecx ); push( esi ); push( edi ); ?_cpyIndex_ := 0; ?_cpyElements_ := 1; #while( _cpyIndex_ < _aritySrc_ ) ?_cpyElements_ := _cpyElements_ * @dim( _src_ )[ _cpyIndex_ ]; #if ( @dim( _src_ )[_cpyIndex_] <> @dim( _dest_ )[_cpyIndex_] ) #error( "Array shapes must be the same" ) #endif ?_cpyIndex_ := _cpyIndex_ + 1; #endwhile // Emit an appropriate memory move instruction: cld(); lea( edi, _dest_ ); lea( esi, _src_ ); mov( _cpyElements_, ecx ); array._copyArray_( @size( @text( @typename( _src_ ))) ) pop( edi ); pop( esi ); pop( ecx ); #endif #endif #endmacro/*************************************************************************/ // reduce- // // This macro does a row reduction. That is, it eliminates // one dimension of the array using a user-defined sequence // of instructions. // // Syntax: // // array.reduce( srcArray, destArray ) // // <<instrs to perform before reduction>> // // array.beforeRow // // <<instrs to execute before each row is reduced>> // // array.reduction // // <<instrs to perform on each element of the // row being reduce. Note: ESI contains the // index into the source array, EAX & EDX are (the // only registers) free for use.>> // // array.afterRow // // <<instrs to execute after the row is reduced. // Note: EDI contains an index into the // destination array. EAX & EDX are (the only // registers) free for use.>> // // array.endreduce; #macro reduce ( _theSrc_, _theDest_ ): _dimIndex_, _dimSrc_, _dimDest_, _arityDest_, _aritySrc_, _goodShape_, _DidBeforeRow_, _DidReduce_, _DidAfterRow_, _ElementSize_, _DestElementSize_, _NumIterations_, _BadArity_, _GoodArity_; ?_DidBeforeRow_ := false; ?_DidAfterRow_ := false; ?_DidReduce_ := false; #if( array.isItDynamic( _theSrc_ )) ?_aritySrc_ := @elements( _theSrc_.dopeVector ); ?_ElementSize_ := @size ( @text( @typename( _theSrc_.elementType )) ); #else ?_aritySrc_ := @arity( _theSrc_ ); ?_ElementSize_ := @size( _theSrc_ ) div @elements( _theSrc_ ); #endif #if( array.isItDynamic( _theDest_ )) ?_arityDest_ := @elements( _theDest_.dopeVector ); ?_DestElementSize_ := @size ( @text( @typename( _theDest_.elementType )) ); #else ?_arityDest_ := @arity( _theDest_ ); ?_DestElementSize_ := @size( _theDest_ ) div @elements( _theDest_ ); #endif push( ecx ); push( esi ); push( edi ); #if( _ElementSize_ <> _DestElementSize_ ) #error( "Array elements must be the same size" ) ?_goodShape_ := false; #elseif( _aritySrc_ <> _arityDest_ + 1 ) #error ( "Destination array must have one " "fewer dimensions than the source array" ) ?_goodShape_ := false;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -