📄 arrays.hhf
字号:
// Begin by checking to see if the highest dimension // is _xpos_. If so, use loop counter zero as the // index value. If not, use loop counter n (n=arity-1) // as the index value. ?_i_ := @arity( _destArray_ ) - 1; #if( _i_ = _xpos_ ) mov( (type dword [esp] ), edi ); #else mov ( (type dword [esp + _i_*4] ), edi ); #endif // Okay, for all dimensions except _xpos_ and zero, // compute the row-major offset into the array. // Swap indicies zero and _xpos_. Note that _xpos_ // may have been handled above. ?_i_ := _i_ - 1; #while( _i_ > 0 ) array.mulbyConst ( @dim( _destArray_ )[_i_], edi ); #if( _i_ = _xpos_ ) add( [esp], edi ); #else add( [esp+_i_*4], edi ); #endif ?_i_ := _i_ - 1; #endwhile array.mulbyConst( _dstd_[_xpos_], edi ); add( [esp + _xpos_*4], edi ); // Okay, EDI is the index into the destination array. // ESI contains the pointer at the current source // element. Copy the data from the source array to // the destination array. #if( _dSize_ = 1 ) mov( [esi], al ); mov( al, [ebx+edi] ); inc( esi ); #elseif( _dSize_ = 2 ) mov( [esi], ax ); mov( ax, [ebx+edi*2] ); add( 2, esi ); #elseif( _dSize_ = 4 ) mov( [esi], eax ); mov( eax, [ebx+edi*4] ); add( 4, esi ); #else mov( [esi], eax ); mov( [esi+4], edx ); mov( eax, [ebx+edi*8] ); mov( edx, [ebx+edi*8+4] ); add( 8, esi ); #endif ?_i_ := 0; #while( _i_ < @arity( _destArray_ )) endfor; ?_i_ := _i_ + 1; #endwhile // Remove loop control variables from the stack. add( @arity( _destArray_ ) * 4, esp ); // Remove registers from the stack: pop( edi ); pop( esi ); pop( ebx ); pop( eax ); #endif #endif #else // Both arrays must be static. ?_srcd_ := @dim( _srcArray_ ); ?_dstd_ := @dim( _destArray_ ); ?_sSize_ := @ElementSize( _srcArray_ ); ?_dSize_ := @ElementSize( _destArray_ ); #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" ); #elseif ( @arity( _srcArray_ ) <= _xpos_ | @arity( _destArray_ ) <= _xpos_ | @arity( _srcArray_ ) <> @arity( _destArray_ ) ) #error ( "array.transpose:" nl "Arrays must have at least " + string( _xpos_ ) + " dimensions" nl "and they must have the same number of dimensions" ); #else // Verify that the shapes of the arrays are reasonable. #if ( _srcd_[0] <> _dstd_[_xpos_] | _srcd_[_xpos_] <> _dstd_[0] ) #error ( "array.transpose:" nl "Array shapes are incorrect" ); #else ?_i_ := 1; #while( _i_ < @arity( _destArray_ )) #if( _i_ <> _xpos_ ) #if( _srcd_[_i_] <> _dstd_[_i_] ) #error ( "array.transpose:" nl "Array shapes are incompatible" ) #endif #endif ?_i_ := _i_ + 1; #endwhile #endif // Optimize the most common case (transposing // a two-dim array or the last two dimensions // of an array). #if( _xpos_ = 1 ) push( eax ); push( ebx ); push( ecx ); push( edx ); push( esi ); push( edi ); lea( ebx, _srcArray_ ); lea( ecx, [ebx + @size( _srcArray_ )] ); push( ecx ); lea( ecx, _destArray_ ); sub( _dstd_[0] * _dstd_[1] * _dSize_, ecx ); while( ebx < [esp] ) do add( _dstd_[0] * _dstd_[1] * _dSize_, ecx ); for( mov(0, esi ); esi < _dstd_[0]; inc( esi )) do for ( mov( 0, edi ); edi < _dstd_[_xpos_]; inc( edi ) ) do #if( _sSize_ = 1 ) intmul( _dstd_[0], edi, edx ); add( esi, edx ); mov( [ebx], al ); mov( al, [ecx+edx] ); inc( ebx ); #elseif( _sSize_ = 2 ) intmul( _dstd_[0], edi, edx ); add( esi, edx ); mov( [ebx], ax ); mov( ax, [ecx+edx*2] ); add( 2, ebx ); #elseif( _sSize_ = 4 ) intmul( _dstd_[0], edi, edx ); add( esi, edx ); mov( [ebx], eax ); mov( eax, [ecx+edx*4] ); add( 4, ebx ); #elseif( _sSize) = 8 ) intmul( _dstd_[0], edi, 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( 4, 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 // Make room for a set of loop control variables // on the stack: push( eax ); push( ebx ); push( esi ); push( edi ); lea( esi, _srcArray_ ); lea( ebx, _destArray_ ); sub( @arity( _destArray_ ) * 4, esp ); ?_i_ := @arity( _destArray_ ); #while( _i_ > 0 ) ?_offset_ := ( _i_ - 1 ) * 4; for ( mov(0, (type dword [esp+_offset_])); (type dword [esp+_offset_]) < _dstd_[_i_ - 1]; inc( (type dword [esp+_offset_])) ) do ?_i_ := _i_ - 1; #endwhile // Compute index into the destination array. // Note: to properly transpose, we need to // swap the zero index with the _xpos_ index. // // Begin by checking to see if the highest dimension // is _xpos_. If so, use loop counter zero as the // index value. If not, use loop counter n (n=arity-1) // as the index value. ?_i_ := @arity( _destArray_ ) - 1; #if( _i_ = _xpos_ ) mov( (type dword [esp] ), edi ); #else mov ( (type dword [esp + _i_*4] ), edi ); #endif // Okay, for all dimensions except _xpos_ and zero, // compute the row-major offset into the array. // Swap indicies zero and _xpos_. Note that _xpos_ // may have been handled above. ?_i_ := _i_ - 1; #while( _i_ > 0 ) array.mulbyConst ( _dstd_[_i_], edi ); #if( _i_ = _xpos_ ) add( [esp], edi ); #else add( [esp+_i_*4], edi ); #endif ?_i_ := _i_ - 1; #endwhile array.mulbyConst( _dstd_[_xpos_], edi ); add( [esp + _xpos_*4], edi ); // Okay, EDI is the index into the destination array. // ESI contains the pointer at the current source // element. Copy the data from the source array to // the destination array. #if( _dSize_ = 1 ) mov( [esi], al ); mov( al, [ebx+edi] ); inc( esi ); #elseif( _dSize_ = 2 ) mov( [esi], ax ); mov( ax, [ebx+edi*2] ); add( 2, esi ); #elseif( _dSize_ = 4 ) mov( [esi], eax ); mov( eax, [ebx+edi*4] ); add( 4, esi ); #else mov( [esi], eax ); mov( [esi+4], edx ); mov( eax, [ebx+edi*8] ); mov( edx, [ebx+edi*8+4] ); add( 8, esi ); #endif ?_i_ := 0; #while( _i_ < @arity( _destArray_ )) endfor; ?_i_ := _i_ + 1; #endwhile // Remove loop control variables from the stack. add( @arity( _destArray_ ) * 4, esp ); // Remove registers from the stack: pop( edi ); pop( esi ); pop( ebx ); pop( eax ); #endif #endif #endif #endmacro/*************************************************************************///// print( array, minwidth, decpts ) #macro print( _arrayToPrint_, _fmt_[] ): _dims_, _Arity_, _fmtOptions_, _elementTypeName_; #if( @elements( _fmt_ ) = 0 ) ?_fmtOptions_:text := ""; #elseif( @elements( _fmt_ ) = 1 ) ?_fmtOptions_:text := ":" + _fmt_[0]; #elseif( @elements( _fmt_ ) = 2 ) ?_fmtOptions_:text := ":" + _fmt_[0] + ":" + _fmt_[1]; #else #error( "array.print: too many parameters" ); ?_fmtOptions_:text := ""; #endif push( eax ); push( edx ); push( esi ); push( edi ); #if( !array.isItDynamic( _arrayToPrint_ )) ?_dims_ := @dim( _arrayToPrint_ ); ?_Arity_ := @arity( _arrayToPrint_ ); xor( esi, esi ); mov( 1, edi ); while( edi <= @elements( _arrayToPrint_ ) ) do stdout.put( _arrayToPrint_[ esi ] _fmtOptions_ ); #if( _Arity_ > 1 ) mov( edi, eax ); cdq(); div( _dims_[ 0 ], edx:eax ); if( !edx ) then stdout.newln(); #if( _Arity_ > 2 ) mov( edi, eax ); cdq(); div( _dims_[0] * _dims_[1], edx:eax ); if( !edx ) then stdout.newln(); endif; #endif else stdout.put( ", " ); endif; #endif add( @ElementSize( _arrayToPrint_ ), esi ); inc( edi ); endwhile; #else ?_Arity_ := 1; push( ecx ); push( ebx ); mov( _arrayToPrint_.dopeVector[0], ecx ); mov( _arrayToPrint_.dataPtr, esi ); #while( _Arity_ < @elements( _arrayToPrint_.dopeVector ) ) intmul( _arrayToPrint_.dopeVector[ _Arity_*4 ], ecx ); ?_Arity_ := _Arity_ + 1; #endwhile mov( _arrayToPrint_.dataPtr, esi ); mov( 1, edi ); while( edi <= ecx ) do ?_elementTypeName_:text := @typename( _arrayToPrint_.elementType ); stdout.put ( (type _elementTypeName_ [ esi ]) _fmtOptions_ ); #if( @elements( _arrayToPrint_.dopeVector ) > 1 ) mov( edi, eax ); cdq(); div ( (type uns32 _arrayToPrint_.dopeVector[0]), edx:eax ); if( !edx ) then stdout.newln(); #if( _Arity_ > 2 ) mov( _arrayToPrint_.dopeVector[ 0 ], ebx ); intmul( _arrayToPrint_.dopeVector[ 4 ], ebx ); mov( edi, eax ); cdq(); div( ebx, edx:eax ); if( !edx ) then stdout.newln(); endif; #endif else stdout.put( ", " ); endif; #endif add( @Size( _arrayToPrint_.elementType ), esi ); inc( edi ); endwhile; pop( ebx ); pop( ecx ); #endif pop( edi ); pop( esi ); pop( edx ); pop( eax ); // Deallocate compile-time storage for _dims_ ?_dims_ := 0; #endmacro/*************************************************************************///// lookupTable-//// Generate a lookup table (only in the read-only data section)//// Usage://// someID: // array.lookupTable// ( // elementType,// defaultCaseLabel, // tableValue:indexList, // tableValue:indexList, // ... // );//// For each value in the indexList list of values, this macro inserts// the "tableValue" into the array at each specified index, e.g.,//// luTable : // array.lookupTable// (// dword, // Data type// $ff, // Default value for empty holes.// 10: 9, // 11: 10, // 12: 0, // 13: 5, // 14: 12, // 15: 8, // 16: 16, // 18: 14 15, // 19: 6 7 11 13, // 20: 1 // );//// This creates the following array://// luTable:dword[17] :=// [// 12, // from 12:0// 20, // from 20:1// $ff,// $ff,// $ff,// 13, // from 13:5// 19, // from 19:6 7 11 13// 19, // " " " "// 15, // from 15:8// 10, // from 10:9// 11, // from 11:10// 19, // from 19:6 7 11 13// 14, // from 14:12// 19, // from 19:6 7 11 13// 18, // from 18:14 15// 18, // from 18:14 15// 16 // from 16:16// ];//// This macro serves as a "data type" declaration returning the type and// constant data for a lookup table. It also defines the following constants://// someID_minValue - Minimum lookup value appearing in the table.// someID_minIndex - Minimum lookup value times the size of a table entry.//// someID_maxValue - Maximum lookup value appearing in the table.// someID_maxIndex - Maximum lookup value times the size of a table entry.// Constants you may want to change to control warnings emitted by// the mwjmp macro:val maxCases := 4096; // Maximum # of cases we will allow largeTable := 256; // A "large" table has at least 256 entries sparseTable := 4; // A "sparse" table is one that has 4x as // many (or more) unused entries as it has // actual entries.type caseRecord: record value :dword; lblStr :string; endrecord; val cases :caseRecord[ maxCases ] := maxCases dup [caseRecord:[0,""]]; leftItem :caseRecord := caseRecord:[ 0, "" ]; rightItem :caseRecord := caseRecord:[ 0, "" ]; #macro lessThan; (array.leftItem.value < array.rightItem.value) #endmacro #macro lookupTable( tableType, _defaultCase_, _entries_[] ): _boundsError_, _numEntries_, _i_, _j_, _k_, _m_, _endLabel_, _tableValue_, _valueList_, _slots_, _minLabel_, _maxLabel_, _tableID_; // First, save the label applied to this array so we // can generate the minLabel later. forward( _tableID_ ); ?_numEntries_ := @elements( _entries_ ); // Okay, parse each of the arguments and extract the constant // and label c
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -