match.S 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407
  1. /*
  2. Copyright (c) 1990-2005 Info-ZIP. All rights reserved.
  3. See the accompanying file LICENSE, version 2004-May-22 or later
  4. (the contents of which are also included in zip.h) for terms of use.
  5. If, for some reason, both of these files are missing, the Info-ZIP license
  6. also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
  7. */
  8. /*
  9. * match.s by Jean-loup Gailly. Translated to 32 bit code by Kai Uwe Rommel.
  10. * The 68020 version has been written by Francesco Potorti` <pot@cnuce.cnr.it>
  11. * with adaptations by Carsten Steger <stegerc@informatik.tu-muenchen.de>,
  12. * Andreas Schwab <schwab@lamothe.informatik.uni-dortmund.de> and
  13. * Kristoffer Eriksson <ske@pkmab.se>
  14. */
  15. /* This file is NOT used in conjunction with zlib. */
  16. #ifndef USE_ZLIB
  17. /* Preprocess with -DNO_UNDERLINE if your C compiler does not prefix
  18. * external symbols with an underline character '_'.
  19. */
  20. #if defined(NO_UNDERLINE) || defined(__ELF__)
  21. # define _prev prev
  22. # define _window window
  23. # define _match_start match_start
  24. # define _prev_length prev_length
  25. # define _good_match good_match
  26. # define _nice_match nice_match
  27. # define _strstart strstart
  28. # define _max_chain_length max_chain_length
  29. # define _match_init match_init
  30. # define _longest_match longest_match
  31. #endif
  32. #ifdef DYN_ALLOC
  33. error: DYN_ALLOC not yet supported in match.s
  34. #endif
  35. /* Use 16-bytes alignment if your assembler supports it. Warning: gas
  36. * uses a log(x) parameter (.align 4 means 16-bytes alignment). On SVR4
  37. * the parameter is a number of bytes.
  38. */
  39. #ifndef ALIGNMENT
  40. # define ALIGNMENT 4
  41. #endif
  42. #ifndef WSIZE
  43. # define WSIZE 32768
  44. #endif
  45. #define MIN_MATCH 3
  46. #define MAX_MATCH 258
  47. #define MIN_LOOKAHEAD (MAX_MATCH + MIN_MATCH + 1)
  48. #define MAX_DIST (WSIZE - MIN_LOOKAHEAD)
  49. #if defined(i386) || defined(_I386) || defined(_i386) || defined(__i386)
  50. /* This version is for 386 Unix or OS/2 in 32 bit mode.
  51. * Warning: it uses the AT&T syntax: mov source,dest
  52. * This file is only optional. If you want to force the C version,
  53. * add -DNO_ASM to CFLAGS in Makefile and set OBJA to an empty string.
  54. * If you have reduced WSIZE in (g)zip.h, then make sure this is
  55. * assembled with an equivalent -DWSIZE=<whatever>.
  56. * This version assumes static allocation of the arrays (-DDYN_ALLOC not used).
  57. */
  58. .file "match.S"
  59. .globl _match_init
  60. .globl _longest_match
  61. .text
  62. _match_init:
  63. ret
  64. /*-----------------------------------------------------------------------
  65. * Set match_start to the longest match starting at the given string and
  66. * return its length. Matches shorter or equal to prev_length are discarded,
  67. * in which case the result is equal to prev_length and match_start is
  68. * garbage.
  69. * IN assertions: cur_match is the head of the hash chain for the current
  70. * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
  71. */
  72. .align ALIGNMENT
  73. _longest_match: /* int longest_match(cur_match) */
  74. #define cur_match 20(%esp)
  75. /* return address */ /* esp+16 */
  76. push %ebp /* esp+12 */
  77. push %edi /* esp+8 */
  78. push %esi /* esp+4 */
  79. push %ebx /* esp */
  80. /*
  81. * match equ esi
  82. * scan equ edi
  83. * chain_length equ ebp
  84. * best_len equ ebx
  85. * limit equ edx
  86. */
  87. mov cur_match,%esi
  88. mov _strstart,%edx
  89. mov _max_chain_length,%ebp /* chain_length = max_chain_length */
  90. mov %edx,%edi
  91. sub $(MAX_DIST),%edx /* limit = strstart-MAX_DIST */
  92. cld /* string ops increment si and di */
  93. jae limit_ok
  94. sub %edx,%edx /* limit = NIL */
  95. limit_ok:
  96. add $2+_window,%edi /* edi = offset(window+strstart+2) */
  97. mov _prev_length,%ebx /* best_len = prev_length */
  98. movw -2(%edi),%cx /* cx = scan[0..1] */
  99. movw -3(%ebx,%edi),%ax /* ax = scan[best_len-1..best_len] */
  100. cmp _good_match,%ebx /* do we have a good match already? */
  101. jb do_scan
  102. shr $2,%ebp /* chain_length >>= 2 */
  103. jmp do_scan
  104. .align ALIGNMENT
  105. long_loop:
  106. /* at this point, edi == scan+2, esi == cur_match */
  107. movw -3(%ebx,%edi),%ax /* ax = scan[best_len-1..best_len] */
  108. movw -2(%edi),%cx /* cx = scan[0..1] */
  109. short_loop:
  110. /*
  111. * at this point, di == scan+2, si == cur_match,
  112. * ax = scan[best_len-1..best_len] and cx = scan[0..1]
  113. */
  114. and $(WSIZE-1), %esi
  115. dec %ebp /* --chain_length */
  116. movw _prev(,%esi,2),%si /* cur_match = prev[cur_match] */
  117. /* top word of esi is still 0 */
  118. jz the_end
  119. cmp %edx,%esi /* cur_match <= limit ? */
  120. jbe the_end
  121. do_scan:
  122. cmpw _window-1(%ebx,%esi),%ax/* check match at best_len-1 */
  123. jne short_loop
  124. cmpw _window(%esi),%cx /* check min_match_length match */
  125. jne short_loop
  126. add $2+_window,%esi /* si = match */
  127. mov $((MAX_MATCH>>1)-1),%ecx/* scan for at most MAX_MATCH bytes */
  128. mov %edi,%eax /* ax = scan+2 */
  129. repe; cmpsw /* loop until mismatch */
  130. je maxmatch /* match of length MAX_MATCH? */
  131. mismatch:
  132. movb -2(%edi),%cl /* mismatch on first or second byte? */
  133. xchg %edi,%eax /* edi = scan+2, eax = end of scan */
  134. subb -2(%esi),%cl /* cl = 0 if first bytes equal */
  135. sub %edi,%eax /* eax = len */
  136. sub $2+_window,%esi /* esi = cur_match + len */
  137. sub %eax,%esi /* esi = cur_match */
  138. subb $1,%cl /* set carry if cl == 0 (cannot use DEC) */
  139. adc $0,%eax /* eax = carry ? len+1 : len */
  140. cmp %ebx,%eax /* len > best_len ? */
  141. jle long_loop
  142. mov %esi,_match_start /* match_start = cur_match */
  143. mov %eax,%ebx /* ebx = best_len = len */
  144. #ifdef FULL_SEARCH
  145. cmp $(MAX_MATCH),%eax /* len >= MAX_MATCH ? */
  146. #else
  147. cmp _nice_match,%eax /* len >= nice_match ? */
  148. #endif
  149. jl long_loop
  150. the_end:
  151. mov %ebx,%eax /* result = eax = best_len */
  152. pop %ebx
  153. pop %esi
  154. pop %edi
  155. pop %ebp
  156. ret
  157. .align ALIGNMENT
  158. maxmatch:
  159. cmpsb
  160. jmp mismatch
  161. #else /* !(i386 || _I386 || _i386 || __i386) */
  162. /* ======================== 680x0 version ================================= */
  163. #if defined(m68k)||defined(mc68k)||defined(__mc68000__)||defined(__MC68000__)
  164. # ifndef mc68000
  165. # define mc68000
  166. # endif
  167. #endif
  168. #if defined(__mc68020__) || defined(__MC68020__) || defined(sysV68)
  169. # ifndef mc68020
  170. # define mc68020
  171. # endif
  172. #endif
  173. #if defined(mc68020) || defined(mc68000)
  174. #if (defined(mc68020) || defined(NeXT)) && !defined(UNALIGNED_OK)
  175. # define UNALIGNED_OK
  176. #endif
  177. #ifdef sysV68 /* Try Motorola Delta style */
  178. # define GLOBAL(symbol) global symbol
  179. # define TEXT text
  180. # define FILE(filename) file filename
  181. # define invert_maybe(src,dst) dst,src
  182. # define imm(data) &data
  183. # define reg(register) %register
  184. # define addl add.l
  185. # define addql addq.l
  186. # define blos blo.b
  187. # define bhis bhi.b
  188. # define bras bra.b
  189. # define clrl clr.l
  190. # define cmpmb cmpm.b
  191. # define cmpw cmp.w
  192. # define cmpl cmp.l
  193. # define lslw lsl.w
  194. # define lsrl lsr.l
  195. # define movel move.l
  196. # define movew move.w
  197. # define moveb move.b
  198. # define moveml movem.l
  199. # define subl sub.l
  200. # define subw sub.w
  201. # define subql subq.l
  202. # define IndBase(bd,An) (bd,An)
  203. # define IndBaseNdxl(bd,An,Xn) (bd,An,Xn.l)
  204. # define IndBaseNdxw(bd,An,Xn) (bd,An,Xn.w)
  205. # define predec(An) -(An)
  206. # define postinc(An) (An)+
  207. #else /* default style (Sun 3, NeXT, Amiga, Atari) */
  208. # define GLOBAL(symbol) .globl symbol
  209. # define TEXT .text
  210. # define FILE(filename) .even
  211. # define invert_maybe(src,dst) src,dst
  212. # if defined(sun) || defined(mc68k)
  213. # define imm(data) #data
  214. # else
  215. # define imm(data) \#data
  216. # endif
  217. # define reg(register) register
  218. # define blos bcss
  219. # if defined(sun) || defined(mc68k)
  220. # define movel movl
  221. # define movew movw
  222. # define moveb movb
  223. # endif
  224. # define IndBase(bd,An) An@(bd)
  225. # define IndBaseNdxl(bd,An,Xn) An@(bd,Xn:l)
  226. # define IndBaseNdxw(bd,An,Xn) An@(bd,Xn:w)
  227. # define predec(An) An@-
  228. # define postinc(An) An@+
  229. #endif /* styles */
  230. #define Best_Len reg(d0) /* unsigned */
  231. #define Cur_Match reg(d1) /* Ipos */
  232. #define Loop_Counter reg(d2) /* int */
  233. #define Scan_Start reg(d3) /* unsigned short */
  234. #define Scan_End reg(d4) /* unsigned short */
  235. #define Limit reg(d5) /* IPos */
  236. #define Chain_Length reg(d6) /* unsigned */
  237. #define Scan_Test reg(d7)
  238. #define Scan reg(a0) /* *uch */
  239. #define Match reg(a1) /* *uch */
  240. #define Prev_Address reg(a2) /* *Pos */
  241. #define Scan_Ini reg(a3) /* *uch */
  242. #define Match_Ini reg(a4) /* *uch */
  243. #define Stack_Pointer reg(sp)
  244. GLOBAL (_match_init)
  245. GLOBAL (_longest_match)
  246. TEXT
  247. FILE ("match.S")
  248. _match_init:
  249. rts
  250. /*-----------------------------------------------------------------------
  251. * Set match_start to the longest match starting at the given string and
  252. * return its length. Matches shorter or equal to prev_length are discarded,
  253. * in which case the result is equal to prev_length and match_start is
  254. * garbage.
  255. * IN assertions: cur_match is the head of the hash chain for the current
  256. * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
  257. */
  258. /* int longest_match (cur_match) */
  259. #ifdef UNALIGNED_OK
  260. # define pushreg 15928 /* d2-d6/a2-a4 */
  261. # define popreg 7292
  262. #else
  263. # define pushreg 16184 /* d2-d7/a2-a4 */
  264. # define popreg 7420
  265. #endif
  266. _longest_match:
  267. movel IndBase(4,Stack_Pointer),Cur_Match
  268. moveml imm(pushreg),predec(Stack_Pointer)
  269. movel _max_chain_length,Chain_Length
  270. movel _prev_length,Best_Len
  271. movel imm(_prev),Prev_Address
  272. movel imm(_window+MIN_MATCH),Match_Ini
  273. movel _strstart,Limit
  274. movel Match_Ini,Scan_Ini
  275. addl Limit,Scan_Ini
  276. subw imm(MAX_DIST),Limit
  277. bhis L__limit_ok
  278. clrl Limit
  279. L__limit_ok:
  280. cmpl invert_maybe(_good_match,Best_Len)
  281. blos L__length_ok
  282. lsrl imm(2),Chain_Length
  283. L__length_ok:
  284. subql imm(1),Chain_Length
  285. #ifdef UNALIGNED_OK
  286. movew IndBase(-MIN_MATCH,Scan_Ini),Scan_Start
  287. movew IndBaseNdxw(-MIN_MATCH-1,Scan_Ini,Best_Len),Scan_End
  288. #else
  289. moveb IndBase(-MIN_MATCH,Scan_Ini),Scan_Start
  290. lslw imm(8),Scan_Start
  291. moveb IndBase(-MIN_MATCH+1,Scan_Ini),Scan_Start
  292. moveb IndBaseNdxw(-MIN_MATCH-1,Scan_Ini,Best_Len),Scan_End
  293. lslw imm(8),Scan_End
  294. moveb IndBaseNdxw(-MIN_MATCH,Scan_Ini,Best_Len),Scan_End
  295. #endif
  296. bras L__do_scan
  297. L__long_loop:
  298. #ifdef UNALIGNED_OK
  299. movew IndBaseNdxw(-MIN_MATCH-1,Scan_Ini,Best_Len),Scan_End
  300. #else
  301. moveb IndBaseNdxw(-MIN_MATCH-1,Scan_Ini,Best_Len),Scan_End
  302. lslw imm(8),Scan_End
  303. moveb IndBaseNdxw(-MIN_MATCH,Scan_Ini,Best_Len),Scan_End
  304. #endif
  305. L__short_loop:
  306. lslw imm(1),Cur_Match
  307. movew IndBaseNdxl(0,Prev_Address,Cur_Match),Cur_Match
  308. cmpw invert_maybe(Limit,Cur_Match)
  309. dbls Chain_Length,L__do_scan
  310. bras L__return
  311. L__do_scan:
  312. movel Match_Ini,Match
  313. addl Cur_Match,Match
  314. #ifdef UNALIGNED_OK
  315. cmpw invert_maybe(IndBaseNdxw(-MIN_MATCH-1,Match,Best_Len),Scan_End)
  316. bne L__short_loop
  317. cmpw invert_maybe(IndBase(-MIN_MATCH,Match),Scan_Start)
  318. bne L__short_loop
  319. #else
  320. moveb IndBaseNdxw(-MIN_MATCH-1,Match,Best_Len),Scan_Test
  321. lslw imm(8),Scan_Test
  322. moveb IndBaseNdxw(-MIN_MATCH,Match,Best_Len),Scan_Test
  323. cmpw invert_maybe(Scan_Test,Scan_End)
  324. bne L__short_loop
  325. moveb IndBase(-MIN_MATCH,Match),Scan_Test
  326. lslw imm(8),Scan_Test
  327. moveb IndBase(-MIN_MATCH+1,Match),Scan_Test
  328. cmpw invert_maybe(Scan_Test,Scan_Start)
  329. bne L__short_loop
  330. #endif
  331. movew imm((MAX_MATCH-MIN_MATCH+1)-1),Loop_Counter
  332. movel Scan_Ini,Scan
  333. L__scan_loop:
  334. cmpmb postinc(Match),postinc(Scan)
  335. dbne Loop_Counter,L__scan_loop
  336. subl Scan_Ini,Scan
  337. addql imm(MIN_MATCH-1),Scan
  338. cmpl invert_maybe(Best_Len,Scan)
  339. bls L__short_loop
  340. movel Scan,Best_Len
  341. movel Cur_Match,_match_start
  342. #ifdef FULL_SEARCH
  343. cmpl invert_maybe(imm(MAX_MATCH),Best_Len)
  344. #else
  345. cmpl invert_maybe(_nice_match,Best_Len)
  346. #endif
  347. blos L__long_loop
  348. L__return:
  349. moveml postinc(Stack_Pointer),imm(popreg)
  350. rts
  351. #else
  352. error: this asm version is for 386 or 680x0 only
  353. #endif /* mc68000 || mc68020 */
  354. #endif /* i386 || _I386 || _i386 || __i386 */
  355. #endif /* !USE_ZLIB */