⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 arrays.hhf

📁 High Level assembly language(HLA)软件
💻 HHF
📖 第 1 页 / 共 5 页
字号:
		#else			// Verify the shapes of the two arrays.			// The dest must have one less dimension than the			// source (that was checked above) and except for			// the dimension in src specified by _theDim_, each			// src dimension must match the corresponding			// dest dimension.			//			// Note: If either, or both, of the arrays are dynamic,			// the check must be done at run-time.  If both arrays			// are static, then the check can be done at compile time.			#if			( 					!array.isItDynamic( _theSrc_ ) 				&	!array.isItDynamic( _theDest_ )			)				// Both arrays are static, do the check at compile-time.				?_dimSrc_ := @dim( _theSrc_ );				?_dimDest_ := @dim( _theDest_ );				?_dimIndex_ := 0;				?_NumIterations_ := 1;				?_goodShape_ := true;				#while( _dimIndex_ < _arityDest_ )					#if( _dimSrc_[ _dimIndex_ ] <> _dimDest_[ _dimIndex_ ] )						#error( "reduce: illegal destination shape" )						?_goodShape_ := false;					#endif					?_NumIterations_ := 						_NumIterations_ * _dimSrc_[ _dimIndex_ ];					?_dimIndex_ := _dimIndex_ + 1;				#endwhile			#elseif			(					array.isItDynamic( _theSrc_ ) 				&	!array.isItDynamic( _theDest_ )			)				// The source array is dynamic, must check the				// dimensions at run-time.				?_dimDest_ := @dim( _theDest_ );				?_goodShape_ := true;				?_NumIterations_ := 1;				?_dimIndex_ := 0;				#if( _arityDest_ <> 0 )					#while( _dimIndex_ < _arityDest_ - 1 )						cmp						( 							_theSrc_.dopeVector[ _dimIndex_*4 ], 							_dimDest_[ _dimIndex_ ] 						);						jne _BadArity_;						?_NumIterations_ := 							_NumIterations_ * _dimDest_[ _dimIndex_ ];						?_dimIndex_ := _dimIndex_ + 1;					#endwhile					cmp					(						_theSrc_.dopeVector[ (_arityDest_ - 1)*4 ],						_dimDest_[ _arityDest_ - 1 ]					);					je _GoodArity_;					_BadArity_:						raise( ex.ArrayShapeViolation );					_GoodArity_:					?_NumIterations_ := 						_NumIterations_ * _dimDest_[ _arityDest_ - 1 ];				#endif			#elseif			(					!array.isItDynamic( _theSrc_ ) 				&	array.isItDynamic( _theDest_ )			)				// The destination array is dynamic, must check the				// dimensions at run-time.				?_dimSrc_ := @dim( _theSrc_ );				?_goodShape_ := true;				?_NumIterations_ := 1;				?_dimIndex_ := 0;				#if( _aritySrc_ - 1 <> 0 )					#while( _dimIndex_ < _aritySrc_ - 2 )						cmp						( 							_theDest_.dopeVector[ _dimIndex_*4 ], 							_dimSrc_[ _dimIndex_ ] 						);						jne _BadArity_;						?_dimIndex_ := _dimIndex_ + 1;						?_NumIterations_ := 							_NumIterations_ * _dimSrc_[ _dimIndex_ ];					#endwhile					cmp					(						_theDest_.dopeVector[ (_aritySrc_ - 2)*4 ],						_dimSrc_[ _aritySrc_ - 2 ]					);					je _GoodArity_;					_BadArity_:						raise( ex.ArrayShapeViolation );					_GoodArity_:					?_NumIterations_ := 						_NumIterations_ * _dimSrc_[ _aritySrc_ - 2 ];				#else					#error( "Source array must have at least one dimension" )					?_goodShape_ := false;				#endif			#else				// Both arrays are dynamic, so we must check the				// dimensions at run-time.				push( eax );				mov( 1, eax );				mov( @elements( _theDest_.dopeVector ), ecx );				while( ecx > 0 ) do					mov( _theSrc_.dopeVector[ ecx*4-4 ], esi );					cmp( esi, _theDest_.dopeVector[ ecx*4-4 ] );					je _GoodArity_;						raise( ex.ArrayShapeViolation );					_GoodArity_:					intmul( esi, eax );					dec( ecx );				endwhile;				?_goodShape_ := true;				intmul( _ElementSize_, eax );				xchg( eax, [esp] );			#endif		#endif	#keyword beforeRow;		#if( _goodShape_ & !_DidBeforeRow_ )			#if			( 					!array.isItDynamic( _theSrc_ ) 				|	!array.isItDynamic( _theDest_ )			)				// Construct the for loop that will generate				// the reduction.  Note that at least one				// of the arrays is a static array, so we				// can use the _NumIterations_ constant.				xor( esi, esi );				for				( 					xor( edi, edi );					edi < _NumIterations_ * _ElementSize_;					add( _ElementSize_, edi) 				) do			#else				// As above, but both arrays are dynamic.				// The number of loop iterations can be				// found on the top of the stack.				xor( esi, esi );				for				( 					xor( edi, edi );					edi < [esp];					add( _ElementSize_, edi) 				) do			#endif		#endif		?_DidBeforeRow_ := true;	#keyword reduction:_srcDims_;		#if( !_DidBeforeRow_ )			#error			( 				"'beforeRow' section must precede the 'reduction' section" 			)			?_DidEachRow_ := true; // So we don't get two messages.		#endif		#if( _goodShape_ & !_DidReduce_ )			// Emit the for loop that indexes through the			// array elements we are reducing:			#if( !array.isItDynamic( _theSrc_ ))				?_srcDims_ := @dim( _theSrc_ );				for				(					xor( ecx, ecx );					ecx < _srcDims_[ @elements( _srcDims_ ) - 1 ];					inc( ecx )				) do			#else				push				( 					_theSrc_.dopeVector					[ 						( @elements( _theSrc_.dopeVector ) - 1 ) * 4					] 				);				for				(					xor( ecx, ecx );					ecx < [esp];					inc( ecx )				) do			#endif					#endif		?_DidReduce_ := true;		#keyword afterRow;		#if( !_DidBeforeRow_ )			#error( "Missing 'beforeRow' and 'reduction' sections" )			?_DidBeforeRow_ := true;		#elseif( !_DidReduce_ )			#error( "Missing 'reduction' section" )			?_DidReduce_ := true;		#else			// Bump up the index into the array by the size of			// a single array element:			add( _ElementSize_, esi );			// Endfor that matches the innermost loop:						endfor;			// If the source array is a dynamic array, remove			// the ending loop index from the stack:			#if( array.isItDynamic( _theSrc_ ))				add( 4, esp );			#endif		#endif		?_DidAfterRow_ := true;	#terminator endreduce;		#if( _goodShape_ )			#if( !_DidBeforeRow_ )				#error				( 					"Missing 'beforeRow', 'reduction', "					"and 'afterRow' sections" 				)			#elseif( !_DidReduce_ )				#error( "Missing 'reduction' and 'afterRow' sections" )			#elseif( !_DidAfterRow_ )				#error( "Missing 'afterRow' section" )			#else				// Emit the endfor for the enclosing loop.				endfor;				// If both arrays were dynamic, we need to remove				// the ending loop index from the stack:				#if				(						array.isItDynamic( _theSrc_ )					&	array.isItDynamic( _theDest_ )				)					add( 4, esp );				#endif			#endif		#endif		pop( edi );		pop( esi );		pop( ecx );	#endmacro/*************************************************************************/	#macro mulbyConst( src1, dest );		#if( src1 = 1 )			mov( src2, dest );		#elseif( src1 = 2 )			shl( 1, dest );		#elseif( src1 = 4 )			shl( 2, dest );		#elseif( src1 = 8 )			shl( 3, dest );		#elseif( src1 = 16 )			shl( 4, dest );		#else			intmul( src1, dest );		#endif	#endmacro	#macro transpose( _srcArray_, _destArray_, _xposDim_[] ):		_xpos_,		_offset_,		_srcd_,		_dstd_,		_dSize_,		_sSize_;		// See if the third parameter is present.		// If so, verify that it is an integer constant		// falling in the range 0..arity( _srcArray_ ) - 1		#if( @Elements( _xposDim_ ) = 0 )			// If third parameter is not present, default the			// transpose dimension to one.			?_xpos_ := 1;		#elseif( @Elements( _xposDim_ ) = 1 )			// If we've got a third parameter, verify that			// it is a constant.			#if( !@IsConst( @text( _xposDim_[0] )))				#error				(					"array.transpose:" nl					"Expected a constant for the transpose dimension"				);			#else				// If the third parameter is a constant, verify that				// it is a numeric constant.				?_xpos_ := @text( _xposDim_[0] );				#if( !hla.isNumber( _xpos_ ))					#error					(						"array.transpose:" nl						"Transpose dimension parameter must be an integer"					)					?_xpos_ := 1;				#endif			#endif		#else			#error			(				"array.transpose:" nl				"Too many parameters"			);			?_xpos_ := 1;		#endif		// It is illegal to transpose dimension zero since that's		// the other dimension we're working with.  Also, negative		// dimensions don't make sense, so check that here as well.		#if( _xpos_ <= 0 )			#error			(				"array.transpose:" nl				"Transpose dimension must be one or greater"			);			?_xpos_ := 1;		#endif		// Handle the case where both arrays are dynamic:		#if		( 				array.isItDynamic( _srcArray_ ) 			&	array.isItDynamic( _destArray_ )		)			// Check the element sizes statically to ensure			// they are reasonable and are the same size.			?_sSize_ := @Size( _srcArray_.elementType );			?_dSize_ := @Size( _destArray_.elementType );			#if			(					_sSize_ <> 1				&	_sSize_ <> 2				&	_sSize_ <> 4				&	_sSize_ <> 8				&	_sSize_ <> _dSize_			)				#error				(					"array.transpose: " nl					"Can only handle arrays with 1, 2, 4, or 8 byte elements"				);			#else				// We must check for proper array shapes at run-time				// since we don't know the dest array dimensions				// until then.				push( eax );				if				(#{					?_i_ := 1;					#while( _i_ < @Elements( _srcArray_.dopeVector ))						#if( _i_ <> _xpos_ )							mov( _srcArray_.dopeVector[_i_*4], eax );							cmp							(								eax,								_destArray_.dopeVector[_i_*4]							);							jne true;						#endif						?_i_ := _i_ + 1;					#endwhile										mov( _srcArray_.dopeVector[0], eax ); 					cmp( eax, _destArray_.dopeVector[0] );					jne true;					mov( _srcArray_.dopeVector[_xpos_*4], eax );					cmp( eax, _destArray_.dopeVector[_xpos_*4] );					je false;				}#) then					raise( ex.ArrayShapeViolation );				endif;								// Optimize the most common case (transposing				// a two-dim array or the last two dimensions				// of an array).				#if( _xpos_ = 1 )					push( ebx );					push( ecx );					push( edx );					push( esi );					push( edi );					// Note: assume that the src and dest array					// sizes are the same.					//					// Begin by computing the size of the					// matrix composed of the lower two dimensions.					// The loop below uses this value.					mov( _srcArray_.dopeVector[0], ecx );					intmul( _srcArray_.dopeVector[4], ecx );					#if( _sSize_ = 2 )						shl( 1, ecx );					#elseif( _sSize_ = 4 )						shl( 2, ecx );					#elseif( _sSize_ = 8 )						shl( 3, ecx );					#endif					push( ecx );	// Save matrix size at [esp+4].					// Compute the size of the entire matrix and					// the compute the address of the last element					// of the source array so we can use this as					// a loop termination value.					?_i_ := 2;					#while( _i_ < @Elements( _srcArray_.dopeVector ) )						intmul( _srcArray_.dopeVector[_i_*4], ecx );						?_i_ := _i_ + 1;					#endwhile					mov( _srcArray_.dataPtr, ebx );					add( ebx, ecx );					push( ecx );	// Save ptr to last src element at [esp].					// Compute the starting address of the first element					// of the destination array, noting that will will					// adjust the block size on the first iteration of					// the loop, below.					mov( _destArray_.dataPtr, ecx );					sub( [esp+4], ecx );					while( ebx < [esp] ) do						add( [esp+4], ecx );						for						( 							mov(0, esi ); 							esi < _srcArray_.dopeVector[0]; 							inc( esi )						) do							for							( 								mov( 0, edi ); 								edi < _srcArray_.dopeVector[4]; 								inc( edi )							) do								#if( _sSize_ = 1 )									mov( edi, edx );									intmul( _destArray_.dopeVector[0], edx );									add( esi, edx );									mov( [ebx], al );									mov( al, [ecx+edx] );									inc( ebx );								#elseif( _sSize_ = 2 )									mov( edi, edx );									intmul( _destArray_.dopeVector[0], edx );									add( esi, edx );									mov( [ebx], ax );									mov( ax, [ecx+edx*2] );									add( 2, ebx );								#elseif( _sSize_ = 4 )									mov( edi, edx );									intmul( _destArray_.dopeVector[0], edx );									add( esi, edx );									mov( [ebx], eax );									mov( eax, [ecx+edx*4] );									add( 4, ebx );								#else									mov( edi, edx );									intmul( _destArray_.dopeVector[0], edx );									add( esi, edx );									mov( [ebx], eax );									mov( eax, [ecx+edx*8] );									mov( [ebx+4], eax );									mov( eax, [ecx+edx*8+4] );									add( 8, ebx );								#endif							endfor;						endfor;					endwhile;					add( 8, esp );					pop( edi );					pop( esi );					pop( edx );					pop( ecx );					pop( ebx );					pop( eax );								// Okay, handle the case where we are not transposing				// the last two dimensions of the array.  This one is				// ugly and less efficient (hence the special case				// above).				#else					push( ebx );					push( esi );					push( edi );					// Make room for a set of loop control variables					// on the stack:					sub( @arity( _srcArray_ ) * 4, esp );					// Initialize array base pointers.					mov( _destArray_.dataPtr, ebx );					mov( _srcArray_.dataPtr, esi );					// Emit the for loops that will do the					// transposition.					?_i_ := @Elements( _srcArray_.dopeVector );					#while( _i_ > 0 )						?_offset_ := ( _i_ - 1 ) * 4;						mov(0, (type dword [esp+_offset_]));						while({							mov( (type dword [esp+_offset_]), eax );							cmp( eax, _srcArray_.dopeVector[ _i_*4 - 4 ] );							jae false;						}) do

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -