1@ Tremolo library
2@-----------------------------------------------------------------------
3@ Copyright (C) 2002-2009, Xiph.org Foundation
4@ Copyright (C) 2010, Robin Watts for Pinknoise Productions Ltd
5@ All rights reserved.
6
7@ Redistribution and use in source and binary forms, with or without
8@ modification, are permitted provided that the following conditions
9@ are met:
10
11@     * Redistributions of source code must retain the above copyright
12@ notice, this list of conditions and the following disclaimer.
13@     * Redistributions in binary form must reproduce the above
14@ copyright notice, this list of conditions and the following disclaimer
15@ in the documentation and/or other materials provided with the
16@ distribution.
17@     * Neither the names of the Xiph.org Foundation nor Pinknoise
18@ Productions Ltd nor the names of its contributors may be used to
19@ endorse or promote products derived from this software without
20@ specific prior written permission.
21@
22@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23@ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24@ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25@ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26@ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27@ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28@ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29@ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31@ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33@ ----------------------------------------------------------------------
34
35    .text
36
37	.global	decode_packed_entry_number
38	.global decode_packed_entry_number_REALSTART
39	.global decode_map
40	.global vorbis_book_decodevv_add
41	.global _checksum
42
43	.extern	oggpack_adv
44	.extern	oggpack_look
45	.extern	oggpack_eop
46	.extern	crc_lookup
47	.hidden	crc_lookup
48
49decode_packed_entry_number_REALSTART:
50dpen_nobits:
51	MOV	r0,r5		@ r0 = b
52	MOV	r1,#1		@ r1 = 1
53	BL	oggpack_adv	@ oggpack_adv(b,1)      /* Force eop */
54duff:
55	MVN	r0,#0		@ return -1
56	LDMFD	r13!,{r4-r8,r10,PC}
57
58dpen_readfailed:
59	SUBS	r4,r4,#1	@ r4 = --read
60	BEQ	dpen_nobits
61	MOV	r0,r5		@ r0 = b
62	MOV	r1,r4		@ r1 = read
63	ADR	r14,dpen_read_return
64	B	oggpack_look
65
66decode_packed_entry_number:
67	@ r0 = codebook       *book
68	@ r1 = oggpack_buffer *b
69	STMFD	r13!,{r4-r8,r10,r14}
70
71	LDMIA	r0,{r4,r6,r7}		@ r4 = read = book->max_length
72					@ r6 = book->dec_table
73					@ r7 = book->dec_method
74	MOV	r5,r1		@ r5 = b
75
76	MOV	r0,r5		@ r0 = b
77	MOV	r1,r4		@ r1 = read
78	BL	oggpack_look
79dpen_read_return:
80	CMP	r0,#0
81	BLT	dpen_readfailed
82
83	@ r0 = lok
84	@ r4 = read
85	@ r5 = b
86	@ r6 = dec_table
87	@ r7 = dec_method
88
89	CMP	r7, #3
90	BGT	meth4
91	BEQ	meth3
92	CMP	r7, #1
93	BGT	meth2
94	BEQ	meth1
95meth0:
96	RSB	r1, r4, #0		@ r1 = i-read = 0-read
97	MOV	r7, #0			@ r7 = chase
98m0_loop:
99	MOVS	r0, r0, LSR #1		@ r0 = lok>>1   C = bottom bit
100	ADC	r2, r6, r7, LSL #1	@ r8 = &t[chase*2+C]
101	LDRB	r7, [r2]
102	ADDS	r1, r1, #1		@ r1 = i-read++ (i-read<0 => i<read)
103	@ stall Xscale
104	CMPLT	r7, #0x80
105	BLT	m0_loop
106	AND	r7, r7, #0x7F		@ r7 = chase
107	CMP	r1, #0			@ if (i-read >= 0) === (i >= read)
108	MVNGT	r7, #0			@ if (i >= read) value to return = -1
109	ADD	r1, r1, r4		@ r1 = i-read+read+1 = i +1
110	MOV	r0, r5			@ r0 = b
111	BL	oggpack_adv		@ oggpack_adv(b, i+1);
112	MOV	r0, r7			@ return chase
113	LDMFD	r13!,{r4-r8,r10,PC}
114
115meth1:
116	@ r0 = lok
117	@ r4 = read
118	@ r5 = b
119	@ r6 = dec_table
120	RSB	r1, r4, #0		@ r1 = i = -read
121	MOV	r10,#0			@ r10= next = 0
122m1_loop:
123	MOV	r7, r10			@ r7 = chase=next
124	MOVS	r0, r0, LSR #1		@ r0 = lok>>1     C = bottom bit
125	ADC	r8, r6, r7		@ r8 = t+chase+bit
126	LDRB	r10,[r8], -r6		@ r10= next=t[chase+bit] r8=chase+bit
127	ADDS	r1, r1, #1		@ r1 = i++
128	@ stall Xscale
129	CMPLT	r10,#0x80		@ if (next & 0x80) == 0
130	BLT	m1_loop
131
132	ADD	r1, r1, r4		@ r1 = i+read
133	MOV	r0, r5			@ r0 = b
134	BL	oggpack_adv		@ oggpack_adv(b, i)
135
136	CMP	r10,#0x80
137	BLT	duff
138
139	CMP	r8, r7			@ if bit==0 (chase+bit==chase) (sets C)
140	LDRNEB	r14,[r6, r7]		@ r14= t[chase]
141	MOVEQ	r14,#128
142	ADC	r12,r8, r6		@ r12= chase+bit+1+t
143	LDRB	r14,[r12,r14,LSR #7]	@ r14= t[chase+bit+1+(!bit || t[chase]0x0x80)]
144	BIC	r10,r10,#0x80		@ r3 = next &= ~0x80
145	@ stall Xscale
146	ORR	r0, r14,r10,LSL #8	@ r7 = chase = (next<<8) | r14
147
148	LDMFD	r13!,{r4-r8,r10,PC}
149
150
151meth2:
152	RSB	r1, r4, #0		@ r1 = i-read = 0-read
153	MOV	r7, #0			@ r7 = chase
154	MOV	r6, r6, LSR #1
155m2_loop:
156	MOVS	r0, r0, LSR #1		@ r0 = lok>>1   C = bottom bit
157	ADC	r2, r6, r7, LSL #1	@ r8 = &t[chase*2+C]
158	LDRH	r7, [r2, r2]
159	ADDS	r1, r1, #1		@ r1 = i-read++ (i-read<0 => i<read)
160	@ stall Xscale
161	CMPLT	r7, #0x8000
162	BLT	m2_loop
163	BIC	r7, r7, #0x8000		@ r7 = chase
164	CMP	r1, #0			@ if (i-read >= 0) === (i >= read)
165	MVNGT	r7, #0			@ if (i >= read) value to return = -1
166	ADD	r1, r1, r4		@ r1 = i-read+read+1 = i +1
167	MOV	r0, r5			@ r0 = b
168	BL	oggpack_adv		@ oggpack_adv(b, i+1);
169	MOV	r0, r7			@ return chase
170	LDMFD	r13!,{r4-r8,r10,PC}
171
172meth3:
173	@ r0 = lok
174	@ r4 = read
175	@ r5 = b
176	@ r6 = dec_table
177	RSB	r1, r4, #0		@ r1 = i = -read
178	MOV	r10,#0			@ r10= next = 0
179m3_loop:
180	MOV	r7, r10			@ r7 = chase=next
181	MOVS	r0, r0, LSR #1		@ r0 = lok>>1     C = bottom bit
182	ADC	r8, r7, #0		@ r8 = chase+bit
183	MOV	r8, r8, LSL #1		@ r8 = (chase+bit)<<1
184	LDRH	r10,[r6, r8]		@ r10= next=t[chase+bit]
185	ADDS	r1, r1, #1		@ r1 = i++
186	@ stall Xscale
187	CMPLT	r10,#0x8000		@ if (next & 0x8000) == 0
188	BLT	m3_loop
189
190	ADD	r1, r1, r4		@ r1 = i+read
191	MOV	r0, r5			@ r0 = b
192	BL	oggpack_adv		@ oggpack_adv(b, i)
193
194	CMP	r10,#0x8000
195	BLT	duff
196
197	MOV	r7, r7, LSL #1
198	CMP	r8, r7			@ if bit==0 (chase+bit==chase) sets C
199	LDRNEH	r14,[r6, r7]		@ r14= t[chase]
200	MOVEQ	r14,#0x8000
201	ADC	r12,r8, r14,LSR #15	@ r12= 1+((chase+bit)<<1)+(!bit || t[chase]0x0x8000)
202	ADC	r12,r12,r14,LSR #15	@ r12= t + (1+chase+bit+(!bit || t[chase]0x0x8000))<<1
203	LDRH	r14,[r6, r12]		@ r14= t[chase+bit+1
204	BIC	r10,r10,#0x8000		@ r3 = next &= ~0x8000
205	@ stall Xscale
206	ORR	r0, r14,r10,LSL #16	@ r7 = chase = (next<<16) | r14
207
208	LDMFD	r13!,{r4-r8,r10,PC}
209
210meth4:
211	RSB	r1, r4, #0		@ r1 = i-read = 0-read
212	MOV	r7, #0			@ r7 = chase
213m4_loop:
214	MOVS	r0, r0, LSR #1		@ r0 = lok>>1   C = bottom bit
215	ADC	r2, r7, r7		@ r8 = chase*2+C
216	LDR	r7, [r6, r2, LSL #2]
217	ADDS	r1, r1, #1		@ r1 = i-read++ (i-read<0 => i<read)
218	@ stall Xscale
219	CMPLT	r7, #0x80000000
220	BLT	m4_loop
221	BIC	r7, r7, #0x80000000	@ r7 = chase
222	CMP	r1, #0			@ if (i-read >= 0) === (i >= read)
223	MVNGT	r7, #0			@ if (i >= read) value to return = -1
224	ADD	r1, r1, r4		@ r1 = i-read+read+1 = i +1
225	MOV	r0, r5			@ r0 = b
226	BL	oggpack_adv		@ oggpack_adv(b, i+1);
227	MOV	r0, r7			@ return chase
228	LDMFD	r13!,{r4-r8,r10,PC}
229
230decode_map:
231	@ r0 = codebook *s
232	@ r1 = oggpack_buffer *b
233	@ r2 = int v
234	@ r3 = int point
235	STMFD	r13!,{r4-r11,r14}
236
237	MOV	r4, r0		@ r4 = s
238	MOV	r5, r1		@ r5 = b
239	MOV	r6, r2		@ r6 = v
240	MOV	r7, r3		@ r7 = point
241	BL	decode_packed_entry_number
242	MOV	r8, r0
243
244	MOV	r0, r5
245	BL	oggpack_eop
246	CMP	r0, #0
247	BNE	dm_duff
248
249	@ r4 = s
250	@ r5 = b
251	@ r6 = v
252	@ r7 = point
253	@ r8 = entry
254
255	LDR	r1, [r4,#12]	@ r1 = s->dec_type
256	LDR	r2, [r4,#16]	@ r2 = s->q_bits
257	LDR	r3, [r4,#20]	@ r3 = s->dim
258	LDR	r5, [r4,#24]	@ r5 = s->q_delp
259	LDR	r11,[r4,#28]	@ r11= s->q_minp
260	LDR	r12,[r4,#32]	@ r12= s->q_del = mul
261	LDR	r14,[r4,#36]	@ r14= s->q_min
262	SUBS	r11,r7, r11	@ r11= add    = point - s->q_minp
263
264	MOVGT	r14,r14,ASR r11	@ r14= add = s->q_min >> add  (if add >0)
265	RSBLT	r11,r11,#0
266	MOVLT	r14,r14,LSL r11	@ r14= add = s->q_min << -add (if add < 0)
267
268	SUBS	r5, r7, r5	@ r5 = shiftM = point - s->q_delp
269	LDR	r7, [r4,#40]	@ r7 = s->q_seq
270	RSBLT	r5, r5, #0	@ if (shiftM<0)  r5 =-shiftM
271	MOVLT	r12,r12,LSL r5	@                r12=mul<<-shiftM
272	MOVLT	r5, #0		@                r5 =shiftM = 0
273	MOVGT	r14,r14,LSL r5	@ add <<= shiftM
274
275	CMP	r7,#0		@ seqMask = (s->q_seq?-1:0)
276	MVNNE	r7,#0
277
278	CMP	r1, #2
279	BEQ	dm2
280	BGT	dm3
281	CMP	r1,#0		@ probably never happens
282	BLE	dm_duff
283dm1:
284	@ r1 = s->dec_type
285	@ r2 = s->q_bits
286	@ r3 = s->dim
287	@ r5 = shiftM
288	@ r6 = v
289	@ r7 = seqMask
290	@ r8 = entry
291	@ r12= mul
292	@ r14= add
293	MOV	r0, #1
294	RSB	r0, r0, r0, LSL r2	@ r0 = mask = (1<<s->q_bits)-1
295	MOV	r11,#0			@ r11= prev = 0
296dm1_loop:
297	AND	r1, r8, r0		@ r1 = v = entry & mask
298	MLA	r1, r12, r1, r14	@ r1 = (add + mul*v)
299	MOV	r8, r8, LSR r2		@ r8 = entry>>s->q_bits
300	SUBS	r3, r3, #1
301	ADD	r1, r11,r1, ASR r5	@ r1 = v = prev+((add+mul*v)>>shiftM)
302	AND	r11,r1, r7		@ r11= prev = seqMask & v
303	STR	r1, [r6], #4		@ *v++ = v
304	BGT	dm1_loop
305
306	MOV	r0, #0
307	LDMFD	r13!,{r4-r11,PC}
308dm2:
309	@ r1 = s->dec_type
310	@ r2 = s->q_bits
311	@ r3 = s->dim
312	@ r4 = s
313	@ r5 = shiftM
314	@ r6 = v
315	@ r7 = seqMask
316	@ r8 = entry
317	@ r12= mul
318	@ r14= add
319	LDR	r1, [r4,#44]		@ r1 = s->q_pack
320	LDR	r4, [r4,#48]		@ r4 = s->q_val
321	MOV	r11,#0			@ r11= prev
322	MOV	r0, #1
323	RSB	r0, r0, r0, LSL r1	@ r8 = mask = (1<<s->q_pack)-1
324	CMP	r2,#8
325	BGT	dm2_hword
326dm2_loop:
327	AND	r2, r8, r0		@ r2 = entry & mask
328	LDRB	r2, [r4, r2]		@ r2 = v = q->val[entry & mask]
329	MOV	r8, r8, LSR r1		@ r8 = entry>>q_pack
330	MLA	r2, r12,r2, r14		@ r2 = (add+mul*v)
331	SUBS	r3, r3, #1
332	ADD	r2, r11,r2, ASR r5	@ r2 = v = prev+(add+mul*v)>>shiftM
333	AND	r11,r2, r7		@ r11= prev = seqMask & v
334	STR	r2, [r6], #4		@ *v++ = v
335	BGT	dm2_loop
336	MOV	r0, #0
337	LDMFD	r13!,{r4-r11,PC}
338
339dm2_hword:
340	AND	r2, r8, r0		@ r2 = entry & mask
341	MOV	r2, r2, LSL #1		@ r2 = 2*r2
342	LDRH	r2, [r4, r2]		@ r2 = v = q->val[entry & mask]
343	MOV	r8, r8, LSR r1		@ r8 = entry>>q_pack
344	MLA	r2, r12,r2, r14		@ r2 = (add+mul*v)
345	SUBS	r3, r3, #1
346	ADD	r2, r11,r2, ASR r5	@ r2 = v = prev+(add+mul*v)>>shiftM
347	AND	r11,r2, r7		@ r11= prev = seqMask & v
348	STR	r2, [r6], #4		@ *v++ = v
349	BGT	dm2_hword
350	MOV	r0, #0
351	LDMFD	r13!,{r4-r11,PC}
352
353dm3:
354	@ r1 = s->dec_type
355	@ r2 = s->q_bits
356	@ r3 = s->dim
357	@ r4 = s
358	@ r5 = shiftM
359	@ r6 = v
360	@ r7 = seqMask
361	@ r8 = entry
362	@ r12= mul
363	@ r14= add
364	LDR	r1, [r4,#44]		@ r1 = s->q_pack
365	LDR	r4, [r4,#52]		@ r4 = s->q_val
366	CMP	r2,#8
367	MOV	r11,#0			@ r11= prev
368	MLA	r4,r1,r8,r4		@ r4 = ptr = s->q_val+entry*s->q_pack
369
370	BGT	dm3_hword
371dm3_loop:
372	LDRB	r2, [r4], #1		@ r2 = v = *ptr++
373	SUBS	r3, r3, #1
374	MLA	r2, r12,r2, r14		@ r2 = (add+mul*v)
375	ADD	r2, r11,r2, ASR r5	@ r2 = v = prev+(add+mul*v)>>shiftM
376	AND	r11,r2, r7		@ r11= prev = seqMask & v
377	STR	r2, [r6], #4		@ *v++ = v
378	BGT	dm3_loop
379	MOV	r0, #0
380	LDMFD	r13!,{r4-r11,PC}
381
382dm3_hword:
383	LDRH	r2, [r4], #2		@ r2 = *ptr++
384	SUBS	r3, r3, #1
385	MLA	r2, r12,r2, r14		@ r2 = (add+mul*v)
386	ADD	r2, r11,r2, ASR r5	@ r2 = v = prev+(add+mul*v)>>shiftM
387	AND	r11,r2, r7		@ r11= prev = seqMask & v
388	STR	r2, [r6], #4		@ *v++ = v
389	BGT	dm3_hword
390	MOV	r0, #0
391	LDMFD	r13!,{r4-r11,PC}
392
393dm_duff:
394	MVN	r0,#0
395	LDMFD	r13!,{r4-r11,PC}
396
397vorbis_book_decodevv_add:
398	@ r0 = codebook     *book
399	@ r1 = ogg_int32_t **a
400	@ r2 = long          offset
401	@ r3 = int           ch
402	@ <> = b
403	@ <> = n
404	@ <> = point
405	STMFD	r13!,{r4-r11,R14}
406	LDR	r7, [r0, #13*4]		@ r7 = used_entries
407	MOV	r9, r0			@ r9 = book
408	MOV	r10,r1			@ r10= 0xa[chptr]      chptr=0
409	MOV	r6, r3			@ r6 = ch
410	ADD	r8, r10,r3, LSL #2	@ r8 = 0xa[ch]
411	MOV	r11,r2			@ r11= offset
412	CMP	r7, #0			@ if (used_entries <= 0)
413	BLE	vbdvva_exit		@     exit
414	LDR	r5, [r13,#10*4]		@ r5 = n
415vbdvva_loop1:
416	@ r5 = n
417	@ r6 = ch
418	@ r8 = 0xa[ch]
419	@ r9 = book
420	@ r10= 0xa[chptr]
421	@ r11= offset
422	MOV	r0, r9			@ r0 = book
423	LDR	r1, [r13,# 9*4]		@ r1 = b
424	LDR	r2, [r9, #14*4]		@ r2 = v = dec_buf
425	LDR	r3, [r13,#11*4]		@ r3 = point
426	BL	decode_map
427	CMP	r0, #0
428	BNE	vbdvva_fail
429
430	LDR	r0, [r9, # 5*4]		@ r0 = book->dim
431	LDR	r1, [r9, #14*4]		@ r1 = v = dec_buf
432vbdvva_loop2:
433	LDR	r2, [r10],#4		@ r2 = a[chptr++]
434	LDR	r12,[r1], #4		@ r1 = v[j++]
435	CMP	r10,r8			@ if (chptr == ch)
436	SUBEQ	r10,r10,r6, LSL #2	@    chptr = 0
437	LDR	r14,[r2, r11,LSL #2]!	@ r2 = 0xa[chptr++][i] r14=[r12]
438	ADDEQ	r11,r11,#1		@    i++
439	SUBEQ	r5, r5, #1		@    n--
440	SUBS	r0, r0, #1		@ r0--
441	ADD	r12,r12,r14		@ r12= a[chptr++][i]+ v[j]
442	STR	r12,[r2]		@ r12= a[chptr++][i]+=v[j]
443	BGT	vbdvva_loop2
444	CMP	r5,#0
445	BGT	vbdvva_loop1
446vbdvva_exit:
447	MOV	r0, #0			@ return 0
448	LDMFD	r13!,{r4-r11,PC}
449vbdvva_fail:
450	MVN	r0, #0			@ return -1
451	LDMFD	r13!,{r4-r11,PC}
452
453_checksum:
454	@ r0 = ogg_reference *or
455	@ r1 = bytes
456	STMFD	r13!,{r5-r6,r14}
457
458	ADR	r6,.Lcrc_lookup
459	LDR	r5,[r6]
460	ADD	r5,r6
461	MOV	r14,#0			@ r14= crc_reg = 0
462	MOVS	r12,r0
463	BEQ	_cs_end
464_cs_loop1:
465	LDMIA	r12,{r0,r2,r3,r12}	@ r0 = or->buffer
466					@ r2 = or->begin
467					@ r3 = or->length
468					@ r12= or->next
469	LDR	r0,[r0]			@ r0 = or->buffer->data
470	CMP	r1,r3			@ r3 = post = (bytes < or->length ?
471	MOVLT	r3,r1			@              bytes : or->length)
472	MOVS	r6,r3			@ r6 = j = post
473	BEQ	_cs_no_bytes
474	ADD	r0,r0,r2		@ r0 = or->buffer->data + or->begin
475_cs_loop2:
476	LDRB	r2, [r0],#1		@ r2 = data[j]
477	@ stall
478	@ stall Xscale
479	EOR	r2, r2, r14,LSR #24	@ r2 = (crc_reg>>24)^data[j]
480	LDR	r2, [r5, r2, LSL #2]	@ r2 = crc_lkp[(crc_reg>>24)^data[j]]
481	SUBS	r6, r6, #1		@ j--
482	@ stall Xscale
483	EOR	r14,r2, r14,LSL #8	@ r14= crc_reg = (crc_reg<<8)^r2
484	BGT	_cs_loop2
485_cs_no_bytes:
486	SUBS	r1, r1, r3
487	CMPNE	r12,#0
488	BNE	_cs_loop1
489_cs_end:
490	MOV	r0,r14
491	LDMFD	r13!,{r5-r6,PC}
492
493.Lcrc_lookup:
494        .WORD   crc_lookup-.Lcrc_lookup
495
496	@ END
497