182 lines
5 KiB
Text
182 lines
5 KiB
Text
;===========================================================================
|
|
; Copyright (c) 1990-1999 Info-ZIP. All rights reserved.
|
|
;
|
|
; See the accompanying file LICENSE, version 1999-Oct-05 or later
|
|
; (the contents of which are also included in zip.h) for terms of use.
|
|
; If, for some reason, both of these files are missing, the Info-ZIP license
|
|
; also may be found at: ftp://ftp.cdrom.com/pub/infozip/license.html
|
|
;===========================================================================
|
|
; match.a -- optional optimized asm version of longest match in deflate.c
|
|
; Written by 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.
|
|
; If you have reduced WSIZE in zip.h, then make sure this is
|
|
; assembled with an equivalent -dWSIZE=<whatever>.
|
|
;
|
|
; 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
|
|
ifnd WSIZE
|
|
WSIZE equ 32768
|
|
endc
|
|
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
|