/* ;uInt longest_match_x64( ; deflate_state *s, ; IPos cur_match); // current match
; gvmat64.S -- Asm portion of the optimized longest_match for 32 bits x86_64 ; (AMD64 on Athlon 64, Opteron, Phenom ; and Intel EM64T on Pentium 4 with EM64T, Pentium D, Core 2 Duo, Core I5/I7) ; this file is translation from gvmat64.asm to GCC 4.x (for Linux, Mac XCode) ; Copyright (C) 1995-2010 Jean-loup Gailly, Brian Raiter and Gilles Vollant. ; ; File written by Gilles Vollant, by converting to assembly the longest_match ; from Jean-loup Gailly in deflate.c of zLib and infoZip zip. ; and by taking inspiration on asm686 with masm, optimised assembly code ; from Brian Raiter, written 1998 ; ; This software is provided 'as-is', without any express or implied ; warranty. In no event will the authors be held liable for any damages ; arising from the use of this software. ; ; Permission is granted to anyone to use this software for any purpose, ; including commercial applications, and to alter it and redistribute it ; freely, subject to the following restrictions: ; ; 1. The origin of this software must not be misrepresented; you must not ; claim that you wrote the original software. If you use this software ; in a product, an acknowledgment in the product documentation would be ; appreciated but is not required. ; 2. Altered source versions must be plainly marked as such, and must not be ; misrepresented as being the original software ; 3. This notice may not be removed or altered from any source distribution. ; ; http://www.zlib.net ; http://www.winimage.com/zLibDll ; http://www.muppetlabs.com/~breadbox/software/assembly.html ; ; to compile this file for zLib, I use option: ; gcc -c -arch x86_64 gvmat64.S
;uInt longest_match(s, cur_match) ; deflate_state *s; ; IPos cur_match; // current match / ; ; with XCode for Mac, I had strange error with some jump on intel syntax ; this is why BEFORE_JMP and AFTER_JMP are used
*/
/* ; all the +4 offsets are due to the addition of pending_buf_size (in zlib ; in the deflate_state structure since the asm code was first written ; (if you compile with zlib 1.0.4 or older, remove the +4). ; Note : these value are good with a 8 bytes boundary pack structure
*/
/* ;;; Offsets for fields in the deflate_state structure. These numbers ;;; are calculated from the definition of deflate_state, with the ;;; assumption that the compiler will dword-align the fields. (Thus, ;;; changing the definition of deflate_state could easily cause this ;;; program to crash horribly, without so much as a warning at ;;; compile time. Sigh.)
; all the +zlib1222add offsets are due to the addition of fields ; in zlib in the deflate_state structure since the asm code was first written ; (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)"). ; (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0"). ; if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8").
*/
;;; Save registers that the compiler may be using, and adjust esp to ;;; make room for our stack frame.
;;; Retrieve the function arguments. r8d 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.
; ms: parameter 1 in rcx (deflate_state* s), param 2 in edx -> r8 (cur match) ; mac: param 1 in rdi, param 2 rsi ; this clear high 32 bits of r8, which can be garbage in both r8 and rdx
*/
mov [save_rbx],rbx
mov [save_rbp],rbp
mov edi, prev_length
mov esi, good_match
mov eax, WMask
mov ebx, max_chain_length
cmp edi, esi
jl 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
//;;; on zlib only
//;;; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
cmp bx,word ptr [rsi + r8 - 1]
BEFORE_JMP
jnz LookupLoop1
jmp LookupLoopIsZero
AFTER_JMP /* ;;; 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 ;;; r8d = curmatch ;;; edx = chainlenwmask - i.e., ((chainlen << 16) | wmask) ;;; esi = windowbestlen - i.e., (window + bestlen) ;;; edi = prev ;;; ebp = limit
*/
.balign 16
LookupLoop:
and r8d, edx
//;;; Store the current value of chainlen.
mov [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).
*/
lea rsi,[r8+r10]
mov rdx, 0xfffffffffffffef8 //; -(MAX_MATCH_8)
lea rsi, [rsi + r13 + 0x0108] //;MAX_MATCH_8]
lea rdi, [r9 + r13 + 0x0108] //;MAX_MATCH_8]
prefetcht1 [rsi+rdx]
prefetcht1 [rdi+rdx]
/* ;;; Test the strings for equality, 8 bytes at a time. At the end, ;;; adjust rdx 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. (rsi 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.
*/
add rdx,4
shr rax,32
or ax,ax
BEFORE_JMP
jnz LenLower
AFTER_JMP
LenLower32:
shr eax,16
add rdx,2
LenLower: sub al, 1
adc rdx, 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 rax, [rdi + rdx] sub rax, r9
cmp eax, MAX_MATCH
BEFORE_JMP
jge LenMaximum
AFTER_JMP /* ;;; 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. ;///////////////////////////////////
*/
cmp eax, r11d
jg LongerMatch
ret 0
//; please don't remove this string !
//; Your can freely use gvmat64 in any free or commercial app
//; but it is far better don't remove the string in the binary!
// db 0dh,0ah,"asm686 with masm, optimised assembly code from Brian Raiter, written 1998, converted to amd 64 by Gilles Vollant 2005",0dh,0ah,0
match_init:
ret 0
Messung V0.5
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.