Home | History | Annotate | Download | only in Tremolo
      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 oggpack_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 
     66 look_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
     86 look_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
     91 look_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
    104 look_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 
    119 look_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 
    127 look_out_of_data:
    128 	@MVN	r0,#0			; return -1
    129 	MOV	r0,#0
    130 	LDMFD	r13!,{r5,r6,r10,r11,PC}
    131 
    132 look_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
    137 look_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 
    159 oggpack_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}
    172 	BX      LR
    173 adv_slow:
    174 	STMFD	r13!,{r10,r14}
    175 
    176 	LDR	r14,[r0,#12]		@ r14= head
    177 	@ stall
    178 adv_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}
    205 adv_end:
    206 	MOV	r2, #0
    207 	MOV	r12,#0
    208 	STMIA	r0,{r2,r3,r12}
    209 
    210 	LDMFD	r13!,{r10,PC}
    211 
    212 oggpack_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]
    230 	BX      LR
    231 
    232 oggpack_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 
    258 read_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
    278 read_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
    282 read_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
    300 read_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
    309 read_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 
    337 read_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 
    346 read_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 
    372 read_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
    377 read_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
    400