123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399 |
- @ Tremolo library
- @-----------------------------------------------------------------------
- @ Copyright (C) 2002-2009, Xiph.org Foundation
- @ Copyright (C) 2010, Robin Watts for Pinknoise Productions Ltd
- @ All rights reserved.
- @ Redistribution and use in source and binary forms, with or without
- @ modification, are permitted provided that the following conditions
- @ are met:
- @ * Redistributions of source code must retain the above copyright
- @ notice, this list of conditions and the following disclaimer.
- @ * Redistributions in binary form must reproduce the above
- @ copyright notice, this list of conditions and the following disclaimer
- @ in the documentation and/or other materials provided with the
- @ distribution.
- @ * Neither the names of the Xiph.org Foundation nor Pinknoise
- @ Productions Ltd nor the names of its contributors may be used to
- @ endorse or promote products derived from this software without
- @ specific prior written permission.
- @
- @ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- @ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- @ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- @ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- @ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- @ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- @ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- @ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- @ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- @ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- @ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- @ ----------------------------------------------------------------------
- .text
- .global oggpack_look
- .global oggpack_adv
- .global oggpack_readinit
- .global oggpack_read
- oggpack_look:
- @ r0 = oggpack_buffer *b
- @ r1 = int bits
- STMFD r13!,{r10,r11,r14}
- LDMIA r0,{r2,r3,r12}
- @ r2 = bitsLeftInSegment
- @ r3 = ptr
- @ r12= bitsLeftInWord
- SUBS r2,r2,r1 @ bitsLeftinSegment -= bits
- BLT look_slow @ Not enough bits in this segment for
- @ this request. Do it slowly.
- LDR r10,[r3] @ r10= ptr[0]
- RSB r14,r12,#32 @ r14= 32-bitsLeftInWord
- SUBS r12,r12,r1 @ r12= bitsLeftInWord -= bits
- LDRLT r11,[r3,#4]! @ r11= ptr[1]
- MOV r10,r10,LSR r14 @ r10= ptr[0]>>(32-bitsLeftInWord)
- ADDLE r12,r12,#32 @ r12= bitsLeftInWord += 32
- RSB r14,r14,#32 @ r14= 32-bitsLeftInWord
- ORRLT r10,r10,r11,LSL r14 @ r10= Next 32 bits.
- MOV r14,#1
- RSB r14,r14,r14,LSL r1
- AND r0,r10,r14
- LDMFD r13!,{r10,r11,PC}
- look_slow:
- STMFD r13!,{r5,r6}
- ADDS r10,r2,r1 @ r10= bitsLeftInSegment + bits (i.e.
- @ the initial value of bitsLeftInSeg)
- @ r10 = bitsLeftInSegment (initial)
- @ r12 = bitsLeftInWord
- RSB r14,r12,#32 @ r14= 32-bitsLeftInWord
- MOV r5,r10 @ r5 = bitsLeftInSegment (initial)
- BLT look_overrun
- BEQ look_next_segment @ r10= r12 = 0, if we branch
- CMP r12,r10 @ If bitsLeftInWord < bitsLeftInSeg
- @ there must be more in the next word
- LDR r10,[r3],#4 @ r10= ptr[0]
- LDRLT r6,[r3] @ r6 = ptr[1]
- MOV r11,#1
- MOV r10,r10,LSR r14 @ r10= first bitsLeftInWord bits
- ORRLT r10,r10,r6,LSL r12 @ r10= first bitsLeftInSeg bits+crap
- RSB r11,r11,r11,LSL r5 @ r11= mask
- AND r10,r10,r11 @ r10= first r5 bits
- @ Load the next segments data
- look_next_segment:
- @ At this point, r10 contains the first r5 bits of the result
- LDR r11,[r0,#12] @ r11= head = b->head
- @ Stall
- @ Stall
- look_next_segment_2:
- LDR r11,[r11,#12] @ r11= head = head->next
- @ Stall
- @ Stall
- CMP r11,#0
- BEQ look_out_of_data
- LDMIA r11,{r6,r12,r14} @ r6 = buffer
- @ r12= begin
- @ r14= length
- LDR r6,[r6] @ r6 = buffer->data
- CMP r14,#0
- BEQ look_next_segment_2
- ADD r6,r6,r12 @ r6 = buffer->data+begin
- look_slow_loop:
- LDRB r12,[r6],#1 @ r12= *buffer
- SUBS r14,r14,#1 @ r14= length
- @ Stall
- ORR r10,r10,r12,LSL r5 @ r10= first r5+8 bits
- ADD r5,r5,#8
- BLE look_really_slow
- CMP r5,r1
- BLT look_slow_loop
- MOV r14,#1
- RSB r14,r14,r14,LSL r1
- AND r0,r10,r14
- LDMFD r13!,{r5,r6,r10,r11,PC}
- look_really_slow:
- CMP r5,r1
- BLT look_next_segment_2
- MOV r14,#1
- RSB r14,r14,r14,LSL r1
- AND r0,r10,r14
- LDMFD r13!,{r5,r6,r10,r11,PC}
- look_out_of_data:
- @MVN r0,#0 ; return -1
- MOV r0,#0
- LDMFD r13!,{r5,r6,r10,r11,PC}
- look_overrun:
- @ We had overrun when we started, so we need to skip -r10 bits.
- LDR r11,[r0,#12] @ r11 = head = b->head
- @ stall
- @ stall
- look_overrun_next_segment:
- LDR r11,[r11,#12] @ r11 = head->next
- @ stall
- @ stall
- CMP r11,#0
- BEQ look_out_of_data
- LDMIA r11,{r6,r7,r14} @ r6 = buffer
- @ r7 = begin
- @ r14= length
- LDR r6,[r6] @ r6 = buffer->data
- @ stall
- @ stall
- ADD r6,r6,r7 @ r6 = buffer->data+begin
- MOV r14,r14,LSL #3 @ r14= length in bits
- ADDS r14,r14,r10 @ r14= length in bits-bits to skip
- MOVLE r10,r14
- BLE look_overrun_next_segment
- RSB r10,r10,#0 @ r10= bits to skip
- ADD r6,r10,r10,LSR #3 @ r6 = pointer to data
- MOV r10,#0
- B look_slow_loop
- oggpack_adv:
- @ r0 = oggpack_buffer *b
- @ r1 = bits
- LDMIA r0,{r2,r3,r12}
- @ r2 = bitsLeftInSegment
- @ r3 = ptr
- @ r12= bitsLeftInWord
- SUBS r2,r2,r1 @ Does this run us out of bits in the
- BLE adv_slow @ segment? If so, do it slowly
- SUBS r12,r12,r1
- ADDLE r12,r12,#32
- ADDLE r3,r3,#4
- STMIA r0,{r2,r3,r12}
- BX LR
- adv_slow:
- STMFD r13!,{r10,r14}
- LDR r14,[r0,#12] @ r14= head
- @ stall
- adv_slow_loop:
- LDR r1,[r0,#20] @ r1 = count
- LDR r10,[r14,#8] @ r10= head->length
- LDR r14,[r14,#12] @ r14= head->next
- @ stall
- ADD r1,r1,r10 @ r1 = count += head->length
- CMP r14,#0
- BEQ adv_end
- STR r1,[r0,#20] @ b->count = count
- STR r14,[r0,#12] @ b->head = head
- LDMIA r14,{r3,r10,r12} @ r3 = buffer
- @ r10= begin
- @ r12= length
- LDR r3,[r3] @ r3 = buffer->data
- ADD r3,r3,r10 @ r3 = Pointer to start (byte)
- AND r10,r3,#3 @ r10= bytes to backtrk to word align
- MOV r10,r10,LSL #3 @ r10= bits to backtrk to word align
- RSB r10,r10,#32 @ r10= bits left in word
- ADDS r10,r10,r2 @ r10= bits left in word after skip
- ADDLE r10,r10,#32
- ADDLE r3,r3,#4
- BIC r3,r3,#3 @ r3 = Pointer to start (word)
- ADDS r2,r2,r12,LSL #3 @ r2 = length in bits after advance
- BLE adv_slow_loop
- STMIA r0,{r2,r3,r10}
- LDMFD r13!,{r10,PC}
- adv_end:
- MOV r2, #0
- MOV r12,#0
- STMIA r0,{r2,r3,r12}
- LDMFD r13!,{r10,PC}
- oggpack_readinit:
- @ r0 = oggpack_buffer *b
- @ r1 = oggreference *r
- STR r1,[r0,#12] @ b->head = r1
- STR r1,[r0,#16] @ b->tail = r1
- LDMIA r1,{r2,r3,r12} @ r2 = b->head->buffer
- @ r3 = b->head->begin
- @ r12= b->head->length
- LDR r2,[r2] @ r2 = b->head->buffer->data
- MOV r1,r12,LSL #3 @ r1 = BitsInSegment
- MOV r12,#0
- ADD r3,r2,r3 @ r3 = r2+b->head->begin
- BIC r2,r3,#3 @ r2 = b->headptr (word)
- AND r3,r3,#3
- MOV r3,r3,LSL #3
- RSB r3,r3,#32 @ r3 = BitsInWord
- STMIA r0,{r1,r2,r3}
- STR r12,[r0,#20]
- BX LR
- oggpack_read:
- @ r0 = oggpack_buffer *b
- @ r1 = int bits
- STMFD r13!,{r10,r11,r14}
- LDMIA r0,{r2,r3,r12}
- @ r2 = bitsLeftInSegment
- @ r3 = ptr
- @ r12= bitsLeftInWord
- SUBS r2,r2,r1 @ bitsLeftinSegment -= bits
- BLT read_slow @ Not enough bits in this segment for
- @ this request. Do it slowly.
- LDR r10,[r3] @ r10= ptr[0]
- RSB r14,r12,#32 @ r14= 32-bitsLeftInWord
- SUBS r12,r12,r1 @ r12= bitsLeftInWord -= bits
- ADDLE r3,r3,#4
- LDRLT r11,[r3] @ r11= ptr[1]
- MOV r10,r10,LSR r14 @ r10= ptr[0]>>(32-bitsLeftInWord)
- ADDLE r12,r12,#32 @ r12= bitsLeftInWord += 32
- RSB r14,r14,#32 @ r14= 32-bitsLeftInWord
- ORRLT r10,r10,r11,LSL r14 @ r10= Next 32 bits.
- STMIA r0,{r2,r3,r12}
- MOV r14,#1
- RSB r14,r14,r14,LSL r1
- AND r0,r10,r14
- LDMFD r13!,{r10,r11,PC}
- read_slow:
- STMFD r13!,{r5,r6}
- ADDS r10,r2,r1 @ r10= bitsLeftInSegment + bits (i.e.
- @ the initial value of bitsLeftInSeg)
- @ r10 = bitsLeftInSegment (initial)
- @ r12 = bitsLeftInWord
- RSB r14,r12,#32 @ r14= 32-bitsLeftInWord
- MOV r5,r10 @ r5 = bitsLeftInSegment (initial)
- BLT read_overrun
- BEQ read_next_segment @ r10= r12 = 0, if we branch
- CMP r12,r10 @ If bitsLeftInWord < bitsLeftInSeg
- @ there must be more in the next word
- LDR r10,[r3],#4 @ r10= ptr[0]
- LDRLT r6,[r3] @ r6 = ptr[1]
- MOV r11,#1
- MOV r10,r10,LSR r14 @ r10= first bitsLeftInWord bits
- ORRLT r10,r10,r6,LSL r12 @ r10= first bitsLeftInSeg bits+crap
- RSB r11,r11,r11,LSL r5 @ r11= mask
- AND r10,r10,r11 @ r10= first r5 bits
- @ Load the next segments data
- read_next_segment:
- @ At this point, r10 contains the first r5 bits of the result
- LDR r11,[r0,#12] @ r11= head = b->head
- @ Stall
- read_next_segment_2:
- @ r11 = head
- LDR r6,[r0,#20] @ r6 = count
- LDR r12,[r11,#8] @ r12= length
- LDR r11,[r11,#12] @ r11= head = head->next
- @ Stall
- ADD r6,r6,r12 @ count += length
- CMP r11,#0
- BEQ read_out_of_data
- STR r11,[r0,#12]
- STR r6,[r0,#20] @ b->count = count
- LDMIA r11,{r6,r12,r14} @ r6 = buffer
- @ r12= begin
- @ r14= length
- LDR r6,[r6] @ r6 = buffer->data
- CMP r14,#0
- BEQ read_next_segment_2
- ADD r6,r6,r12 @ r6 = buffer->data+begin
- read_slow_loop:
- LDRB r12,[r6],#1 @ r12= *buffer
- SUBS r14,r14,#1 @ r14= length
- @ Stall
- ORR r10,r10,r12,LSL r5 @ r10= first r5+8 bits
- ADD r5,r5,#8
- BLE read_really_slow
- CMP r5,r1
- BLT read_slow_loop
- read_end:
- MOV r12,#1
- RSB r12,r12,r12,LSL r1
- @ Store back the new position
- @ r2 = -number of bits to go from this segment
- @ r6 = ptr
- @ r14= bytesLeftInSegment
- @ r11= New head value
- LDMIA r11,{r3,r6,r14} @ r3 = buffer
- @ r6 = begin
- @ r14= length
- LDR r3,[r3] @ r3 = buffer->data
- ADD r1,r2,r14,LSL #3 @ r1 = bitsLeftInSegment
- @ stall
- ADD r6,r3,r6 @ r6 = pointer
- AND r3,r6,#3 @ r3 = bytes used in first word
- RSB r3,r2,r3,LSL #3 @ r3 = bits used in first word
- BIC r2,r6,#3 @ r2 = word ptr
- RSBS r3,r3,#32 @ r3 = bitsLeftInWord
- ADDLE r3,r3,#32
- ADDLE r2,r2,#4
- STMIA r0,{r1,r2,r3}
- AND r0,r10,r12
- LDMFD r13!,{r5,r6,r10,r11,PC}
- read_really_slow:
- CMP r5,r1
- BGE read_end
- LDR r14,[r11,#8] @ r14= length of segment just done
- @ stall
- @ stall
- ADD r2,r2,r14,LSL #3 @ r2 = -bits to use from next seg
- B read_next_segment_2
- read_out_of_data:
- @ Store back the new position
- @ r2 = -number of bits to go from this segment
- @ r6 = ptr
- @ r14= bytesLeftInSegment
- @ RJW: This may be overkill - we leave the buffer empty, with -1
- @ bits left in it. We might get away with just storing the
- @ bitsLeftInSegment as -1.
- LDR r11,[r0,#12] @ r11=head
- LDMIA r11,{r3,r6,r14} @ r3 = buffer
- @ r6 = begin
- @ r14= length
- LDR r3,[r3] @ r3 = buffer->data
- ADD r6,r3,r6 @ r6 = pointer
- ADD r6,r6,r14
- AND r3,r6,#3 @ r3 = bytes used in first word
- MOV r3,r3,LSL #3 @ r3 = bits used in first word
- BIC r2,r6,#3 @ r2 = word ptr
- RSBS r3,r3,#32 @ r3 = bitsLeftInWord
- MVN r1,#0 @ r1 = -1 = bitsLeftInSegment
- STMIA r0,{r1,r2,r3}
- @MVN r0,#0 ; return -1
- MOV r0,#0
- LDMFD r13!,{r5,r6,r10,r11,PC}
- read_overrun:
- @ We had overrun when we started, so we need to skip -r10 bits.
- LDR r11,[r0,#12] @ r11 = head = b->head
- @ stall
- @ stall
- read_overrun_next_segment:
- LDR r11,[r11,#12] @ r11 = head->next
- @ stall
- @ stall
- CMP r11,#0
- BEQ read_out_of_data
- LDMIA r11,{r6,r7,r14} @ r6 = buffer
- @ r7 = begin
- @ r14= length
- LDR r6,[r6] @ r6 = buffer->data
- @ stall
- @ stall
- ADD r6,r6,r7 @ r6 = buffer->data+begin
- MOV r14,r14,LSL #3 @ r14= length in bits
- ADDS r14,r14,r10 @ r14= length in bits-bits to skip
- MOVLE r10,r14
- BLE read_overrun_next_segment
- RSB r10,r10,#0 @ r10= bits to skip
- ADD r6,r10,r10,LSR #3 @ r6 = pointer to data
- MOV r10,#0
- B read_slow_loop
- @ END
|