aboutsummaryrefslogtreecommitdiff
path: root/engines/scumm/smush/codec47ARM.s
blob: 81bfdb2d222f272cdd1f72609befe2bb00464872 (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
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
@ ScummVM - Graphic Adventure Engine
@
@ ScummVM is the legal property of its developers, whose names
@ are too numerous to list here. Please refer to the COPYRIGHT
@ file distributed with this source distribution.
@
@ This program is free software@ you can redistribute it and/or
@ modify it under the terms of the GNU General Public License
@ as published by the Free Software Foundation@ either version 2
@ of the License, or (at your option) any later version.
@
@ This program is distributed in the hope that it will be useful,
@ but WITHOUT ANY WARRANTY@ without even the implied warranty of
@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
@ GNU General Public License for more details.
@
@ You should have received a copy of the GNU General Public License
@ along with this program@ if not, write to the Free Software
@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@
@ $URL$
@ $Id$
@
@ @author Robin Watts (robin@wss.co.uk)
@
@ This file, provides an ARM optimised version of sections of codec47.cpp.
@ The algorithm is essentially the same as that within codec47.cpp
@ so to understand this file you should understand codec47.cpp first.

	.text

	.global	_ARM_Smush_decode2

_ARM_Smush_decode2:
	@ r0 = dst
	@ r1 = src
	@ r2 = width
	@ r3 = height
	@ r4 = param
	@ <> = _table
	@ <> = _tableBig
	@ <> = _offset1
	@ <> = _offset2
	@ <> = _tableSmall
	STMFD	r13!,{r2,r4-r11,R14}

        LDR	r4,[r13,#40]	@ r4 = param (40 = (9+1)*4)
	@ stall
	@ stall
	SUB	r4,r4,#0xF8

	@ r0 = dst
	@ r1 = _d_src
	@ r2 = _d_pitch
	@ r3 = height
	@ r4 = param
	ADD	r7,r2,#7		@ r14 = bw
	MOV	r7,r7,LSR #3
y_loop:
x_loop:
	@ LEVEL 1
	LDRB	r6,[r1],#1		@ r6 = *_d_src++
	@ stall
	@ stall
	CMP	r6,#0xF8
	BLT	level1codeSMALL
	CMP	r6,#0xFC
	BLT	level1codeMID
	BEQ	level1codeFC
	CMP	r6,#0xFE
	BGT	level1codeFF
	BEQ	level1codeFE
level1codeFD:
	LDRB	r6,[r1],#1		@ r6 = tmp = *_d_src++
	LDR	r8,[r13,#48]		@ r8 = _tableBig (48 = (9+1+2)*4)
	@ stall
	ADD	r12,r6,r6,LSL #1	@ r12= tmp*3
	ADD	r6,r6,r12,LSL #5	@ r6 = tmp*97
	ADD	r8,r8,r6,LSL #2		@ r8 = _tableBig + tmp*388
	LDRB	r9,[r8,#384]		@ r9 = l = tmp_ptr[384]
	LDRB	r6,[r1],#1		@ r6 = val = *_d_src++
	ADD	r12,r8,#384		@ r12= &tmp_ptr[384]
	@ I don't really believe the next 2 lines are necessary, but...
	CMP	r9,#0
	BEQ	level1codeFD_over1
level1codeFD_loop1:
	LDRB	r10,[r8],#1
	LDRB	r11,[r8],#1
	SUBS	r9,r9,#1
	ADD	r10,r10,r0
	STRB	r6,[r10,r11,LSL #8]	@ *(_d_dst + (*tmp_ptr2++)) = val
	BGT	level1codeFD_loop1
level1codeFD_over1:
	LDRB	r9,[r12,#1]		@ r9 = l = tmp_ptr[385]
	LDRB	r6,[r1],#1		@ r6 = val = *_d_src++
	SUB	r12,r12,#256		@ r12= &tmp_ptr[128] (256 = 384-128)
	@ I don't really believe the next 2 lines are necessary, but...
	CMP	r9,#0
	BEQ	level1codeFD_over2
level1codeFD_loop2:
	LDRB	r10,[r12],#1
	LDRB	r11,[r12],#1
	SUBS	r9,r9,#1
	ADD	r10,r10,r0
	STRB	r6,[r10,r11,LSL #8]	@ *(_d_dst + (*tmp_ptr2++)) = val
	BGT	level1codeFD_loop2
level1codeFD_over2:
level1_end:

	ADD	r0,r0,#8
	SUBS	r7,r7,#1
	BGT	x_loop

	ADD	r7,r2,#7
	MOV	r7,r7,LSR #3
	ADD	r0,r0,r2,LSL #3
	SUB	r0,r0,r7,LSL #3	@ r0 = dst += next_line
	SUBS	r3,r3,#8	@ if (--bh > 0)
	BGT	y_loop		@   loop back

	LDMFD	r13!,{r2,r4-r11,PC}

level1codeSMALL:
	LDR	r8,[r13,#44]		@ r8 = _table (44 = (9+1+1)*4)
	LDR	r9,[r13,#52]		@ r9 = _offset1 (52 = (9+1+3)*4)
	MOV	r6,r6,LSL #1		@ r6 = code<<1
	LDRSH	r8,[r8,r6]		@ tmp2 = _table[code]
level1codeFC:
	@ EQ => FC
	LDREQ	r9,[r13,#56]		@ r9 = _offset2 (56 = (9+1+4)*4)
	MOVEQ	r8,#0
	SUB	r11,r2,#7		@ r11 = _d_pitch-7
	ADD	r9,r9,r0		@ tmp2 = _d_dst+_offset
	ADD	r8,r8,r9		@ tmp2 = _d_dst+_table[code]+_offset
					@ r8 = &_dst[tmp2]
	MOV	r12,#8
level1codeSMALL_loop:
	LDRB	r5, [r8],#1		@ r5  = d_dst[tmp2]
	LDRB	r6, [r8],#1		@ r10 = d_dst[tmp2]
	LDRB	r9, [r8],#1		@ r10 = d_dst[tmp2]
	LDRB	r10,[r8],#1		@ r10 = d_dst[tmp2]
	STRB	r5, [r0],#1		@ d_dst[0] = r5
	STRB	r6, [r0],#1		@ d_dst[1] = r6
	STRB	r9, [r0],#1		@ d_dst[2] = r9
	STRB	r10,[r0],#1		@ d_dst[3] = r10
	LDRB	r5, [r8],#1		@ r5  = d_dst[tmp2]
	LDRB	r6, [r8],#1		@ r10 = d_dst[tmp2]
	LDRB	r9, [r8],#1		@ r10 = d_dst[tmp2]
	LDRB	r10,[r8],r11		@ r10 = d_dst[tmp2]
	STRB	r5, [r0],#1		@ d_dst[4] = r5
	STRB	r6, [r0],#1		@ d_dst[5] = r6
	STRB	r9, [r0],#1		@ d_dst[6] = r9
	STRB	r10,[r0],r11		@ d_dst[7] = r10   d_dst += d_pitch
	SUBS	r12,r12,#1
	BGT	level1codeSMALL_loop
	SUB	r0,r0,r2,LSL #3		@ revert d_dst
	B	level1_end

level1codeMID:
	@ LT => F8<=code<FC case
	@ EQ => FE case
	LDRB	r6,[r4,r6]		@ r6 = t = _paramPtr[code]
level1codeFE:
	LDREQB	r6,[r1],#1		@ r6 = t = *_d_src++
	MOV	r12,#8
	SUB	r11,r2,#7		@ r11 = _d_pitch-7
level1codeMID_loop:
	STRB	r6,[r0],#1
	STRB	r6,[r0],#1
	STRB	r6,[r0],#1
	STRB	r6,[r0],#1
	STRB	r6,[r0],#1
	STRB	r6,[r0],#1
	STRB	r6,[r0],#1
	STRB	r6,[r0],r11
	SUBS	r12,r12,#1
	BGT	level1codeMID_loop
	SUB	r0,r0,r2,LSL #3		@ revert d_dst
	B	level1_end

level1codeFF:
	BL	level2
	ADD	r0,r0,#4
	BL	level2
	ADD	r0,r0,r2,LSL #2
	SUB	r0,r0,#4
	BL	level2
	ADD	r0,r0,#4
	BL	level2
	SUB	r0,r0,#4
	SUB	r0,r0,r2,LSL #2
	B	level1_end

level2:
	@ r0 = _d_dst
	@ r1 = _d_src
	@ r2 = _d_pitch
	@ r3 = PRESERVE
	@ r4 = param
	@ r7 = PRESERVE
	@ r14= return address
	LDRB	r6,[r1],#1		@ r6 = *_d_src++
	@ stall
	@ stall
	CMP	r6,#0xF8
	BLT	level2codeSMALL
	CMP	r6,#0xFC
	BLT	level2codeMID
	BEQ	level2codeFC
	CMP	r6,#0xFE
	BGT	level2codeFF
	BEQ	level2codeFE
level2codeFD:
	LDRB	r6,[r1],#1		@ r6 = tmp = *_d_src++
	LDR	r8,[r13,#60]		@ r8 = _tableSmall (60 = (9+1+5)*4)
	@ stall
	@ stall
	ADD	r8,r8,r6,LSL #7		@ r8 = _tableSmall + tmp*128
	LDRB	r9,[r8,#96]		@ r9 = l = tmp_ptr[96]
	LDRB	r6,[r1],#1		@ r6 = val = *_d_src++
	ADD	r12,r8,#32		@ r12 = tmp_ptr + 32
	@ I don't really believe the next 2 lines are necessary, but...
	CMP	r9,#0
	BEQ	level2codeFD_over1
level2codeFD_loop1:
	LDRB	r10,[r8],#1
	LDRB	r11,[r8],#1
	SUBS	r9,r9,#1
	ADD	r10,r10,r0
	STRB	r6,[r10,r11,LSL #8]	@ *(_d_dst + (*tmp_ptr2++)) = val
	BGT	level2codeFD_loop1
level2codeFD_over1:
	LDRB	r9,[r12,#65]		@ r9 = l = tmp_ptr[97] (65 = 97-32)
	LDRB	r6,[r1],#1		@ r6 = val = *_d_src++
	@ I don't really believe the next 2 lines are necessary, but...
	CMP	r9,#0
	MOVEQ	PC,R14
level2codeFD_loop2:
	LDRB	r10,[r12],#1
	LDRB	r11,[r12],#1
	SUBS	r9,r9,#1
	ADD	r10,r10,r0
	STRB	r6,[r10,r11,LSL #8]	@ *(_d_dst + (*tmp_ptr2++)) = val
	BGT	level2codeFD_loop2

	MOV	PC,R14

level2codeSMALL:
	LDR	r8,[r13,#44]		@ r8 = _table (44 = (9+1+1)*4)
	LDR	r9,[r13,#52]		@ r9 = _offset1 (52 = (9+1+3)*4)
	MOV	r6,r6,LSL #1		@ r6 = code<<1
	LDRSH	r8,[r8,r6]		@ tmp2 = _table[code]
level2codeFC:
	@ EQ => FC
	LDREQ	r9,[r13,#56]		@ r9 = _offset2 (56 = (9+1+4)*4)
	MOVEQ	r8,#0
	SUB	r11,r2,#3		@ r11 = _d_pitch-3
	ADD	r9,r9,r0		@ tmp2 = _d_dst + _table[code]
	ADD	r8,r8,r9		@ tmp2 = _d_dst+_table[code]+_offset1
					@ r8 = &_dst[tmp2]
	MOV	r12,#4
level2codeSMALL_loop:
	LDRB	r5, [r8],#1		@ r5  = d_dst[tmp2]
	LDRB	r6, [r8],#1		@ r10 = d_dst[tmp2]
	LDRB	r9, [r8],#1		@ r10 = d_dst[tmp2]
	LDRB	r10,[r8],r11		@ r10 = d_dst[tmp2]
	STRB	r5, [r0],#1		@ d_dst[4] = r5
	STRB	r6, [r0],#1		@ d_dst[5] = r6
	STRB	r9, [r0],#1		@ d_dst[6] = r9
	STRB	r10,[r0],r11		@ d_dst[7] = r10   d_dst += d_pitch
	SUBS	r12,r12,#1
	BGT	level2codeSMALL_loop
	SUB	r0,r0,r2,LSL #2		@ revert d_dst
	MOV	PC,R14

level2codeMID:
	@ LT => F8<=code<FC case
	@ EQ => FE case
	LDRB	r6,[r4,r6]		@ r6 = t = _paramPtr[code]
level2codeFE:
	LDREQB	r6,[r1],#1		@ r6 = t = *_d_src++
	MOV	r12,#4
	SUB	r11,r2,#3		@ r11 = _d_pitch-7
level2codeMID_loop:
	STRB	r6,[r0],#1
	STRB	r6,[r0],#1
	STRB	r6,[r0],#1
	STRB	r6,[r0],r11
	SUBS	r12,r12,#1
	BGT	level2codeMID_loop
	SUB	r0,r0,r2,LSL #2		@ revert d_dst
	MOV	PC,R14

level2codeFF:
	MOV	r5,r14
	BL	level3
	ADD	r0,r0,#2
	BL	level3
	ADD	r0,r0,r2,LSL #1
	SUB	r0,r0,#2
	BL	level3
	ADD	r0,r0,#2
	BL	level3
	SUB	r0,r0,#2
	SUB	r0,r0,r2,LSL #1
	MOV	PC,R5

level3:
	@ r0 = _d_dst
	@ r1 = _d_src
	@ r2 = _d_pitch
	@ r3 = PRESERVE
	@ r4 = param
	@ r5 = preserve
	@ r7 = PRESERVE
	@ r14= return address
	LDRB	r6,[r1],#1		@ r6 = code = *_d_src++
	@ stall
	@ stall
	CMP	r6,#0xF8
	BLT	level3codeSMALL
	CMP	r6,#0xFC
	BLT	level3codeMID
	BEQ	level3codeFC
	CMP	r6,#0xFE
	BGT	level3codeFF
level3codeFE:
	LDRB	r6,[r1],#1		@ r6 = t = *_d_src++
level3codeMID:
	@ LT => F8<=code<FC case
	@ EQ => FE case
	LDRLTB	r6,[r4,r6]		@ r6 = t = _paramPtr[code]
	@ stall
	@ stall
	STRB	r6,[r0,#1]
	STRB	r6,[r0],r2
	STRB	r6,[r0,#1]
	STRB	r6,[r0],-r2
	MOV	PC,R14

level3codeFF:
	LDRB	r6,[r1],#1
	LDRB	r9,[r1],#1
	LDRB	r10,[r1],#1
	LDRB	r11,[r1],#1
	STRB	r9, [r0,#1]
	STRB	r6, [r0],r2
	STRB	r11,[r0,#1]
	STRB	r10,[r0],-r2
	MOV	PC,R14

level3codeSMALL:
	LDR	r8,[r13,#44]		@ r8 = _table (44 = (9+1+1)*4)
	LDR	r9,[r13,#52]		@ r9 = _offset1 (52 = (9+1+3)*4)
	MOV	r6,r6,LSL #1		@ r6 = code<<1
	LDRSH	r8,[r8,r6]		@ tmp2 = _table[code]
level3codeFC:
	@ EQ => FC
	LDREQ	r9,[r13,#56]		@ r9 = _offset2 (56 = (9+1+4)*4)
	MOVEQ	r8,#0
	ADD	r9,r9,r0		@ tmp2 = _d_dst+offset
	ADD	r8,r8,r9		@ tmp2 = _d_dst+_table[code]+_offset
					@ r8 = &_dst[tmp2]
	LDRB	r6, [r8,#1]		@ r6 = d_dst[tmp2+1]
	LDRB	r9, [r8],r2		@ r9 = d_dst[tmp2+0]
	LDRB	r10,[r8,#1]		@ r10= d_dst[tmp2+dst+1]
	LDRB	r11,[r8],-r2		@ r11= d_dst[tmp2+dst]
	STRB	r6, [r0,#1]		@ d_dst[1    ] = r6
	STRB	r9, [r0],r2		@ d_dst[0    ] = r9
	STRB	r10,[r0,#1]		@ d_dst[dst+1] = r10
	STRB	r11,[r0],-r2		@ d_dst[dst  ] = r11
	MOV	PC,R14