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