home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 9 Archive / 09-Archive.zip / zip22.zip / amiga / match_68.a < prev    next >
Text File  |  1996-12-14  |  8KB  |  266 lines

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