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