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