Metropoli BBS
VIEWER: match.a MODE: TEXT (ASCII)
; match.a -- optional optimized asm version of longest match in deflate.c
; Copyright (C) 1992-1993 Jean-loup Gailly
;
; Adapted for the Amiga by Carsten Steger <stegerc@informatik.tu-muenchen.de>
; using the code in match.S.
; The major change in this code consists of removing all unaligned
; word accesses, because they cause 68000-based Amigas to crash.
; For maximum speed, UNALIGNED_OK can be defined in Makefile.sasc.
; The program will then only run on 68020-based Amigas, though.
;
; This code will run with registerized parameters too, unless SAS
; changes parameter passing conventions between new releases of SAS/C.


Cur_Match       reg     d0      ; Must be in d0!
Best_Len        reg     d1
Loop_Counter    reg     d2
Scan_Start      reg     d3
Scan_End        reg     d4
Limit           reg     d5
Chain_Length    reg     d6
Scan_Test       reg     d7
Scan            reg     a0
Match           reg     a1
Prev_Address    reg     a2
Scan_Ini        reg     a3
Match_Ini       reg     a4

MAX_MATCH       equ     258
MIN_MATCH       equ     3
WSIZE           equ     32768
MAX_DIST        equ     WSIZE-MAX_MATCH-MIN_MATCH-1


        xref    _max_chain_length
        xref    _prev_length
        xref    _prev
        xref    _window
        xref    _strstart
        xref    _good_match
        xref    _match_start
        xref    _nice_match


        section match,code

        xdef    _match_init
        xdef    @match_init
        xdef    _longest_match
        xdef    @longest_match


_match_init:
@match_init:
        rts


_longest_match:
        move.l  4(sp),Cur_Match
@longest_match:
        ifd     UNALIGNED_OK
        movem.l d2-d6/a2-a4,-(sp)
        else
        movem.l d2-d7/a2-a4,-(sp)
        endc
        move.l  _max_chain_length,Chain_Length
        move.l  _prev_length,Best_Len
        lea     _prev,Prev_Address
        lea     _window+MIN_MATCH,Match_Ini
        move.l  _strstart,Limit
        move.l  Match_Ini,Scan_Ini
        add.l   Limit,Scan_Ini
        subi.w  #MAX_DIST,Limit
        bhi.b   limit_ok
        moveq   #0,Limit
limit_ok:
        cmp.l   _good_match,Best_Len
        bcs.b   length_ok
        lsr.l   #2,Chain_Length
length_ok:
        subq.l  #1,Chain_Length

        ifd     UNALIGNED_OK

        move.w  -MIN_MATCH(Scan_Ini),Scan_Start
        move.w  -MIN_MATCH-1(Scan_Ini,Best_Len.L),Scan_End

        else

        move.b  -MIN_MATCH(Scan_Ini),Scan_Start
        lsl.w   #8,Scan_Start
        move.b  -MIN_MATCH+1(Scan_Ini),Scan_Start
        move.b  -MIN_MATCH-1(Scan_Ini,Best_Len.L),Scan_End
        lsl.w   #8,Scan_End
        move.b  -MIN_MATCH(Scan_Ini,Best_Len.L),Scan_End

        endc

        bra.b   do_scan

long_loop:

        ifd     UNALIGNED_OK

        move.w  -MIN_MATCH-1(Scan_Ini,Best_Len.L),Scan_End

        else

        move.b  -MIN_MATCH-1(Scan_Ini,Best_Len.L),Scan_End
        lsl.w   #8,Scan_End
        move.b  -MIN_MATCH(Scan_Ini,Best_Len.L),Scan_End

        endc

short_loop:
        lsl.w   #1,Cur_Match
        move.w  0(Prev_Address,Cur_Match.L),Cur_Match
        cmp.w   Limit,Cur_Match
        dbls    Chain_Length,do_scan
        bra.b   return

do_scan:
        move.l  Match_Ini,Match
        add.l   Cur_Match,Match

        ifd     UNALIGNED_OK

        cmp.w   -MIN_MATCH-1(Match,Best_Len.L),Scan_End
        bne.b   short_loop
        cmp.w   -MIN_MATCH(Match),Scan_Start
        bne.b   short_loop

        else

        move.b  -MIN_MATCH-1(Match,Best_Len.L),Scan_Test
        lsl.w   #8,Scan_Test
        move.b  -MIN_MATCH(Match,Best_Len.L),Scan_Test
        cmp.w   Scan_Test,Scan_End
        bne.b   short_loop
        move.b  -MIN_MATCH(Match),Scan_Test
        lsl.w   #8,Scan_Test
        move.b  -MIN_MATCH+1(Match),Scan_Test
        cmp.w   Scan_Test,Scan_Start
        bne.b   short_loop

        endc

        move.w  #(MAX_MATCH-MIN_MATCH),Loop_Counter
        move.l  Scan_Ini,Scan
scan_loop:
        cmpm.b  (Match)+,(Scan)+
        dbne    Loop_Counter,scan_loop

        sub.l   Scan_Ini,Scan
        addq.l  #(MIN_MATCH-1),Scan
        cmp.l   Best_Len,Scan
        bls.b   short_loop
        move.l  Scan,Best_Len
        move.l  Cur_Match,_match_start
        cmp.l   _nice_match,Best_Len
        bcs.b   long_loop
return:
        move.l  Best_Len,d0
        ifd     UNALIGNED_OK
        movem.l (sp)+,d2-d6/a2-a4
        else
        movem.l (sp)+,d2-d7/a2-a4
        endc
        rts

        end
[ RETURN TO DIRECTORY ]