gvmat64.asm
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:15k
源码类别:

通讯编程

开发平台:

Visual C++

  1. ;uInt longest_match_x64(
  2. ;    deflate_state *s,
  3. ;    IPos cur_match);                             /* current match */
  4. ; gvmat64.asm -- Asm portion of the optimized longest_match for 32 bits x86
  5. ; Copyright (C) 1995-2005 Jean-loup Gailly, Brian Raiter and Gilles Vollant.
  6. ;
  7. ; File written by Gilles Vollant, by converting to assembly the longest_match
  8. ;  from Jean-loup Gailly in deflate.c of zLib and infoZip zip.
  9. ;
  10. ;  and by taking inspiration on asm686 with masm, optimised assembly code
  11. ;        from Brian Raiter, written 1998
  12. ;
  13. ;         http://www.zlib.net
  14. ;         http://www.winimage.com/zLibDll
  15. ;         http://www.muppetlabs.com/~breadbox/software/assembly.html
  16. ;
  17. ; to compile this file for infozip Zip, I use option:
  18. ;   ml64.exe /Flgvmat64 /c /Zi /DINFOZIP gvmat64.asm
  19. ;
  20. ; to compile this file for zLib, I use option:
  21. ;   ml64.exe /Flgvmat64 /c /Zi gvmat64.asm
  22. ; Be carrefull to adapt zlib1222add below to your version of zLib
  23. ;   (if you use a version of zLib before 1.0.4 or after 1.2.2.2, change
  24. ;    value of zlib1222add later)
  25. ;
  26. ; This file compile with Microsoft Macro Assembler (x64) for AMD64
  27. ;
  28. ;   ml64.exe is given with Visual Studio 2005 and Windows 2003 server DDK
  29. ;
  30. ;   (you can get Windows 2003 server DDK with ml64 and cl for AMD64 from
  31. ;      http://www.microsoft.com/whdc/devtools/ddk/default.mspx for low price)
  32. ;
  33. ;uInt longest_match(s, cur_match)
  34. ;    deflate_state *s;
  35. ;    IPos cur_match;                             /* current match */
  36. .code
  37. longest_match PROC
  38. ;LocalVarsSize   equ 88
  39.  LocalVarsSize   equ 72
  40. ; register used : rax,rbx,rcx,rdx,rsi,rdi,r8,r9,r10,r11,r12
  41. ; free register :  r14,r15
  42. ; register can be saved : rsp
  43.  chainlenwmask   equ  rsp + 8 - LocalVarsSize    ; high word: current chain len
  44.                                                  ; low word: s->wmask
  45. ;window          equ  rsp + xx - LocalVarsSize   ; local copy of s->window ; stored in r10
  46. ;windowbestlen   equ  rsp + xx - LocalVarsSize   ; s->window + bestlen , use r10+r11
  47. ;scanstart       equ  rsp + xx - LocalVarsSize   ; first two bytes of string ; stored in r12w
  48. ;scanend         equ  rsp + xx - LocalVarsSize   ; last two bytes of string use ebx
  49. ;scanalign       equ  rsp + xx - LocalVarsSize   ; dword-misalignment of string r13
  50. ;bestlen         equ  rsp + xx - LocalVarsSize   ; size of best match so far -> r11d
  51. ;scan            equ  rsp + xx - LocalVarsSize   ; ptr to string wanting match -> r9
  52. IFDEF INFOZIP
  53. ELSE
  54.  nicematch       equ  (rsp + 16 - LocalVarsSize) ; a good enough match size
  55. ENDIF
  56. save_rdi        equ  rsp + 24 - LocalVarsSize
  57. save_rsi        equ  rsp + 32 - LocalVarsSize
  58. save_rbx        equ  rsp + 40 - LocalVarsSize
  59. save_rbp        equ  rsp + 48 - LocalVarsSize
  60. save_r12        equ  rsp + 56 - LocalVarsSize
  61. save_r13        equ  rsp + 64 - LocalVarsSize
  62. ;save_r14        equ  rsp + 72 - LocalVarsSize
  63. ;save_r15        equ  rsp + 80 - LocalVarsSize
  64. ;  all the +4 offsets are due to the addition of pending_buf_size (in zlib
  65. ;  in the deflate_state structure since the asm code was first written
  66. ;  (if you compile with zlib 1.0.4 or older, remove the +4).
  67. ;  Note : these value are good with a 8 bytes boundary pack structure
  68.     MAX_MATCH           equ     258
  69.     MIN_MATCH           equ     3
  70.     MIN_LOOKAHEAD       equ     (MAX_MATCH+MIN_MATCH+1)
  71. ;;; Offsets for fields in the deflate_state structure. These numbers
  72. ;;; are calculated from the definition of deflate_state, with the
  73. ;;; assumption that the compiler will dword-align the fields. (Thus,
  74. ;;; changing the definition of deflate_state could easily cause this
  75. ;;; program to crash horribly, without so much as a warning at
  76. ;;; compile time. Sigh.)
  77. ;  all the +zlib1222add offsets are due to the addition of fields
  78. ;  in zlib in the deflate_state structure since the asm code was first written
  79. ;  (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)").
  80. ;  (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0").
  81. ;  if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8").
  82. IFDEF INFOZIP
  83. _DATA   SEGMENT
  84. COMM    window_size:DWORD
  85. ; WMask ; 7fff
  86. COMM    window:BYTE:010040H
  87. COMM    prev:WORD:08000H
  88. ; MatchLen : unused
  89. ; PrevMatch : unused
  90. COMM    strstart:DWORD
  91. COMM    match_start:DWORD
  92. ; Lookahead : ignore
  93. COMM    prev_length:DWORD ; PrevLen
  94. COMM    max_chain_length:DWORD
  95. COMM    good_match:DWORD
  96. COMM    nice_match:DWORD
  97. prev_ad equ OFFSET prev
  98. window_ad equ OFFSET window
  99. nicematch equ nice_match
  100. _DATA ENDS
  101. WMask equ 07fffh
  102. ELSE
  103.   IFNDEF zlib1222add
  104.     zlib1222add equ 8
  105.   ENDIF
  106. dsWSize         equ 56+zlib1222add+(zlib1222add/2)
  107. dsWMask         equ 64+zlib1222add+(zlib1222add/2)
  108. dsWindow        equ 72+zlib1222add
  109. dsPrev          equ 88+zlib1222add
  110. dsMatchLen      equ 128+zlib1222add
  111. dsPrevMatch     equ 132+zlib1222add
  112. dsStrStart      equ 140+zlib1222add
  113. dsMatchStart    equ 144+zlib1222add
  114. dsLookahead     equ 148+zlib1222add
  115. dsPrevLen       equ 152+zlib1222add
  116. dsMaxChainLen   equ 156+zlib1222add
  117. dsGoodMatch     equ 172+zlib1222add
  118. dsNiceMatch     equ 176+zlib1222add
  119. window_size     equ [ rcx + dsWSize]
  120. WMask           equ [ rcx + dsWMask]
  121. window_ad       equ [ rcx + dsWindow]
  122. prev_ad         equ [ rcx + dsPrev]
  123. strstart        equ [ rcx + dsStrStart]
  124. match_start     equ [ rcx + dsMatchStart]
  125. Lookahead       equ [ rcx + dsLookahead] ; 0ffffffffh on infozip
  126. prev_length     equ [ rcx + dsPrevLen]
  127. max_chain_length equ [ rcx + dsMaxChainLen]
  128. good_match      equ [ rcx + dsGoodMatch]
  129. nice_match      equ [ rcx + dsNiceMatch]
  130. ENDIF
  131. ; parameter 1 in r8(deflate state s), param 2 in rdx (cur match)
  132. ; see http://weblogs.asp.net/oldnewthing/archive/2004/01/14/58579.aspx and
  133. ; http://msdn.microsoft.com/library/en-us/kmarch/hh/kmarch/64bitAMD_8e951dd2-ee77-4728-8702-55ce4b5dd24a.xml.asp
  134. ;
  135. ; All registers must be preserved across the call, except for
  136. ;   rax, rcx, rdx, r8, r9, r10, and r11, which are scratch.
  137. ;;; Save registers that the compiler may be using, and adjust esp to
  138. ;;; make room for our stack frame.
  139. ;;; Retrieve the function arguments. r8d will hold cur_match
  140. ;;; throughout the entire function. edx will hold the pointer to the
  141. ;;; deflate_state structure during the function's setup (before
  142. ;;; entering the main loop.
  143. ; parameter 1 in rcx (deflate_state* s), param 2 in edx -> r8 (cur match)
  144. ; this clear high 32 bits of r8, which can be garbage in both r8 and rdx
  145.         mov [save_rdi],rdi
  146.         mov [save_rsi],rsi
  147.         mov [save_rbx],rbx
  148.         mov [save_rbp],rbp
  149. IFDEF INFOZIP
  150.         mov r8d,ecx
  151. ELSE
  152.         mov r8d,edx
  153. ENDIF
  154.         mov [save_r12],r12
  155.         mov [save_r13],r13
  156. ;        mov [save_r14],r14
  157. ;        mov [save_r15],r15
  158. ;;; uInt wmask = s->w_mask;
  159. ;;; unsigned chain_length = s->max_chain_length;
  160. ;;; if (s->prev_length >= s->good_match) {
  161. ;;;     chain_length >>= 2;
  162. ;;; }
  163.         mov edi, prev_length
  164.         mov esi, good_match
  165.         mov eax, WMask
  166.         mov ebx, max_chain_length
  167.         cmp edi, esi
  168.         jl  LastMatchGood
  169.         shr ebx, 2
  170. LastMatchGood:
  171. ;;; chainlen is decremented once beforehand so that the function can
  172. ;;; use the sign flag instead of the zero flag for the exit test.
  173. ;;; It is then shifted into the high word, to make room for the wmask
  174. ;;; value, which it will always accompany.
  175.         dec ebx
  176.         shl ebx, 16
  177.         or  ebx, eax
  178. ;;; on zlib only
  179. ;;; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
  180. IFDEF INFOZIP
  181.         mov [chainlenwmask], ebx
  182. ; on infozip nice_match = [nice_match]
  183. ELSE
  184.         mov eax, nice_match
  185.         mov [chainlenwmask], ebx
  186.         mov r10d, Lookahead
  187.         cmp r10d, eax
  188.         cmovnl r10d, eax
  189.         mov [nicematch],r10d
  190. ENDIF
  191. ;;; register Bytef *scan = s->window + s->strstart;
  192.         mov r10, window_ad
  193.         mov ebp, strstart
  194.         lea r13, [r10 + rbp]
  195. ;;; Determine how many bytes the scan ptr is off from being
  196. ;;; dword-aligned.
  197.          mov r9,r13
  198.          neg r13
  199.          and r13,3
  200. ;;; IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
  201. ;;;     s->strstart - (IPos)MAX_DIST(s) : NIL;
  202. IFDEF INFOZIP
  203.         mov eax,07efah ; MAX_DIST = (WSIZE-MIN_LOOKAHEAD) (0x8000-(3+8+1))
  204. ELSE
  205.         mov eax, window_size
  206.         sub eax, MIN_LOOKAHEAD
  207. ENDIF
  208.         xor edi,edi
  209.         sub ebp, eax
  210.         mov r11d, prev_length
  211.         cmovng ebp,edi
  212. ;;; int best_len = s->prev_length;
  213. ;;; Store the sum of s->window + best_len in esi locally, and in esi.
  214.        lea  rsi,[r10+r11]
  215. ;;; register ush scan_start = *(ushf*)scan;
  216. ;;; register ush scan_end   = *(ushf*)(scan+best_len-1);
  217. ;;; Posf *prev = s->prev;
  218.         movzx r12d,word ptr [r9]
  219.         movzx ebx, word ptr [r9 + r11 - 1]
  220.         mov rdi, prev_ad
  221. ;;; Jump into the main loop.
  222.         mov edx, [chainlenwmask]
  223.         cmp bx,word ptr [rsi + r8 - 1]
  224.         jz  LookupLoopIsZero
  225. LookupLoop1:
  226.         and r8d, edx
  227.         movzx   r8d, word ptr [rdi + r8*2]
  228.         cmp r8d, ebp
  229.         jbe LeaveNow
  230.         sub edx, 00010000h
  231.         js  LeaveNow
  232. LoopEntry1:
  233.         cmp bx,word ptr [rsi + r8 - 1]
  234.         jz  LookupLoopIsZero
  235. LookupLoop2:
  236.         and r8d, edx
  237.         movzx   r8d, word ptr [rdi + r8*2]
  238.         cmp r8d, ebp
  239.         jbe LeaveNow
  240.         sub edx, 00010000h
  241.         js  LeaveNow
  242. LoopEntry2:
  243.         cmp bx,word ptr [rsi + r8 - 1]
  244.         jz  LookupLoopIsZero
  245. LookupLoop4:
  246.         and r8d, edx
  247.         movzx   r8d, word ptr [rdi + r8*2]
  248.         cmp r8d, ebp
  249.         jbe LeaveNow
  250.         sub edx, 00010000h
  251.         js  LeaveNow
  252. LoopEntry4:
  253.         cmp bx,word ptr [rsi + r8 - 1]
  254.         jnz LookupLoop1
  255.         jmp LookupLoopIsZero
  256. ;;; do {
  257. ;;;     match = s->window + cur_match;
  258. ;;;     if (*(ushf*)(match+best_len-1) != scan_end ||
  259. ;;;         *(ushf*)match != scan_start) continue;
  260. ;;;     [...]
  261. ;;; } while ((cur_match = prev[cur_match & wmask]) > limit
  262. ;;;          && --chain_length != 0);
  263. ;;;
  264. ;;; Here is the inner loop of the function. The function will spend the
  265. ;;; majority of its time in this loop, and majority of that time will
  266. ;;; be spent in the first ten instructions.
  267. ;;;
  268. ;;; Within this loop:
  269. ;;; ebx = scanend
  270. ;;; r8d = curmatch
  271. ;;; edx = chainlenwmask - i.e., ((chainlen << 16) | wmask)
  272. ;;; esi = windowbestlen - i.e., (window + bestlen)
  273. ;;; edi = prev
  274. ;;; ebp = limit
  275. LookupLoop:
  276.         and r8d, edx
  277.         movzx   r8d, word ptr [rdi + r8*2]
  278.         cmp r8d, ebp
  279.         jbe LeaveNow
  280.         sub edx, 00010000h
  281.         js  LeaveNow
  282. LoopEntry:
  283.         cmp bx,word ptr [rsi + r8 - 1]
  284.         jnz LookupLoop1
  285. LookupLoopIsZero:
  286.         cmp     r12w, word ptr [r10 + r8]
  287.         jnz LookupLoop1
  288. ;;; Store the current value of chainlen.
  289.         mov [chainlenwmask], edx
  290. ;;; Point edi to the string under scrutiny, and esi to the string we
  291. ;;; are hoping to match it up with. In actuality, esi and edi are
  292. ;;; both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and edx is
  293. ;;; initialized to -(MAX_MATCH_8 - scanalign).
  294.         lea rsi,[r8+r10]
  295.         mov rdx, 0fffffffffffffef8h; -(MAX_MATCH_8)
  296.         lea rsi, [rsi + r13 + 0108h] ;MAX_MATCH_8]
  297.         lea rdi, [r9 + r13 + 0108h] ;MAX_MATCH_8]
  298.         prefetcht1 [rsi+rdx]
  299.         prefetcht1 [rdi+rdx]
  300. ;;; Test the strings for equality, 8 bytes at a time. At the end,
  301. ;;; adjust rdx so that it is offset to the exact byte that mismatched.
  302. ;;;
  303. ;;; We already know at this point that the first three bytes of the
  304. ;;; strings match each other, and they can be safely passed over before
  305. ;;; starting the compare loop. So what this code does is skip over 0-3
  306. ;;; bytes, as much as necessary in order to dword-align the edi
  307. ;;; pointer. (rsi will still be misaligned three times out of four.)
  308. ;;;
  309. ;;; It should be confessed that this loop usually does not represent
  310. ;;; much of the total running time. Replacing it with a more
  311. ;;; straightforward "rep cmpsb" would not drastically degrade
  312. ;;; performance.
  313. LoopCmps:
  314.         mov rax, [rsi + rdx]
  315.         xor rax, [rdi + rdx]
  316.         jnz LeaveLoopCmps
  317.         mov rax, [rsi + rdx + 8]
  318.         xor rax, [rdi + rdx + 8]
  319.         jnz LeaveLoopCmps8
  320.         mov rax, [rsi + rdx + 8+8]
  321.         xor rax, [rdi + rdx + 8+8]
  322.         jnz LeaveLoopCmps16
  323.         add rdx,8+8+8
  324.         jmp short LoopCmps
  325. LeaveLoopCmps16: add rdx,8
  326. LeaveLoopCmps8: add rdx,8
  327. LeaveLoopCmps:
  328.         test    eax, 0000FFFFh
  329.         jnz LenLower
  330.         test eax,0ffffffffh
  331.         jnz LenLower32
  332.         add rdx,4
  333.         shr rax,32
  334.         or ax,ax
  335.         jnz LenLower
  336. LenLower32:
  337.         shr eax,16
  338.         add rdx,2
  339. LenLower:   sub al, 1
  340.         adc rdx, 0
  341. ;;; Calculate the length of the match. If it is longer than MAX_MATCH,
  342. ;;; then automatically accept it as the best possible match and leave.
  343.         lea rax, [rdi + rdx]
  344.         sub rax, r9
  345.         cmp eax, MAX_MATCH
  346.         jge LenMaximum
  347. ;;; If the length of the match is not longer than the best match we
  348. ;;; have so far, then forget it and return to the lookup loop.
  349. ;///////////////////////////////////
  350.         cmp eax, r11d
  351.         jg  LongerMatch
  352.         lea rsi,[r10+r11]
  353.         mov rdi, prev_ad
  354.         mov edx, [chainlenwmask]
  355.         jmp LookupLoop
  356. ;;;         s->match_start = cur_match;
  357. ;;;         best_len = len;
  358. ;;;         if (len >= nice_match) break;
  359. ;;;         scan_end = *(ushf*)(scan+best_len-1);
  360. LongerMatch:
  361.         mov r11d, eax
  362.         mov match_start, r8d
  363.         cmp eax, [nicematch]
  364.         jge LeaveNow
  365.         lea rsi,[r10+rax]
  366.         movzx   ebx, word ptr [r9 + rax - 1]
  367.         mov rdi, prev_ad
  368.         mov edx, [chainlenwmask]
  369.         jmp LookupLoop
  370. ;;; Accept the current string, with the maximum possible length.
  371. LenMaximum:
  372.         mov r11d,MAX_MATCH
  373.         mov match_start, r8d
  374. ;;; if ((uInt)best_len <= s->lookahead) return (uInt)best_len;
  375. ;;; return s->lookahead;
  376. LeaveNow:
  377. IFDEF INFOZIP
  378.         mov eax,r11d
  379. ELSE
  380.         mov eax, Lookahead
  381.         cmp r11d, eax
  382.         cmovng eax, r11d
  383. ENDIF
  384. ;;; Restore the stack and return from whence we came.
  385.         mov rsi,[save_rsi]
  386.         mov rdi,[save_rdi]
  387.         mov rbx,[save_rbx]
  388.         mov rbp,[save_rbp]
  389.         mov r12,[save_r12]
  390.         mov r13,[save_r13]
  391. ;        mov r14,[save_r14]
  392. ;        mov r15,[save_r15]
  393.         ret 0
  394. ; please don't remove this string !
  395. ; Your can freely use gvmat64 in any free or commercial app
  396. ; but it is far better don't remove the string in the binary!
  397.     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
  398. longest_match   ENDP
  399. match_init PROC
  400.   ret 0
  401. match_init ENDP
  402. END