match32.asm 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. ;===========================================================================
  2. ; Copyright (c) 1990-2005 Info-ZIP. All rights reserved.
  3. ;
  4. ; See the accompanying file LICENSE, version 2005-Feb-10 or later
  5. ; (the contents of which are also included in zip.h) for terms of use.
  6. ; If, for some reason, all these files are missing, the Info-ZIP license
  7. ; also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
  8. ;===========================================================================
  9. ;
  10. ; match32.asm by Jean-loup Gailly.
  11. ; match32.asm, optimized version of longest_match() in deflate.c
  12. ; To be used only with 32 bit flat model. To simplify the code, the option
  13. ; -DDYN_ALLOC is not supported.
  14. ; This file is only optional. If you don't have an assembler, use the
  15. ; C version (add -DNO_ASM to CFLAGS in makefile and remove match.o
  16. ; from OBJI). If you have reduced WSIZE in zip.h, then make sure this is
  17. ; assembled with an equivalent -DWSIZE=<whatever>.
  18. ; Caution: this module works for IBM's C/C++ compiler versions 2 and 3
  19. ; and for Watcom's 32-bit C/C++ compiler. Both pass the first (and only)
  20. ; argument for longest_match in the EAX register, not on the stack, with
  21. ; the default calling conventions (_System would use the stack).
  22. ;
  23. ;==============================================================================
  24. ;
  25. ; Do NOT assemble this source if external crc32 routine from zlib gets used.
  26. ;
  27. IFNDEF USE_ZLIB
  28. ;
  29. .386
  30. name match
  31. BSS32 segment dword USE32 public 'BSS'
  32. extrn window : byte
  33. extrn prev : word
  34. extrn prev_length : dword
  35. extrn strstart : dword
  36. extrn match_start : dword
  37. extrn max_chain_length : dword
  38. extrn good_match : dword
  39. extrn nice_match : dword
  40. BSS32 ends
  41. CODE32 segment dword USE32 public 'CODE'
  42. assume cs:CODE32, ds:FLAT, ss:FLAT
  43. public match_init
  44. public longest_match
  45. ifndef WSIZE
  46. WSIZE equ 32768 ; keep in sync with zip.h !
  47. endif
  48. MIN_MATCH equ 3
  49. MAX_MATCH equ 258
  50. MIN_LOOKAHEAD equ (MAX_MATCH+MIN_MATCH+1)
  51. MAX_DIST equ (WSIZE-MIN_LOOKAHEAD)
  52. ; initialize or check the variables used in match.asm.
  53. match_init proc near
  54. ret
  55. match_init endp
  56. ; -----------------------------------------------------------------------
  57. ; Set match_start to the longest match starting at the given string and
  58. ; return its length. Matches shorter or equal to prev_length are discarded,
  59. ; in which case the result is equal to prev_length and match_start is
  60. ; garbage.
  61. ; IN assertions: cur_match is the head of the hash chain for the current
  62. ; string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
  63. ; int longest_match(cur_match)
  64. longest_match proc near
  65. ; return address ; esp+16
  66. push ebp ; esp+12
  67. push edi ; esp+8
  68. push esi ; esp+4
  69. lea ebx,window
  70. add ebx,2
  71. window_off equ dword ptr [esp]
  72. push ebx ; esp
  73. ; match equ esi
  74. ; scan equ edi
  75. ; chain_length equ ebp
  76. ; best_len equ ebx
  77. ; limit equ edx
  78. mov esi,eax ; cur_match
  79. mov edx,strstart
  80. mov ebp,max_chain_length ; chain_length = max_chain_length
  81. mov edi,edx
  82. sub edx,MAX_DIST ; limit = strstart-MAX_DIST
  83. cld ; string ops increment esi and edi
  84. jae short limit_ok
  85. sub edx,edx ; limit = NIL
  86. limit_ok:
  87. add edi,window_off ; edi = offset(window + strstart + 2)
  88. mov ebx,prev_length ; best_len = prev_length
  89. mov cx,[edi-2] ; cx = scan[0..1]
  90. mov ax,[ebx+edi-3] ; ax = scan[best_len-1..best_len]
  91. cmp ebx,good_match ; do we have a good match already?
  92. jb do_scan
  93. shr ebp,2 ; chain_length >>= 2
  94. jmp short do_scan
  95. align 4 ; align destination of branch
  96. long_loop:
  97. ; at this point, edi == scan+2, esi == cur_match
  98. mov ax,[ebx+edi-3] ; ax = scan[best_len-1..best_len]
  99. mov cx,[edi-2] ; cx = scan[0..1]
  100. short_loop:
  101. ; at this point, edi == scan+2, esi == cur_match,
  102. ; ax = scan[best_len-1..best_len] and cx = scan[0..1]
  103. and esi,WSIZE-1 ; not needed if WSIZE=32768
  104. dec ebp ; --chain_length
  105. shl esi,1 ; cur_match as word index
  106. mov si,prev[esi] ; cur_match = prev[cur_match]
  107. ; top word of esi is still 0
  108. jz the_end
  109. cmp esi,edx ; cur_match <= limit ?
  110. jbe short the_end
  111. do_scan:
  112. cmp ax,word ptr window[ebx+esi-1] ; check match at best_len-1
  113. jne short_loop
  114. cmp cx,word ptr window[esi] ; check min_match_length match
  115. jne short_loop
  116. add esi,window_off ; esi = match
  117. mov ecx,(MAX_MATCH-2)/2 ; scan for at most MAX_MATCH bytes
  118. mov eax,edi ; eax = scan+2
  119. repe cmpsw ; loop until mismatch
  120. je maxmatch ; match of length MAX_MATCH?
  121. mismatch:
  122. mov cl,[edi-2] ; mismatch on first or second byte?
  123. xchg eax,edi ; edi = scan+2, eax = end of scan
  124. sub cl,[esi-2] ; cl = 0 if first bytes equal
  125. sub eax,edi ; eax = len
  126. sub esi,window_off ; esi = match - (2 + offset(window))
  127. sub esi,eax ; esi = cur_match (= match - len)
  128. sub cl,1 ; set carry if cl == 0 (can't use DEC)
  129. adc eax,0 ; eax = carry ? len+1 : len
  130. cmp eax,ebx ; len > best_len ?
  131. jle long_loop
  132. mov match_start,esi ; match_start = cur_match
  133. mov ebx,eax ; ebx = best_len = len
  134. ifdef FULL_SEARCH
  135. cmp eax,MAX_MATCH ; len >= MAX_MATCH ?
  136. else
  137. cmp eax,nice_match ; len >= nice_match ?
  138. endif
  139. jl long_loop
  140. the_end:
  141. mov eax,ebx ; result = eax = best_len
  142. pop ebx
  143. pop esi
  144. pop edi
  145. pop ebp
  146. ret
  147. maxmatch: ; come here if maximum match
  148. cmpsb ; increment esi and edi
  149. jmp mismatch ; force match_length = MAX_LENGTH
  150. longest_match endp
  151. CODE32 ends
  152. ;
  153. ENDIF ; !USE_ZLIB
  154. ;
  155. end