[llvm-commits] [parallel] CVS: llvm/runtime/zlib/contrib/masm686/match.asm

Misha Brukman brukman at cs.uiuc.edu
Mon Mar 1 18:14:24 PST 2004


Changes in directory llvm/runtime/zlib/contrib/masm686:

match.asm added (r1.1.2.1)

---
Log message:

Merge from trunk

---
Diffs of the changes:  (+408 -0)

Index: llvm/runtime/zlib/contrib/masm686/match.asm
diff -c /dev/null llvm/runtime/zlib/contrib/masm686/match.asm:1.1.2.1
*** /dev/null	Mon Mar  1 17:58:58 2004
--- llvm/runtime/zlib/contrib/masm686/match.asm	Mon Mar  1 17:58:48 2004
***************
*** 0 ****
--- 1,408 ----
+ 
+ ; 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 at kinesoft.com>
+ ;                    and Chuck Walbourn <chuckw at kinesoft.com>
+ ; Corrections by Cosmin Truta <cosmint at 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 at muppetlabs.com>
+ 
+ 	.686P
+ 	.MODEL	FLAT
+ 
+ ;===========================================================================
+ ; EQUATES
+ ;===========================================================================
+ 
+ MAX_MATCH	EQU 258
+ MIN_MATCH	EQU 3
+ MIN_LOOKAHEAD	EQU (MAX_MATCH + MIN_MATCH + 1)
+ MAX_MATCH_8	EQU ((MAX_MATCH + 7) AND (NOT 7))
+ 
+ ;===========================================================================
+ ; STRUCTURES
+ ;===========================================================================
+ 
+ ; This STRUCT assumes a 4-byte alignment
+ 
+ DEFLATE_STATE	STRUCT
+ ds_strm			dd ?
+ ds_status		dd ?
+ ds_pending_buf		dd ?
+ ds_pending_buf_size	dd ?
+ ds_pending_out		dd ?
+ ds_pending		dd ?
+ ds_wrap			dd ?
+ ds_data_type		db ?
+ ds_method		db ?
+ 			db ?	; padding
+ 			db ?	; padding
+ ds_last_flush		dd ?
+ ds_w_size		dd ?	; used
+ ds_w_bits		dd ?
+ ds_w_mask		dd ?	; used
+ ds_window		dd ?	; used
+ ds_window_size		dd ?
+ ds_prev			dd ?	; used
+ ds_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 ?	; used
+ ds_prev_match		dd ?	; used
+ ds_match_available	dd ?
+ ds_strstart		dd ?	; used
+ ds_match_start		dd ?	; used
+ ds_lookahead		dd ?	; used
+ ds_prev_length		dd ?	; used
+ ds_max_chain_length	dd ?	; used
+ ds_max_laxy_match	dd ?
+ ds_level		dd ?
+ ds_strategy		dd ?
+ ds_good_match		dd ?	; used
+ ds_nice_match		dd ?	; used
+ 
+ ; Don't need anymore of the struct for match
+ DEFLATE_STATE	ENDS
+ 
+ ;===========================================================================
+ ; CODE
+ ;===========================================================================
+ _TEXT	SEGMENT
+ 
+ ;---------------------------------------------------------------------------
+ ; match_init
+ ;---------------------------------------------------------------------------
+ 	ALIGN	4
+ PUBLIC	_match_init
+ _match_init	PROC
+ 	; no initialization needed
+ 	ret
+ _match_init	ENDP
+ 
+ ;---------------------------------------------------------------------------
+ ; uInt longest_match(deflate_state *deflatestate, IPos curmatch)
+ ;---------------------------------------------------------------------------
+ 	ALIGN	4
+ 
+ PUBLIC	_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
+ ; Variables
+ chainlenwmask	=  0	; high word: current chain len
+ 			; low word: s->wmask
+ window		=  4	; local copy of s->window
+ windowbestlen	=  8	; s->window + bestlen
+ scanend		= 12	; last two bytes of string
+ scanstart	= 16	; first two bytes of string
+ scanalign	= 20	; dword-misalignment of string
+ nicematch	= 24	; a good enough match size
+ bestlen		= 28	; size of best match so far
+ scan		= 32	; ptr to string wanting match
+ varsize		= 36	; number of bytes (also offset to last saved register)
+ 
+ ; Saved Registers (actually pushed into place)
+ ebx_save	= 36
+ edi_save	= 40
+ esi_save	= 44
+ ebp_save	= 48
+ 
+ ; Parameters
+ retaddr		= 52
+ deflatestate	= 56
+ curmatch	= 60
+ 
+ ; Save registers that the compiler may be using
+ 	push	ebp
+ 	push	edi
+ 	push	esi
+ 	push	ebx
+ 
+ ; Allocate local variable space
+ 	sub	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_STATE
+ 
+ 	mov	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_length
+ 	mov	ebx, [edx].ds_good_match
+ 	cmp	eax, ebx
+ 	mov	eax, [edx].ds_w_mask
+ 	mov	ebx, [edx].ds_max_chain_length
+ 	jl	SHORT LastMatchGood
+ 	shr	ebx, 2
+ LastMatchGood:
+ 
+ ; 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	ebx
+ 	shl	ebx, 16
+ 	or	ebx, eax
+ 	mov	[esp+chainlenwmask], ebx
+ 
+ ; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
+ 
+ 	mov	eax, [edx].ds_nice_match
+ 	mov	ebx, [edx].ds_lookahead
+ 	cmp	ebx, eax
+ 	jl	SHORT LookaheadLess
+ 	mov	ebx, eax
+ LookaheadLess:
+ 	mov	[esp+nicematch], ebx
+ 
+ ;/* register Bytef *scan = s->window + s->strstart;                     */
+ 
+ 	mov	esi, [edx].ds_window
+ 	mov	[esp+window], esi
+ 	mov	ebp, [edx].ds_strstart
+ 	lea	edi, [esi+ebp]
+ 	mov	[esp+scan],edi
+ 
+ ;/* Determine how many bytes the scan ptr is off from being             */
+ ;/* dword-aligned.                                                      */
+ 
+ 	mov	eax, edi
+ 	neg	eax
+ 	and	eax, 3
+ 	mov	[esp+scanalign], eax
+ 
+ ;/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ?                      */
+ ;/*     s->strstart - (IPos)MAX_DIST(s) : NIL;                          */
+ 
+ 	mov	eax, [edx].ds_w_size
+ 	sub	eax, MIN_LOOKAHEAD
+ 	sub	ebp, eax
+ 	jg	SHORT LimitPositive
+ 	xor	ebp, ebp
+ LimitPositive:
+ 
+ ;/* int best_len = s->prev_length;                                      */
+ 
+ 	mov	eax, [edx].ds_prev_length
+ 	mov	[esp+bestlen], eax
+ 
+ ;/* Store the sum of s->window + best_len in %esi locally, and in %esi. */
+ 
+ 	add	esi, eax
+ 	mov	[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], ebx
+ 	movzx	ebx, WORD PTR[eax+edi-1]
+ 	mov	[esp+scanend], ebx
+ 	mov	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	4
+ LookupLoop:
+ 	and	ecx, edx
+ 	movzx	ecx, WORD PTR[edi+ecx*2]
+ 	cmp	ecx, ebp
+ 	jbe	LeaveNow
+ 	sub	edx, 000010000H
+ 	js	LeaveNow
+ 
+ LoopEntry:
+ 	movzx	eax, WORD PTR[esi+ecx-1]
+ 	cmp	eax, ebx
+ 	jnz	SHORT LookupLoop
+ 
+ 	mov	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, ecx
+ 	mov	eax, [esp+scanalign]
+ 	mov	edx, -MAX_MATCH_8
+ 	lea	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 LeaveLoopCmps
+ 
+ 	mov	eax, DWORD PTR[esi+edx+4]
+ 	xor	eax, DWORD PTR[edi+edx+4]
+ 	jnz	SHORT LeaveLoopCmps4
+ 
+ 	add	edx, 8
+ 	jnz	SHORT LoopCmps
+ 	jmp	LenMaximum
+ 	ALIGN	4
+ 
+ LeaveLoopCmps4:
+ 	add	edx, 4
+ 
+ LeaveLoopCmps:
+ 	test	eax, 00000FFFFH
+ 	jnz	SHORT LenLower
+ 
+ 	add	edx, 2
+ 	shr	eax, 16
+ 
+ LenLower:
+ 	sub	al, 1
+ 	adc	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, edi
+ 	cmp	eax, MAX_MATCH
+ 	jge	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, ebx
+ 	jg	SHORT LongerMatch
+ 	mov	esi, [esp+windowbestlen]
+ 	mov	edi, [edx].ds_prev
+ 	mov	ebx, [esp+scanend]
+ 	mov	edx, [esp+chainlenwmask]
+ 	jmp	LookupLoop
+ 	ALIGN	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], eax
+ 	mov	[edx].ds_match_start, ecx
+ 	cmp	eax, ebx
+ 	jge	SHORT LeaveNow
+ 	mov	esi, [esp+window]
+ 	add	esi, eax
+ 	mov	[esp+windowbestlen], esi
+ 	movzx	ebx, WORD PTR[edi+eax-1]
+ 	mov	edi, [edx].ds_prev
+ 	mov	[esp+scanend], ebx
+ 	mov	edx, [esp+chainlenwmask]
+ 	jmp	LookupLoop
+ 	ALIGN	4
+ 
+ ;/* Accept the current string, with the maximum possible length.        */
+ 
+ LenMaximum:
+ 	mov	edx, [esp+deflatestate]
+ 	mov	DWORD PTR[esp+bestlen], MAX_MATCH
+ 	mov	[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_lookahead
+ 	cmp	ebx, eax
+ 	jg	SHORT LookaheadRet
+ 	mov	eax, ebx
+ LookaheadRet:
+ 
+ ; Restore the stack and return from whence we came.
+ 
+ 	add	esp, varsize
+ 	pop	ebx
+ 	pop	esi
+ 	pop	edi
+ 	pop	ebp
+ 	ret
+ 
+ _longest_match	ENDP
+ 
+ _TEXT	ENDS
+ END





More information about the llvm-commits mailing list