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