summaryrefslogtreecommitdiff
path: root/amiga/match.a
blob: ec5bcf0ecf6652501a802f3a7b5a1b062cd1a3e6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
;===========================================================================
; 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