URL
https://opencores.org/ocsvn/openrisc/openrisc/trunk
Subversion Repositories openrisc
[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [zlib/] [contrib/] [masm686/] [match.asm] - Rev 745
Compare with Previous | Blame | View Log
; match.asm -- Pentium-Pro optimized version of longest_match();; Updated for zlib 1.1.3 and converted to MASM 6.1x; Copyright (C) 2000 Dan Higdon <hdan@kinesoft.com>; and Chuck Walbourn <chuckw@kinesoft.com>; Corrections by Cosmin Truta <cosmint@cs.ubbcluj.ro>;; This is free software; you can redistribute it and/or modify it; under the terms of the GNU General Public License.; Based on match.S; Written for zlib 1.1.2; Copyright (C) 1998 Brian Raiter <breadbox@muppetlabs.com>;; Modified by Gilles Vollant (2005) for add gzhead and gzindex.686P.MODEL FLAT;===========================================================================; EQUATES;===========================================================================MAX_MATCH EQU 258MIN_MATCH EQU 3MIN_LOOKAHEAD EQU (MAX_MATCH + MIN_MATCH + 1)MAX_MATCH_8 EQU ((MAX_MATCH + 7) AND (NOT 7));===========================================================================; STRUCTURES;===========================================================================; This STRUCT assumes a 4-byte alignmentDEFLATE_STATE STRUCTds_strm dd ?ds_status dd ?ds_pending_buf dd ?ds_pending_buf_size dd ?ds_pending_out dd ?ds_pending dd ?ds_wrap dd ?; gzhead and gzindex are added in zlib 1.2.2.2 (see deflate.h)ds_gzhead dd ?ds_gzindex dd ?ds_data_type db ?ds_method db ?db ? ; paddingdb ? ; paddingds_last_flush dd ?ds_w_size dd ? ; usedds_w_bits dd ?ds_w_mask dd ? ; usedds_window dd ? ; usedds_window_size dd ?ds_prev dd ? ; usedds_head dd ?ds_ins_h dd ?ds_hash_size dd ?ds_hash_bits dd ?ds_hash_mask dd ?ds_hash_shift dd ?ds_block_start dd ?ds_match_length dd ? ; usedds_prev_match dd ? ; usedds_match_available dd ?ds_strstart dd ? ; usedds_match_start dd ? ; usedds_lookahead dd ? ; usedds_prev_length dd ? ; usedds_max_chain_length dd ? ; usedds_max_laxy_match dd ?ds_level dd ?ds_strategy dd ?ds_good_match dd ? ; usedds_nice_match dd ? ; used; Don't need anymore of the struct for matchDEFLATE_STATE ENDS;===========================================================================; CODE;===========================================================================_TEXT SEGMENT;---------------------------------------------------------------------------; match_init;---------------------------------------------------------------------------ALIGN 4PUBLIC _match_init_match_init PROC; no initialization neededret_match_init ENDP;---------------------------------------------------------------------------; uInt longest_match(deflate_state *deflatestate, IPos curmatch);---------------------------------------------------------------------------ALIGN 4PUBLIC _longest_match_longest_match PROC; Since this code uses EBP for a scratch register, the stack frame must; be manually constructed and referenced relative to the ESP register.; Stack image; Variableschainlenwmask = 0 ; high word: current chain len; low word: s->wmaskwindow = 4 ; local copy of s->windowwindowbestlen = 8 ; s->window + bestlenscanend = 12 ; last two bytes of stringscanstart = 16 ; first two bytes of stringscanalign = 20 ; dword-misalignment of stringnicematch = 24 ; a good enough match sizebestlen = 28 ; size of best match so farscan = 32 ; ptr to string wanting matchvarsize = 36 ; number of bytes (also offset to last saved register); Saved Registers (actually pushed into place)ebx_save = 36edi_save = 40esi_save = 44ebp_save = 48; Parametersretaddr = 52deflatestate = 56curmatch = 60; Save registers that the compiler may be usingpush ebppush edipush esipush ebx; Allocate local variable spacesub esp,varsize; Retrieve the function arguments. ecx will hold cur_match; throughout the entire function. edx will hold the pointer to the; deflate_state structure during the function's setup (before; entering the main loop).mov edx, [esp+deflatestate]ASSUME edx:PTR DEFLATE_STATEmov ecx, [esp+curmatch]; uInt wmask = s->w_mask;; unsigned chain_length = s->max_chain_length;; if (s->prev_length >= s->good_match) {; chain_length >>= 2;; }mov eax, [edx].ds_prev_lengthmov ebx, [edx].ds_good_matchcmp eax, ebxmov eax, [edx].ds_w_maskmov ebx, [edx].ds_max_chain_lengthjl SHORT LastMatchGoodshr ebx, 2LastMatchGood:; chainlen is decremented once beforehand so that the function can; use the sign flag instead of the zero flag for the exit test.; It is then shifted into the high word, to make room for the wmask; value, which it will always accompany.dec ebxshl ebx, 16or ebx, eaxmov [esp+chainlenwmask], ebx; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;mov eax, [edx].ds_nice_matchmov ebx, [edx].ds_lookaheadcmp ebx, eaxjl SHORT LookaheadLessmov ebx, eaxLookaheadLess:mov [esp+nicematch], ebx;/* register Bytef *scan = s->window + s->strstart; */mov esi, [edx].ds_windowmov [esp+window], esimov ebp, [edx].ds_strstartlea edi, [esi+ebp]mov [esp+scan],edi;/* Determine how many bytes the scan ptr is off from being */;/* dword-aligned. */mov eax, edineg eaxand eax, 3mov [esp+scanalign], eax;/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */;/* s->strstart - (IPos)MAX_DIST(s) : NIL; */mov eax, [edx].ds_w_sizesub eax, MIN_LOOKAHEADsub ebp, eaxjg SHORT LimitPositivexor ebp, ebpLimitPositive:;/* int best_len = s->prev_length; */mov eax, [edx].ds_prev_lengthmov [esp+bestlen], eax;/* Store the sum of s->window + best_len in %esi locally, and in %esi. */add esi, eaxmov [esp+windowbestlen], esi;/* register ush scan_start = *(ushf*)scan; */;/* register ush scan_end = *(ushf*)(scan+best_len-1); */;/* Posf *prev = s->prev; */movzx ebx, WORD PTR[edi]mov [esp+scanstart], ebxmovzx ebx, WORD PTR[eax+edi-1]mov [esp+scanend], ebxmov edi, [edx].ds_prev;/* Jump into the main loop. */mov edx, [esp+chainlenwmask]jmp SHORT LoopEntry;/* do {; * match = s->window + cur_match;; * if (*(ushf*)(match+best_len-1) != scan_end ||; * *(ushf*)match != scan_start) continue;; * [...]; * } while ((cur_match = prev[cur_match & wmask]) > limit; * && --chain_length != 0);; *; * Here is the inner loop of the function. The function will spend the; * majority of its time in this loop, and majority of that time will; * be spent in the first ten instructions.; *; * Within this loop:; * %ebx = scanend; * %ecx = curmatch; * %edx = chainlenwmask - i.e., ((chainlen << 16) | wmask); * %esi = windowbestlen - i.e., (window + bestlen); * %edi = prev; * %ebp = limit; */ALIGN 4LookupLoop:and ecx, edxmovzx ecx, WORD PTR[edi+ecx*2]cmp ecx, ebpjbe LeaveNowsub edx, 000010000Hjs LeaveNowLoopEntry:movzx eax, WORD PTR[esi+ecx-1]cmp eax, ebxjnz SHORT LookupLoopmov eax, [esp+window]movzx eax, WORD PTR[eax+ecx]cmp eax, [esp+scanstart]jnz SHORT LookupLoop;/* Store the current value of chainlen. */mov [esp+chainlenwmask], edx;/* Point %edi to the string under scrutiny, and %esi to the string we */;/* are hoping to match it up with. In actuality, %esi and %edi are */;/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is */;/* initialized to -(MAX_MATCH_8 - scanalign). */mov esi, [esp+window]mov edi, [esp+scan]add esi, ecxmov eax, [esp+scanalign]mov edx, -MAX_MATCH_8lea edi, [edi+eax+MAX_MATCH_8]lea esi, [esi+eax+MAX_MATCH_8];/* Test the strings for equality, 8 bytes at a time. At the end,; * adjust %edx so that it is offset to the exact byte that mismatched.; *; * We already know at this point that the first three bytes of the; * strings match each other, and they can be safely passed over before; * starting the compare loop. So what this code does is skip over 0-3; * bytes, as much as necessary in order to dword-align the %edi; * pointer. (%esi will still be misaligned three times out of four.); *; * It should be confessed that this loop usually does not represent; * much of the total running time. Replacing it with a more; * straightforward "rep cmpsb" would not drastically degrade; * performance.; */LoopCmps:mov eax, DWORD PTR[esi+edx]xor eax, DWORD PTR[edi+edx]jnz SHORT LeaveLoopCmpsmov eax, DWORD PTR[esi+edx+4]xor eax, DWORD PTR[edi+edx+4]jnz SHORT LeaveLoopCmps4add edx, 8jnz SHORT LoopCmpsjmp LenMaximumALIGN 4LeaveLoopCmps4:add edx, 4LeaveLoopCmps:test eax, 00000FFFFHjnz SHORT LenLoweradd edx, 2shr eax, 16LenLower:sub al, 1adc edx, 0;/* Calculate the length of the match. If it is longer than MAX_MATCH, */;/* then automatically accept it as the best possible match and leave. */lea eax, [edi+edx]mov edi, [esp+scan]sub eax, edicmp eax, MAX_MATCHjge SHORT LenMaximum;/* If the length of the match is not longer than the best match we */;/* have so far, then forget it and return to the lookup loop. */mov edx, [esp+deflatestate]mov ebx, [esp+bestlen]cmp eax, ebxjg SHORT LongerMatchmov esi, [esp+windowbestlen]mov edi, [edx].ds_prevmov ebx, [esp+scanend]mov edx, [esp+chainlenwmask]jmp LookupLoopALIGN 4;/* s->match_start = cur_match; */;/* best_len = len; */;/* if (len >= nice_match) break; */;/* scan_end = *(ushf*)(scan+best_len-1); */LongerMatch:mov ebx, [esp+nicematch]mov [esp+bestlen], eaxmov [edx].ds_match_start, ecxcmp eax, ebxjge SHORT LeaveNowmov esi, [esp+window]add esi, eaxmov [esp+windowbestlen], esimovzx ebx, WORD PTR[edi+eax-1]mov edi, [edx].ds_prevmov [esp+scanend], ebxmov edx, [esp+chainlenwmask]jmp LookupLoopALIGN 4;/* Accept the current string, with the maximum possible length. */LenMaximum:mov edx, [esp+deflatestate]mov DWORD PTR[esp+bestlen], MAX_MATCHmov [edx].ds_match_start, ecx;/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */;/* return s->lookahead; */LeaveNow:mov edx, [esp+deflatestate]mov ebx, [esp+bestlen]mov eax, [edx].ds_lookaheadcmp ebx, eaxjg SHORT LookaheadRetmov eax, ebxLookaheadRet:; Restore the stack and return from whence we came.add esp, varsizepop ebxpop esipop edipop ebpret_longest_match ENDP_TEXT ENDSEND
