• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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	oggpack_look
38	.global	oggpack_adv
39	.global	oggpack_readinit
40	.global	oggpack_read
41
42	.type	oggpack_look, %function
43	.type	oggpack_adv, %function
44	.type	oggpack_readinit, %function
45	.type	oggpack_read, %function
46
47oggpack_look:
48	@ r0 = oggpack_buffer *b
49	@ r1 = int             bits
50	STMFD	r13!,{r10,r11,r14}
51	LDMIA	r0,{r2,r3,r12}
52					@ r2 = bitsLeftInSegment
53					@ r3 = ptr
54					@ r12= bitsLeftInWord
55	SUBS	r2,r2,r1		@ bitsLeftinSegment -= bits
56	BLT	look_slow		@ Not enough bits in this segment for
57					@ this request. Do it slowly.
58	LDR	r10,[r3]		@ r10= ptr[0]
59	RSB	r14,r12,#32		@ r14= 32-bitsLeftInWord
60	SUBS	r12,r12,r1		@ r12= bitsLeftInWord -= bits
61	LDRLT	r11,[r3,#4]!		@ r11= ptr[1]
62	MOV	r10,r10,LSR r14		@ r10= ptr[0]>>(32-bitsLeftInWord)
63	ADDLE	r12,r12,#32		@ r12= bitsLeftInWord += 32
64	RSB	r14,r14,#32		@ r14= 32-bitsLeftInWord
65	ORRLT	r10,r10,r11,LSL r14	@ r10= Next 32 bits.
66	MOV	r14,#1
67	RSB	r14,r14,r14,LSL r1
68	AND	r0,r10,r14
69	LDMFD	r13!,{r10,r11,PC}
70
71look_slow:
72	STMFD	r13!,{r5,r6}
73	ADDS	r10,r2,r1		@ r10= bitsLeftInSegment + bits (i.e.
74					@ the initial value of bitsLeftInSeg)
75	@ r10 = bitsLeftInSegment (initial)
76	@ r12 = bitsLeftInWord
77	RSB	r14,r12,#32		@ r14= 32-bitsLeftInWord
78	MOV	r5,r10			@ r5 = bitsLeftInSegment (initial)
79	BLT	look_overrun
80	BEQ	look_next_segment	@ r10= r12 = 0, if we branch
81	CMP	r12,r10			@ If bitsLeftInWord < bitsLeftInSeg
82					@ there must be more in the next word
83	LDR	r10,[r3],#4		@ r10= ptr[0]
84	LDRLT	r6,[r3]			@ r6 = ptr[1]
85	MOV	r11,#1
86	MOV	r10,r10,LSR r14		@ r10= first bitsLeftInWord bits
87	ORRLT	r10,r10,r6,LSL r12	@ r10= first bitsLeftInSeg bits+crap
88	RSB	r11,r11,r11,LSL r5	@ r11= mask
89	AND	r10,r10,r11		@ r10= first r5 bits
90	@ Load the next segments data
91look_next_segment:
92	@ At this point, r10 contains the first r5 bits of the result
93	LDR	r11,[r0,#12]		@ r11= head = b->head
94	@ Stall
95	@ Stall
96look_next_segment_2:
97	LDR	r11,[r11,#12]		@ r11= head = head->next
98	@ Stall
99	@ Stall
100	CMP	r11,#0
101	BEQ	look_out_of_data
102	LDMIA	r11,{r6,r12,r14}	@ r6 = buffer
103					@ r12= begin
104					@ r14= length
105	LDR	r6,[r6]			@ r6 = buffer->data
106	CMP	r14,#0
107	BEQ	look_next_segment_2
108	ADD	r6,r6,r12		@ r6 = buffer->data+begin
109look_slow_loop:
110	LDRB	r12,[r6],#1		@ r12= *buffer
111	SUBS	r14,r14,#1		@ r14= length
112	@ Stall
113	ORR	r10,r10,r12,LSL r5	@ r10= first r5+8 bits
114	ADD	r5,r5,#8
115	BLE	look_really_slow
116	CMP	r5,r1
117	BLT	look_slow_loop
118	MOV	r14,#1
119	RSB	r14,r14,r14,LSL r1
120	AND	r0,r10,r14
121	LDMFD	r13!,{r5,r6,r10,r11,PC}
122
123
124look_really_slow:
125	CMP	r5,r1
126	BLT	look_next_segment_2
127	MOV	r14,#1
128	RSB	r14,r14,r14,LSL r1
129	AND	r0,r10,r14
130	LDMFD	r13!,{r5,r6,r10,r11,PC}
131
132look_out_of_data:
133	@MVN	r0,#0			; return -1
134	MOV	r0,#0
135	LDMFD	r13!,{r5,r6,r10,r11,PC}
136
137look_overrun:
138	@ We had overrun when we started, so we need to skip -r10 bits.
139	LDR	r11,[r0,#12]		@ r11 = head = b->head
140	@ stall
141	@ stall
142look_overrun_next_segment:
143	LDR	r11,[r11,#12]		@ r11 = head->next
144	@ stall
145	@ stall
146	CMP	r11,#0
147	BEQ	look_out_of_data
148	LDMIA	r11,{r6,r7,r14}		@ r6 = buffer
149					@ r7 = begin
150					@ r14= length
151	LDR	r6,[r6]			@ r6 = buffer->data
152	@ stall
153	@ stall
154	ADD	r6,r6,r7		@ r6 = buffer->data+begin
155	MOV	r14,r14,LSL #3		@ r14= length in bits
156	ADDS	r14,r14,r10		@ r14= length in bits-bits to skip
157	MOVLE	r10,r14
158	BLE	look_overrun_next_segment
159	RSB	r10,r10,#0		@ r10= bits to skip
160	ADD	r6,r10,r10,LSR #3	@ r6 = pointer to data
161	MOV	r10,#0
162	B	look_slow_loop
163
164oggpack_adv:
165	@ r0 = oggpack_buffer *b
166	@ r1 = bits
167	LDMIA	r0,{r2,r3,r12}
168					@ r2 = bitsLeftInSegment
169					@ r3 = ptr
170					@ r12= bitsLeftInWord
171	SUBS	r2,r2,r1		@ Does this run us out of bits in the
172	BLE	adv_slow		@ segment? If so, do it slowly
173	SUBS	r12,r12,r1
174	ADDLE	r12,r12,#32
175	ADDLE	r3,r3,#4
176	STMIA	r0,{r2,r3,r12}
177	BX      LR
178adv_slow:
179	STMFD	r13!,{r10,r14}
180
181	LDR	r14,[r0,#12]		@ r14= head
182	@ stall
183adv_slow_loop:
184	LDR	r1,[r0,#20]		@ r1 = count
185	LDR	r10,[r14,#8]		@ r10= head->length
186	LDR	r14,[r14,#12]		@ r14= head->next
187	@ stall
188	ADD	r1,r1,r10		@ r1 = count += head->length
189	CMP	r14,#0
190	BEQ	adv_end
191	STR	r1,[r0,#20]		@ b->count = count
192	STR	r14,[r0,#12]		@ b->head = head
193	LDMIA	r14,{r3,r10,r12}	@ r3 = buffer
194					@ r10= begin
195					@ r12= length
196	LDR	r3,[r3]			@ r3 = buffer->data
197	ADD	r3,r3,r10		@ r3 = Pointer to start (byte)
198	AND	r10,r3,#3		@ r10= bytes to backtrk to word align
199	MOV	r10,r10,LSL #3		@ r10= bits to backtrk to word align
200	RSB	r10,r10,#32		@ r10= bits left in word
201	ADDS	r10,r10,r2		@ r10= bits left in word after skip
202	ADDLE	r10,r10,#32
203	ADDLE	r3,r3,#4
204	BIC	r3,r3,#3		@ r3 = Pointer to start (word)
205	ADDS	r2,r2,r12,LSL #3	@ r2 = length in bits after advance
206	BLE	adv_slow_loop
207	STMIA	r0,{r2,r3,r10}
208
209	LDMFD	r13!,{r10,PC}
210adv_end:
211	MOV	r2, #0
212	MOV	r12,#0
213	STMIA	r0,{r2,r3,r12}
214
215	LDMFD	r13!,{r10,PC}
216
217oggpack_readinit:
218	@ r0 = oggpack_buffer *b
219	@ r1 = oggreference   *r
220	STR	r1,[r0,#12]		@ b->head = r1
221	STR	r1,[r0,#16]		@ b->tail = r1
222	LDMIA	r1,{r2,r3,r12}		@ r2 = b->head->buffer
223					@ r3 = b->head->begin
224					@ r12= b->head->length
225	LDR	r2,[r2]			@ r2 = b->head->buffer->data
226	MOV	r1,r12,LSL #3		@ r1 = BitsInSegment
227	MOV	r12,#0
228	ADD	r3,r2,r3		@ r3 = r2+b->head->begin
229	BIC	r2,r3,#3		@ r2 = b->headptr (word)
230	AND	r3,r3,#3
231	MOV	r3,r3,LSL #3
232	RSB	r3,r3,#32		@ r3 = BitsInWord
233	STMIA	r0,{r1,r2,r3}
234	STR	r12,[r0,#20]
235	BX      LR
236
237oggpack_read:
238	@ r0 = oggpack_buffer *b
239	@ r1 = int             bits
240	STMFD	r13!,{r10,r11,r14}
241	LDMIA	r0,{r2,r3,r12}
242					@ r2 = bitsLeftInSegment
243					@ r3 = ptr
244					@ r12= bitsLeftInWord
245	SUBS	r2,r2,r1		@ bitsLeftinSegment -= bits
246	BLT	read_slow		@ Not enough bits in this segment for
247					@ this request. Do it slowly.
248	LDR	r10,[r3]		@ r10= ptr[0]
249	RSB	r14,r12,#32		@ r14= 32-bitsLeftInWord
250	SUBS	r12,r12,r1		@ r12= bitsLeftInWord -= bits
251	ADDLE	r3,r3,#4
252	LDRLT	r11,[r3]		@ r11= ptr[1]
253	MOV	r10,r10,LSR r14		@ r10= ptr[0]>>(32-bitsLeftInWord)
254	ADDLE	r12,r12,#32		@ r12= bitsLeftInWord += 32
255	RSB	r14,r14,#32		@ r14= 32-bitsLeftInWord
256	ORRLT	r10,r10,r11,LSL r14	@ r10= Next 32 bits.
257	STMIA	r0,{r2,r3,r12}
258	MOV	r14,#1
259	RSB	r14,r14,r14,LSL r1
260	AND	r0,r10,r14
261	LDMFD	r13!,{r10,r11,PC}
262
263read_slow:
264	STMFD	r13!,{r5,r6}
265	ADDS	r10,r2,r1		@ r10= bitsLeftInSegment + bits (i.e.
266					@ the initial value of bitsLeftInSeg)
267	@ r10 = bitsLeftInSegment (initial)
268	@ r12 = bitsLeftInWord
269	RSB	r14,r12,#32		@ r14= 32-bitsLeftInWord
270	MOV	r5,r10			@ r5 = bitsLeftInSegment (initial)
271	BLT	read_overrun
272	BEQ	read_next_segment	@ r10= r12 = 0, if we branch
273	CMP	r12,r10			@ If bitsLeftInWord < bitsLeftInSeg
274					@ there must be more in the next word
275	LDR	r10,[r3],#4		@ r10= ptr[0]
276	LDRLT	r6,[r3]			@ r6 = ptr[1]
277	MOV	r11,#1
278	MOV	r10,r10,LSR r14		@ r10= first bitsLeftInWord bits
279	ORRLT	r10,r10,r6,LSL r12	@ r10= first bitsLeftInSeg bits+crap
280	RSB	r11,r11,r11,LSL r5	@ r11= mask
281	AND	r10,r10,r11		@ r10= first r5 bits
282	@ Load the next segments data
283read_next_segment:
284	@ At this point, r10 contains the first r5 bits of the result
285	LDR	r11,[r0,#12]		@ r11= head = b->head
286	@ Stall
287read_next_segment_2:
288	@ r11 = head
289	LDR	r6,[r0,#20]		@ r6 = count
290	LDR	r12,[r11,#8]		@ r12= length
291	LDR	r11,[r11,#12]		@ r11= head = head->next
292	@ Stall
293	ADD	r6,r6,r12		@ count += length
294	CMP	r11,#0
295	BEQ	read_out_of_data
296	STR	r11,[r0,#12]
297	STR	r6,[r0,#20]		@ b->count = count
298	LDMIA	r11,{r6,r12,r14}	@ r6 = buffer
299					@ r12= begin
300					@ r14= length
301	LDR	r6,[r6]			@ r6 = buffer->data
302	CMP	r14,#0
303	BEQ	read_next_segment_2
304	ADD	r6,r6,r12		@ r6 = buffer->data+begin
305read_slow_loop:
306	LDRB	r12,[r6],#1		@ r12= *buffer
307	SUBS	r14,r14,#1		@ r14= length
308	@ Stall
309	ORR	r10,r10,r12,LSL r5	@ r10= first r5+8 bits
310	ADD	r5,r5,#8
311	BLE	read_really_slow
312	CMP	r5,r1
313	BLT	read_slow_loop
314read_end:
315	MOV	r12,#1
316	RSB	r12,r12,r12,LSL r1
317
318	@ Store back the new position
319	@ r2 = -number of bits to go from this segment
320	@ r6 = ptr
321	@ r14= bytesLeftInSegment
322	@ r11= New head value
323	LDMIA	r11,{r3,r6,r14}		@ r3 = buffer
324					@ r6 = begin
325					@ r14= length
326	LDR	r3,[r3]			@ r3 = buffer->data
327	ADD	r1,r2,r14,LSL #3	@ r1 = bitsLeftInSegment
328	@ stall
329	ADD	r6,r3,r6		@ r6 = pointer
330	AND	r3,r6,#3		@ r3 = bytes used in first word
331	RSB	r3,r2,r3,LSL #3		@ r3 = bits used in first word
332	BIC	r2,r6,#3		@ r2 = word ptr
333	RSBS	r3,r3,#32		@ r3 = bitsLeftInWord
334	ADDLE	r3,r3,#32
335	ADDLE	r2,r2,#4
336	STMIA	r0,{r1,r2,r3}
337
338	AND	r0,r10,r12
339	LDMFD	r13!,{r5,r6,r10,r11,PC}
340
341
342read_really_slow:
343	CMP	r5,r1
344	BGE	read_end
345	LDR	r14,[r11,#8]		@ r14= length of segment just done
346	@ stall
347	@ stall
348	ADD	r2,r2,r14,LSL #3	@ r2 = -bits to use from next seg
349	B	read_next_segment_2
350
351read_out_of_data:
352	@ Store back the new position
353	@ r2 = -number of bits to go from this segment
354	@ r6 = ptr
355	@ r14= bytesLeftInSegment
356	@ RJW: This may be overkill - we leave the buffer empty, with -1
357	@ bits left in it. We might get away with just storing the
358	@ bitsLeftInSegment as -1.
359	LDR	r11,[r0,#12]		@ r11=head
360
361	LDMIA	r11,{r3,r6,r14}		@ r3 = buffer
362					@ r6 = begin
363					@ r14= length
364	LDR	r3,[r3]			@ r3 = buffer->data
365	ADD	r6,r3,r6		@ r6 = pointer
366	ADD	r6,r6,r14
367	AND	r3,r6,#3		@ r3 = bytes used in first word
368	MOV	r3,r3,LSL #3		@ r3 = bits used in first word
369	BIC	r2,r6,#3		@ r2 = word ptr
370	RSBS	r3,r3,#32		@ r3 = bitsLeftInWord
371	MVN	r1,#0			@ r1 = -1 = bitsLeftInSegment
372	STMIA	r0,{r1,r2,r3}
373	@MVN	r0,#0			; return -1
374	MOV	r0,#0
375	LDMFD	r13!,{r5,r6,r10,r11,PC}
376
377read_overrun:
378	@ We had overrun when we started, so we need to skip -r10 bits.
379	LDR	r11,[r0,#12]		@ r11 = head = b->head
380	@ stall
381	@ stall
382read_overrun_next_segment:
383	LDR	r11,[r11,#12]		@ r11 = head->next
384	@ stall
385	@ stall
386	CMP	r11,#0
387	BEQ	read_out_of_data
388	LDMIA	r11,{r6,r7,r14}		@ r6 = buffer
389					@ r7 = begin
390					@ r14= length
391	LDR	r6,[r6]			@ r6 = buffer->data
392	@ stall
393	@ stall
394	ADD	r6,r6,r7		@ r6 = buffer->data+begin
395	MOV	r14,r14,LSL #3		@ r14= length in bits
396	ADDS	r14,r14,r10		@ r14= length in bits-bits to skip
397	MOVLE	r10,r14
398	BLE	read_overrun_next_segment
399	RSB	r10,r10,#0		@ r10= bits to skip
400	ADD	r6,r10,r10,LSR #3	@ r6 = pointer to data
401	MOV	r10,#0
402	B	read_slow_loop
403
404	@ END
405