match_68.a 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. ;===========================================================================
  2. ; Copyright (c) 1990-1999 Info-ZIP. All rights reserved.
  3. ;
  4. ; See the accompanying file LICENSE, version 1999-Oct-05 or later
  5. ; (the contents of which are also included in zip.h) for terms of use.
  6. ; If, for some reason, both of these files are missing, the Info-ZIP license
  7. ; also may be found at: ftp://ftp.cdrom.com/pub/infozip/license.html
  8. ;===========================================================================
  9. ; This is a 68000 assembly language version of the Zip function
  10. ; longest_match(). It is written for any 680x0 based computer, but at this
  11. ; time the feature for runtime testing of CPU type is only supported for the
  12. ; Amiga. Hopefully a similar test for the Macintosh is possible, and for any
  13. ; other system that supports both 68000 and 68020+ CPUs. This is written by
  14. ; Paul Kienitz, partially derived from a simpler version by Carsten Steger,
  15. ; derived in turn from a 386 assembly function by Jean-loup Gailly and Kai Uwe
  16. ; Rommel... but also based directly on the C original.
  17. ;
  18. ; The main difference of this from other longest_match() implementations is
  19. ; that it includes both byte based and word based versions of the function,
  20. ; and various symbols can be defined to select whether to use one routine or
  21. ; the other, or to do a platform-specific test at runtime. The symbols that
  22. ; can be used to select behavior are as follows:
  23. ;
  24. ; CPU020 if defined, use 68020 instructions always
  25. ; CPUTEST if defined, check at runtime for CPU type. Another symbol
  26. ; specifying the platform-specific test must be used with this.
  27. ; If neither of these is defined, use 68000 instructions only.
  28. ; AMIGA use Amiga-specific test for 68020, if CPUTEST defined. Also
  29. ; tells it to let a0/a1/d1 be clobbered by functions.
  30. ; ATSIGN define entry symbols in @foo form as well as _foo, with
  31. ; @longest_match taking its parm in d0 instead of on the stack.
  32. ; WSIZE if defined, determines the sliding window size for deflate;
  33. ; the default is 32K. If you have reduced WSIZE for the C code,
  34. ; make sure that this module is assembled with an equivalent
  35. ; "-dWSIZE=<whatever>" (or "-e...") switch.
  36. ;
  37. ; NOTE: no provision is made for 16 bit ints. All external int variables are
  38. ; treated as 32 bit values. This also assumes that longest_match's result is
  39. ; returned in D0.
  40. IFND CPU020
  41. IFND CPUTEST
  42. CPU000 equ 1
  43. ENDC
  44. ENDC
  45. ; global variables:
  46. xref _max_chain_length ; unsigned int
  47. xref _prev_length ; unsigned int
  48. xref _match_start ; unsigned int
  49. xref _strstart ; unsigned int
  50. xref _good_match ; signed int
  51. xref _nice_match ; signed int
  52. xref _window ; array of unsigned char
  53. xref _prev ; array of unsigned short
  54. ; our entry points:
  55. xdef _match_init ; void match_init(void);
  56. xdef _longest_match ; int longest_match(unsigned cur_match);
  57. IFD ATSIGN
  58. xdef @match_init ; for SAS assembler
  59. xdef @longest_match ; ditto
  60. ENDC
  61. ; flag variable for remembering CPU type:
  62. IFD CPUTEST
  63. section cpuflag,data
  64. is020: ds.w 1
  65. ENDC
  66. section match,code
  67. _match_init:
  68. IFD ATSIGN
  69. @match_init:
  70. ENDC
  71. IFD CPUTEST ; now check for platform type
  72. IFD AMIGA ; Amiga specific test for '020 CPU:
  73. xref _SysBase
  74. NOLIST
  75. INCLUDE 'exec/execbase.i'
  76. LIST
  77. clr.w is020 ; default value is 68000
  78. move.l _SysBase,a0
  79. btst #AFB_68020,AttnFlags+1(a0)
  80. beq.s cheap
  81. move.w #1,is020
  82. cheap:
  83. ELSE ; !AMIGA
  84. !! Write an '020-detector for your system here!
  85. ENDC ; AMIGA
  86. ENDC ; CPUTEST
  87. rts ; match_init consists only of rts if CPUTEST unset
  88. IFD AMIGA
  89. SAVEREGS reg d3-d7/a2/a3/a5 ; don't protect d0/d1/a0/a1
  90. ELSE
  91. SAVEREGS reg d1/d3-d7/a0-a3/a5 ; protect all but d0 return val
  92. ENDC
  93. Cur_Match equr d0 ; Must be in d0!
  94. Best_Len equr d1
  95. Scan_Start equr d3
  96. Scan_End equr d4
  97. Limit equr d5
  98. Chain_Length equr d6
  99. Scan_Test equr d7
  100. Scan equr a0
  101. Match equr a1
  102. Prev_Address equr a2
  103. Scan_Ini equr a3
  104. Match_Ini equr a5
  105. MAX_MATCH equ 258
  106. MIN_MATCH equ 3
  107. IFND WSIZE
  108. WSIZE equ 32768
  109. ENDC
  110. MAX_DIST equ WSIZE-MAX_MATCH-MIN_MATCH-1
  111. _longest_match:
  112. move.l 4(sp),Cur_Match ; stack arg to register
  113. IFD ATSIGN
  114. @longest_match:
  115. ENDC
  116. movem.l SAVEREGS,-(sp)
  117. ; setup steps common to byte and word versions:
  118. move.l _max_chain_length,Chain_Length
  119. move.l _prev_length,Best_Len
  120. lea _prev,Prev_Address
  121. lea _window,Match_Ini
  122. move.l _strstart,Limit
  123. move.l Match_Ini,Scan_Ini
  124. addq #MIN_MATCH,Match_Ini
  125. add.l Limit,Scan_Ini
  126. subi.w #MAX_DIST,Limit
  127. bhi.s limit_ok
  128. moveq #0,Limit
  129. limit_ok:
  130. cmp.l _good_match,Best_Len
  131. bcs.s length_ok
  132. lsr.l #2,Chain_Length
  133. length_ok:
  134. subq.l #1,Chain_Length
  135. IFD CPUTEST
  136. tst.w is020 ; can we use '020 stuff today?
  137. bne WORD_match
  138. ENDC
  139. IFND CPU020
  140. ; for 68000 or 68010, use byte operations:
  141. moveq #0,Scan_Start ; clear 2nd and 4th bytes, use 1st & 3rd
  142. moveq #0,Scan_End
  143. moveq #0,Scan_Test
  144. move.b (Scan_Ini),Scan_Start
  145. swap Scan_Start
  146. move.b 1(Scan_Ini),Scan_Start
  147. move.b -1(Scan_Ini,Best_Len),Scan_End
  148. swap Scan_End
  149. move.b 0(Scan_Ini,Best_Len),Scan_End
  150. bra.s bdo_scan
  151. blong_loop:
  152. move.b -1(Scan_Ini,Best_Len),Scan_End
  153. swap Scan_End
  154. move.b 0(Scan_Ini,Best_Len),Scan_End
  155. bshort_loop:
  156. add.w Cur_Match,Cur_Match
  157. move.w 0(Prev_Address,Cur_Match.l),Cur_Match
  158. cmp.l Limit,Cur_Match
  159. dbls Chain_Length,bdo_scan
  160. bra return
  161. bdo_scan:
  162. move.l Match_Ini,Match
  163. add.l Cur_Match,Match
  164. move.b -MIN_MATCH-1(Match,Best_Len),Scan_Test
  165. swap Scan_Test
  166. move.b -MIN_MATCH(Match,Best_Len),Scan_Test
  167. cmp.l Scan_Test,Scan_End
  168. bne.s bshort_loop
  169. move.b -MIN_MATCH(Match),Scan_Test
  170. swap Scan_Test
  171. move.b -MIN_MATCH+1(Match),Scan_Test
  172. cmp.l Scan_Test,Scan_Start
  173. bne.s bshort_loop
  174. move.w #(MAX_MATCH-MIN_MATCH),Scan_Test
  175. lea MIN_MATCH(Scan_Ini),Scan
  176. bscan_loop:
  177. cmpm.b (Match)+,(Scan)+
  178. dbne Scan_Test,bscan_loop
  179. subq #1,Scan
  180. sub.l Scan_Ini,Scan
  181. cmp.l Best_Len,Scan
  182. bls.s bshort_loop
  183. move.l Scan,Best_Len
  184. move.l Cur_Match,_match_start
  185. cmp.l _nice_match,Best_Len
  186. bcs.s blong_loop
  187. IFD CPUTEST
  188. bra return
  189. ENDC
  190. ENDC ; !CPU020
  191. IFND CPU000
  192. ; for 68020 or higher, use word operations even on odd addresses:
  193. WORD_match:
  194. move.w (Scan_Ini),Scan_Start
  195. move.w -1(Scan_Ini,Best_Len),Scan_End
  196. bra.s wdo_scan
  197. wlong_loop:
  198. move.w -1(Scan_Ini,Best_Len),Scan_End
  199. wshort_loop:
  200. add.w Cur_Match,Cur_Match
  201. move.w (Prev_Address,Cur_Match.l),Cur_Match
  202. cmp.l Limit,Cur_Match
  203. dbls Chain_Length,wdo_scan
  204. bra.s return
  205. wdo_scan:
  206. move.l Match_Ini,Match
  207. add.l Cur_Match,Match
  208. cmp.w -MIN_MATCH-1(Match,Best_Len),Scan_End
  209. bne.s wshort_loop
  210. cmp.w -MIN_MATCH(Match),Scan_Start
  211. bne.s wshort_loop
  212. moveq #((MAX_MATCH-MIN_MATCH)/2),Scan_Test ; value = 127
  213. lea MIN_MATCH(Scan_Ini),Scan
  214. wscan_loop:
  215. cmpm.w (Match)+,(Scan)+
  216. dbne Scan_Test,wscan_loop
  217. subq #2,Scan
  218. move.b -MIN_MATCH+1(Match),Scan_Test
  219. cmp.b (Scan),Scan_Test
  220. bne steven
  221. addq #1,Scan
  222. steven:
  223. sub.l Scan_Ini,Scan
  224. cmp.l Best_Len,Scan
  225. bls.s wshort_loop
  226. move.l Scan,Best_Len
  227. move.l Cur_Match,_match_start
  228. cmp.l _nice_match,Best_Len
  229. bcs.s wlong_loop
  230. ENDC ; !CPU000
  231. return:
  232. move.l Best_Len,d0 ; function return value
  233. movem.l (sp)+,SAVEREGS
  234. rts
  235. end