summaryrefslogtreecommitdiff
path: root/Build/source/utils/gzip/amiga/match.a
blob: 0b458d2bf618e25be70f3b72e96bc874cefba410 (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
; match.a -- optional optimized asm version of longest match in deflate.c
; Copyright (C) 1992-1993 Jean-loup Gailly
; This is free software; you can redistribute it and/or modify it under the
; terms of the GNU General Public License, see the file COPYING.
 
; $Id: match.a,v 1.1 1993/03/11 16:05:57 jloup Exp $
;
; 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),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),Scan_End
	lsl.w	#8,Scan_End
	move.b	-MIN_MATCH(Scan_Ini,Best_Len),Scan_End

	endc

	bra.b	do_scan

long_loop:

	ifd	UNALIGNED_OK

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

	else

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

	endc

short_loop:
	lsl.w	#1,Cur_Match
	move.w	0(Prev_Address,Cur_Match),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),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),Scan_Test
	lsl.w	#8,Scan_Test
	move.b	-MIN_MATCH(Match,Best_Len),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