1*bda690e4SXin Li@ Tremolo library 2*bda690e4SXin Li@----------------------------------------------------------------------- 3*bda690e4SXin Li@ Copyright (C) 2002-2009, Xiph.org Foundation 4*bda690e4SXin Li@ Copyright (C) 2010, Robin Watts for Pinknoise Productions Ltd 5*bda690e4SXin Li@ All rights reserved. 6*bda690e4SXin Li 7*bda690e4SXin Li@ Redistribution and use in source and binary forms, with or without 8*bda690e4SXin Li@ modification, are permitted provided that the following conditions 9*bda690e4SXin Li@ are met: 10*bda690e4SXin Li 11*bda690e4SXin Li@ * Redistributions of source code must retain the above copyright 12*bda690e4SXin Li@ notice, this list of conditions and the following disclaimer. 13*bda690e4SXin Li@ * Redistributions in binary form must reproduce the above 14*bda690e4SXin Li@ copyright notice, this list of conditions and the following disclaimer 15*bda690e4SXin Li@ in the documentation and/or other materials provided with the 16*bda690e4SXin Li@ distribution. 17*bda690e4SXin Li@ * Neither the names of the Xiph.org Foundation nor Pinknoise 18*bda690e4SXin Li@ Productions Ltd nor the names of its contributors may be used to 19*bda690e4SXin Li@ endorse or promote products derived from this software without 20*bda690e4SXin Li@ specific prior written permission. 21*bda690e4SXin Li@ 22*bda690e4SXin Li@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23*bda690e4SXin Li@ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24*bda690e4SXin Li@ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25*bda690e4SXin Li@ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 26*bda690e4SXin Li@ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27*bda690e4SXin Li@ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 28*bda690e4SXin Li@ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29*bda690e4SXin Li@ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30*bda690e4SXin Li@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31*bda690e4SXin Li@ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 32*bda690e4SXin Li@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33*bda690e4SXin Li@ ---------------------------------------------------------------------- 34*bda690e4SXin Li 35*bda690e4SXin Li .text 36*bda690e4SXin Li 37*bda690e4SXin Li .global oggpack_look 38*bda690e4SXin Li .global oggpack_adv 39*bda690e4SXin Li .global oggpack_readinit 40*bda690e4SXin Li .global oggpack_read 41*bda690e4SXin Li 42*bda690e4SXin Li .type oggpack_look, %function 43*bda690e4SXin Li .type oggpack_adv, %function 44*bda690e4SXin Li .type oggpack_readinit, %function 45*bda690e4SXin Li .type oggpack_read, %function 46*bda690e4SXin Li 47*bda690e4SXin Lioggpack_look: 48*bda690e4SXin Li @ r0 = oggpack_buffer *b 49*bda690e4SXin Li @ r1 = int bits 50*bda690e4SXin Li STMFD r13!,{r10,r11,r14} 51*bda690e4SXin Li LDMIA r0,{r2,r3,r12} 52*bda690e4SXin Li @ r2 = bitsLeftInSegment 53*bda690e4SXin Li @ r3 = ptr 54*bda690e4SXin Li @ r12= bitsLeftInWord 55*bda690e4SXin Li SUBS r2,r2,r1 @ bitsLeftinSegment -= bits 56*bda690e4SXin Li BLT look_slow @ Not enough bits in this segment for 57*bda690e4SXin Li @ this request. Do it slowly. 58*bda690e4SXin Li LDR r10,[r3] @ r10= ptr[0] 59*bda690e4SXin Li RSB r14,r12,#32 @ r14= 32-bitsLeftInWord 60*bda690e4SXin Li SUBS r12,r12,r1 @ r12= bitsLeftInWord -= bits 61*bda690e4SXin Li LDRLT r11,[r3,#4]! @ r11= ptr[1] 62*bda690e4SXin Li MOV r10,r10,LSR r14 @ r10= ptr[0]>>(32-bitsLeftInWord) 63*bda690e4SXin Li ADDLE r12,r12,#32 @ r12= bitsLeftInWord += 32 64*bda690e4SXin Li RSB r14,r14,#32 @ r14= 32-bitsLeftInWord 65*bda690e4SXin Li ORRLT r10,r10,r11,LSL r14 @ r10= Next 32 bits. 66*bda690e4SXin Li MOV r14,#1 67*bda690e4SXin Li RSB r14,r14,r14,LSL r1 68*bda690e4SXin Li AND r0,r10,r14 69*bda690e4SXin Li LDMFD r13!,{r10,r11,PC} 70*bda690e4SXin Li 71*bda690e4SXin Lilook_slow: 72*bda690e4SXin Li STMFD r13!,{r5,r6} 73*bda690e4SXin Li ADDS r10,r2,r1 @ r10= bitsLeftInSegment + bits (i.e. 74*bda690e4SXin Li @ the initial value of bitsLeftInSeg) 75*bda690e4SXin Li @ r10 = bitsLeftInSegment (initial) 76*bda690e4SXin Li @ r12 = bitsLeftInWord 77*bda690e4SXin Li RSB r14,r12,#32 @ r14= 32-bitsLeftInWord 78*bda690e4SXin Li MOV r5,r10 @ r5 = bitsLeftInSegment (initial) 79*bda690e4SXin Li BLT look_overrun 80*bda690e4SXin Li BEQ look_next_segment @ r10= r12 = 0, if we branch 81*bda690e4SXin Li CMP r12,r10 @ If bitsLeftInWord < bitsLeftInSeg 82*bda690e4SXin Li @ there must be more in the next word 83*bda690e4SXin Li LDR r10,[r3],#4 @ r10= ptr[0] 84*bda690e4SXin Li LDRLT r6,[r3] @ r6 = ptr[1] 85*bda690e4SXin Li MOV r11,#1 86*bda690e4SXin Li MOV r10,r10,LSR r14 @ r10= first bitsLeftInWord bits 87*bda690e4SXin Li ORRLT r10,r10,r6,LSL r12 @ r10= first bitsLeftInSeg bits+crap 88*bda690e4SXin Li RSB r11,r11,r11,LSL r5 @ r11= mask 89*bda690e4SXin Li AND r10,r10,r11 @ r10= first r5 bits 90*bda690e4SXin Li @ Load the next segments data 91*bda690e4SXin Lilook_next_segment: 92*bda690e4SXin Li @ At this point, r10 contains the first r5 bits of the result 93*bda690e4SXin Li LDR r11,[r0,#12] @ r11= head = b->head 94*bda690e4SXin Li @ Stall 95*bda690e4SXin Li @ Stall 96*bda690e4SXin Lilook_next_segment_2: 97*bda690e4SXin Li LDR r11,[r11,#12] @ r11= head = head->next 98*bda690e4SXin Li @ Stall 99*bda690e4SXin Li @ Stall 100*bda690e4SXin Li CMP r11,#0 101*bda690e4SXin Li BEQ look_out_of_data 102*bda690e4SXin Li LDMIA r11,{r6,r12,r14} @ r6 = buffer 103*bda690e4SXin Li @ r12= begin 104*bda690e4SXin Li @ r14= length 105*bda690e4SXin Li LDR r6,[r6] @ r6 = buffer->data 106*bda690e4SXin Li CMP r14,#0 107*bda690e4SXin Li BEQ look_next_segment_2 108*bda690e4SXin Li ADD r6,r6,r12 @ r6 = buffer->data+begin 109*bda690e4SXin Lilook_slow_loop: 110*bda690e4SXin Li LDRB r12,[r6],#1 @ r12= *buffer 111*bda690e4SXin Li SUBS r14,r14,#1 @ r14= length 112*bda690e4SXin Li @ Stall 113*bda690e4SXin Li ORR r10,r10,r12,LSL r5 @ r10= first r5+8 bits 114*bda690e4SXin Li ADD r5,r5,#8 115*bda690e4SXin Li BLE look_really_slow 116*bda690e4SXin Li CMP r5,r1 117*bda690e4SXin Li BLT look_slow_loop 118*bda690e4SXin Li MOV r14,#1 119*bda690e4SXin Li RSB r14,r14,r14,LSL r1 120*bda690e4SXin Li AND r0,r10,r14 121*bda690e4SXin Li LDMFD r13!,{r5,r6,r10,r11,PC} 122*bda690e4SXin Li 123*bda690e4SXin Li 124*bda690e4SXin Lilook_really_slow: 125*bda690e4SXin Li CMP r5,r1 126*bda690e4SXin Li BLT look_next_segment_2 127*bda690e4SXin Li MOV r14,#1 128*bda690e4SXin Li RSB r14,r14,r14,LSL r1 129*bda690e4SXin Li AND r0,r10,r14 130*bda690e4SXin Li LDMFD r13!,{r5,r6,r10,r11,PC} 131*bda690e4SXin Li 132*bda690e4SXin Lilook_out_of_data: 133*bda690e4SXin Li @MVN r0,#0 ; return -1 134*bda690e4SXin Li MOV r0,#0 135*bda690e4SXin Li LDMFD r13!,{r5,r6,r10,r11,PC} 136*bda690e4SXin Li 137*bda690e4SXin Lilook_overrun: 138*bda690e4SXin Li @ We had overrun when we started, so we need to skip -r10 bits. 139*bda690e4SXin Li LDR r11,[r0,#12] @ r11 = head = b->head 140*bda690e4SXin Li @ stall 141*bda690e4SXin Li @ stall 142*bda690e4SXin Lilook_overrun_next_segment: 143*bda690e4SXin Li LDR r11,[r11,#12] @ r11 = head->next 144*bda690e4SXin Li @ stall 145*bda690e4SXin Li @ stall 146*bda690e4SXin Li CMP r11,#0 147*bda690e4SXin Li BEQ look_out_of_data 148*bda690e4SXin Li LDMIA r11,{r6,r7,r14} @ r6 = buffer 149*bda690e4SXin Li @ r7 = begin 150*bda690e4SXin Li @ r14= length 151*bda690e4SXin Li LDR r6,[r6] @ r6 = buffer->data 152*bda690e4SXin Li @ stall 153*bda690e4SXin Li @ stall 154*bda690e4SXin Li ADD r6,r6,r7 @ r6 = buffer->data+begin 155*bda690e4SXin Li MOV r14,r14,LSL #3 @ r14= length in bits 156*bda690e4SXin Li ADDS r14,r14,r10 @ r14= length in bits-bits to skip 157*bda690e4SXin Li MOVLE r10,r14 158*bda690e4SXin Li BLE look_overrun_next_segment 159*bda690e4SXin Li RSB r10,r10,#0 @ r10= bits to skip 160*bda690e4SXin Li ADD r6,r10,r10,LSR #3 @ r6 = pointer to data 161*bda690e4SXin Li MOV r10,#0 162*bda690e4SXin Li B look_slow_loop 163*bda690e4SXin Li 164*bda690e4SXin Lioggpack_adv: 165*bda690e4SXin Li @ r0 = oggpack_buffer *b 166*bda690e4SXin Li @ r1 = bits 167*bda690e4SXin Li LDMIA r0,{r2,r3,r12} 168*bda690e4SXin Li @ r2 = bitsLeftInSegment 169*bda690e4SXin Li @ r3 = ptr 170*bda690e4SXin Li @ r12= bitsLeftInWord 171*bda690e4SXin Li SUBS r2,r2,r1 @ Does this run us out of bits in the 172*bda690e4SXin Li BLE adv_slow @ segment? If so, do it slowly 173*bda690e4SXin Li SUBS r12,r12,r1 174*bda690e4SXin Li ADDLE r12,r12,#32 175*bda690e4SXin Li ADDLE r3,r3,#4 176*bda690e4SXin Li STMIA r0,{r2,r3,r12} 177*bda690e4SXin Li BX LR 178*bda690e4SXin Liadv_slow: 179*bda690e4SXin Li STMFD r13!,{r10,r14} 180*bda690e4SXin Li 181*bda690e4SXin Li LDR r14,[r0,#12] @ r14= head 182*bda690e4SXin Li @ stall 183*bda690e4SXin Liadv_slow_loop: 184*bda690e4SXin Li LDR r1,[r0,#20] @ r1 = count 185*bda690e4SXin Li LDR r10,[r14,#8] @ r10= head->length 186*bda690e4SXin Li LDR r14,[r14,#12] @ r14= head->next 187*bda690e4SXin Li @ stall 188*bda690e4SXin Li ADD r1,r1,r10 @ r1 = count += head->length 189*bda690e4SXin Li CMP r14,#0 190*bda690e4SXin Li BEQ adv_end 191*bda690e4SXin Li STR r1,[r0,#20] @ b->count = count 192*bda690e4SXin Li STR r14,[r0,#12] @ b->head = head 193*bda690e4SXin Li LDMIA r14,{r3,r10,r12} @ r3 = buffer 194*bda690e4SXin Li @ r10= begin 195*bda690e4SXin Li @ r12= length 196*bda690e4SXin Li LDR r3,[r3] @ r3 = buffer->data 197*bda690e4SXin Li ADD r3,r3,r10 @ r3 = Pointer to start (byte) 198*bda690e4SXin Li AND r10,r3,#3 @ r10= bytes to backtrk to word align 199*bda690e4SXin Li MOV r10,r10,LSL #3 @ r10= bits to backtrk to word align 200*bda690e4SXin Li RSB r10,r10,#32 @ r10= bits left in word 201*bda690e4SXin Li ADDS r10,r10,r2 @ r10= bits left in word after skip 202*bda690e4SXin Li ADDLE r10,r10,#32 203*bda690e4SXin Li ADDLE r3,r3,#4 204*bda690e4SXin Li BIC r3,r3,#3 @ r3 = Pointer to start (word) 205*bda690e4SXin Li ADDS r2,r2,r12,LSL #3 @ r2 = length in bits after advance 206*bda690e4SXin Li BLE adv_slow_loop 207*bda690e4SXin Li STMIA r0,{r2,r3,r10} 208*bda690e4SXin Li 209*bda690e4SXin Li LDMFD r13!,{r10,PC} 210*bda690e4SXin Liadv_end: 211*bda690e4SXin Li MOV r2, #0 212*bda690e4SXin Li MOV r12,#0 213*bda690e4SXin Li STMIA r0,{r2,r3,r12} 214*bda690e4SXin Li 215*bda690e4SXin Li LDMFD r13!,{r10,PC} 216*bda690e4SXin Li 217*bda690e4SXin Lioggpack_readinit: 218*bda690e4SXin Li @ r0 = oggpack_buffer *b 219*bda690e4SXin Li @ r1 = oggreference *r 220*bda690e4SXin Li STR r1,[r0,#12] @ b->head = r1 221*bda690e4SXin Li STR r1,[r0,#16] @ b->tail = r1 222*bda690e4SXin Li LDMIA r1,{r2,r3,r12} @ r2 = b->head->buffer 223*bda690e4SXin Li @ r3 = b->head->begin 224*bda690e4SXin Li @ r12= b->head->length 225*bda690e4SXin Li LDR r2,[r2] @ r2 = b->head->buffer->data 226*bda690e4SXin Li MOV r1,r12,LSL #3 @ r1 = BitsInSegment 227*bda690e4SXin Li MOV r12,#0 228*bda690e4SXin Li ADD r3,r2,r3 @ r3 = r2+b->head->begin 229*bda690e4SXin Li BIC r2,r3,#3 @ r2 = b->headptr (word) 230*bda690e4SXin Li AND r3,r3,#3 231*bda690e4SXin Li MOV r3,r3,LSL #3 232*bda690e4SXin Li RSB r3,r3,#32 @ r3 = BitsInWord 233*bda690e4SXin Li STMIA r0,{r1,r2,r3} 234*bda690e4SXin Li STR r12,[r0,#20] 235*bda690e4SXin Li BX LR 236*bda690e4SXin Li 237*bda690e4SXin Lioggpack_read: 238*bda690e4SXin Li @ r0 = oggpack_buffer *b 239*bda690e4SXin Li @ r1 = int bits 240*bda690e4SXin Li STMFD r13!,{r10,r11,r14} 241*bda690e4SXin Li LDMIA r0,{r2,r3,r12} 242*bda690e4SXin Li @ r2 = bitsLeftInSegment 243*bda690e4SXin Li @ r3 = ptr 244*bda690e4SXin Li @ r12= bitsLeftInWord 245*bda690e4SXin Li SUBS r2,r2,r1 @ bitsLeftinSegment -= bits 246*bda690e4SXin Li BLT read_slow @ Not enough bits in this segment for 247*bda690e4SXin Li @ this request. Do it slowly. 248*bda690e4SXin Li LDR r10,[r3] @ r10= ptr[0] 249*bda690e4SXin Li RSB r14,r12,#32 @ r14= 32-bitsLeftInWord 250*bda690e4SXin Li SUBS r12,r12,r1 @ r12= bitsLeftInWord -= bits 251*bda690e4SXin Li ADDLE r3,r3,#4 252*bda690e4SXin Li LDRLT r11,[r3] @ r11= ptr[1] 253*bda690e4SXin Li MOV r10,r10,LSR r14 @ r10= ptr[0]>>(32-bitsLeftInWord) 254*bda690e4SXin Li ADDLE r12,r12,#32 @ r12= bitsLeftInWord += 32 255*bda690e4SXin Li RSB r14,r14,#32 @ r14= 32-bitsLeftInWord 256*bda690e4SXin Li ORRLT r10,r10,r11,LSL r14 @ r10= Next 32 bits. 257*bda690e4SXin Li STMIA r0,{r2,r3,r12} 258*bda690e4SXin Li MOV r14,#1 259*bda690e4SXin Li RSB r14,r14,r14,LSL r1 260*bda690e4SXin Li AND r0,r10,r14 261*bda690e4SXin Li LDMFD r13!,{r10,r11,PC} 262*bda690e4SXin Li 263*bda690e4SXin Liread_slow: 264*bda690e4SXin Li STMFD r13!,{r5,r6} 265*bda690e4SXin Li ADDS r10,r2,r1 @ r10= bitsLeftInSegment + bits (i.e. 266*bda690e4SXin Li @ the initial value of bitsLeftInSeg) 267*bda690e4SXin Li @ r10 = bitsLeftInSegment (initial) 268*bda690e4SXin Li @ r12 = bitsLeftInWord 269*bda690e4SXin Li RSB r14,r12,#32 @ r14= 32-bitsLeftInWord 270*bda690e4SXin Li MOV r5,r10 @ r5 = bitsLeftInSegment (initial) 271*bda690e4SXin Li BLT read_overrun 272*bda690e4SXin Li BEQ read_next_segment @ r10= r12 = 0, if we branch 273*bda690e4SXin Li CMP r12,r10 @ If bitsLeftInWord < bitsLeftInSeg 274*bda690e4SXin Li @ there must be more in the next word 275*bda690e4SXin Li LDR r10,[r3],#4 @ r10= ptr[0] 276*bda690e4SXin Li LDRLT r6,[r3] @ r6 = ptr[1] 277*bda690e4SXin Li MOV r11,#1 278*bda690e4SXin Li MOV r10,r10,LSR r14 @ r10= first bitsLeftInWord bits 279*bda690e4SXin Li ORRLT r10,r10,r6,LSL r12 @ r10= first bitsLeftInSeg bits+crap 280*bda690e4SXin Li RSB r11,r11,r11,LSL r5 @ r11= mask 281*bda690e4SXin Li AND r10,r10,r11 @ r10= first r5 bits 282*bda690e4SXin Li @ Load the next segments data 283*bda690e4SXin Liread_next_segment: 284*bda690e4SXin Li @ At this point, r10 contains the first r5 bits of the result 285*bda690e4SXin Li LDR r11,[r0,#12] @ r11= head = b->head 286*bda690e4SXin Li @ Stall 287*bda690e4SXin Liread_next_segment_2: 288*bda690e4SXin Li @ r11 = head 289*bda690e4SXin Li LDR r6,[r0,#20] @ r6 = count 290*bda690e4SXin Li LDR r12,[r11,#8] @ r12= length 291*bda690e4SXin Li LDR r11,[r11,#12] @ r11= head = head->next 292*bda690e4SXin Li @ Stall 293*bda690e4SXin Li ADD r6,r6,r12 @ count += length 294*bda690e4SXin Li CMP r11,#0 295*bda690e4SXin Li BEQ read_out_of_data 296*bda690e4SXin Li STR r11,[r0,#12] 297*bda690e4SXin Li STR r6,[r0,#20] @ b->count = count 298*bda690e4SXin Li LDMIA r11,{r6,r12,r14} @ r6 = buffer 299*bda690e4SXin Li @ r12= begin 300*bda690e4SXin Li @ r14= length 301*bda690e4SXin Li LDR r6,[r6] @ r6 = buffer->data 302*bda690e4SXin Li CMP r14,#0 303*bda690e4SXin Li BEQ read_next_segment_2 304*bda690e4SXin Li ADD r6,r6,r12 @ r6 = buffer->data+begin 305*bda690e4SXin Liread_slow_loop: 306*bda690e4SXin Li LDRB r12,[r6],#1 @ r12= *buffer 307*bda690e4SXin Li SUBS r14,r14,#1 @ r14= length 308*bda690e4SXin Li @ Stall 309*bda690e4SXin Li ORR r10,r10,r12,LSL r5 @ r10= first r5+8 bits 310*bda690e4SXin Li ADD r5,r5,#8 311*bda690e4SXin Li BLE read_really_slow 312*bda690e4SXin Li CMP r5,r1 313*bda690e4SXin Li BLT read_slow_loop 314*bda690e4SXin Liread_end: 315*bda690e4SXin Li MOV r12,#1 316*bda690e4SXin Li RSB r12,r12,r12,LSL r1 317*bda690e4SXin Li 318*bda690e4SXin Li @ Store back the new position 319*bda690e4SXin Li @ r2 = -number of bits to go from this segment 320*bda690e4SXin Li @ r6 = ptr 321*bda690e4SXin Li @ r14= bytesLeftInSegment 322*bda690e4SXin Li @ r11= New head value 323*bda690e4SXin Li LDMIA r11,{r3,r6,r14} @ r3 = buffer 324*bda690e4SXin Li @ r6 = begin 325*bda690e4SXin Li @ r14= length 326*bda690e4SXin Li LDR r3,[r3] @ r3 = buffer->data 327*bda690e4SXin Li ADD r1,r2,r14,LSL #3 @ r1 = bitsLeftInSegment 328*bda690e4SXin Li @ stall 329*bda690e4SXin Li ADD r6,r3,r6 @ r6 = pointer 330*bda690e4SXin Li AND r3,r6,#3 @ r3 = bytes used in first word 331*bda690e4SXin Li RSB r3,r2,r3,LSL #3 @ r3 = bits used in first word 332*bda690e4SXin Li BIC r2,r6,#3 @ r2 = word ptr 333*bda690e4SXin Li RSBS r3,r3,#32 @ r3 = bitsLeftInWord 334*bda690e4SXin Li ADDLE r3,r3,#32 335*bda690e4SXin Li ADDLE r2,r2,#4 336*bda690e4SXin Li STMIA r0,{r1,r2,r3} 337*bda690e4SXin Li 338*bda690e4SXin Li AND r0,r10,r12 339*bda690e4SXin Li LDMFD r13!,{r5,r6,r10,r11,PC} 340*bda690e4SXin Li 341*bda690e4SXin Li 342*bda690e4SXin Liread_really_slow: 343*bda690e4SXin Li CMP r5,r1 344*bda690e4SXin Li BGE read_end 345*bda690e4SXin Li LDR r14,[r11,#8] @ r14= length of segment just done 346*bda690e4SXin Li @ stall 347*bda690e4SXin Li @ stall 348*bda690e4SXin Li ADD r2,r2,r14,LSL #3 @ r2 = -bits to use from next seg 349*bda690e4SXin Li B read_next_segment_2 350*bda690e4SXin Li 351*bda690e4SXin Liread_out_of_data: 352*bda690e4SXin Li @ Store back the new position 353*bda690e4SXin Li @ r2 = -number of bits to go from this segment 354*bda690e4SXin Li @ r6 = ptr 355*bda690e4SXin Li @ r14= bytesLeftInSegment 356*bda690e4SXin Li @ RJW: This may be overkill - we leave the buffer empty, with -1 357*bda690e4SXin Li @ bits left in it. We might get away with just storing the 358*bda690e4SXin Li @ bitsLeftInSegment as -1. 359*bda690e4SXin Li LDR r11,[r0,#12] @ r11=head 360*bda690e4SXin Li 361*bda690e4SXin Li LDMIA r11,{r3,r6,r14} @ r3 = buffer 362*bda690e4SXin Li @ r6 = begin 363*bda690e4SXin Li @ r14= length 364*bda690e4SXin Li LDR r3,[r3] @ r3 = buffer->data 365*bda690e4SXin Li ADD r6,r3,r6 @ r6 = pointer 366*bda690e4SXin Li ADD r6,r6,r14 367*bda690e4SXin Li AND r3,r6,#3 @ r3 = bytes used in first word 368*bda690e4SXin Li MOV r3,r3,LSL #3 @ r3 = bits used in first word 369*bda690e4SXin Li BIC r2,r6,#3 @ r2 = word ptr 370*bda690e4SXin Li RSBS r3,r3,#32 @ r3 = bitsLeftInWord 371*bda690e4SXin Li MVN r1,#0 @ r1 = -1 = bitsLeftInSegment 372*bda690e4SXin Li STMIA r0,{r1,r2,r3} 373*bda690e4SXin Li @MVN r0,#0 ; return -1 374*bda690e4SXin Li MOV r0,#0 375*bda690e4SXin Li LDMFD r13!,{r5,r6,r10,r11,PC} 376*bda690e4SXin Li 377*bda690e4SXin Liread_overrun: 378*bda690e4SXin Li @ We had overrun when we started, so we need to skip -r10 bits. 379*bda690e4SXin Li LDR r11,[r0,#12] @ r11 = head = b->head 380*bda690e4SXin Li @ stall 381*bda690e4SXin Li @ stall 382*bda690e4SXin Liread_overrun_next_segment: 383*bda690e4SXin Li LDR r11,[r11,#12] @ r11 = head->next 384*bda690e4SXin Li @ stall 385*bda690e4SXin Li @ stall 386*bda690e4SXin Li CMP r11,#0 387*bda690e4SXin Li BEQ read_out_of_data 388*bda690e4SXin Li LDMIA r11,{r6,r7,r14} @ r6 = buffer 389*bda690e4SXin Li @ r7 = begin 390*bda690e4SXin Li @ r14= length 391*bda690e4SXin Li LDR r6,[r6] @ r6 = buffer->data 392*bda690e4SXin Li @ stall 393*bda690e4SXin Li @ stall 394*bda690e4SXin Li ADD r6,r6,r7 @ r6 = buffer->data+begin 395*bda690e4SXin Li MOV r14,r14,LSL #3 @ r14= length in bits 396*bda690e4SXin Li ADDS r14,r14,r10 @ r14= length in bits-bits to skip 397*bda690e4SXin Li MOVLE r10,r14 398*bda690e4SXin Li BLE read_overrun_next_segment 399*bda690e4SXin Li RSB r10,r10,#0 @ r10= bits to skip 400*bda690e4SXin Li ADD r6,r10,r10,LSR #3 @ r6 = pointer to data 401*bda690e4SXin Li MOV r10,#0 402*bda690e4SXin Li B read_slow_loop 403*bda690e4SXin Li 404*bda690e4SXin Li @ END 405