Rough merge of master into experimental
[platform/upstream/libvpx.git] / vp8 / encoder / arm / armv5te / boolhuff_armv5te.asm
1 ;
2 ;  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
3 ;
4 ;  Use of this source code is governed by a BSD-style license
5 ;  that can be found in the LICENSE file in the root of the source
6 ;  tree. An additional intellectual property rights grant can be found
7 ;  in the file PATENTS.  All contributing project authors may
8 ;  be found in the AUTHORS file in the root of the source tree.
9 ;
10
11
12     EXPORT |vp8_start_encode|
13     EXPORT |vp8_encode_bool|
14     EXPORT |vp8_stop_encode|
15     EXPORT |vp8_encode_value|
16     IMPORT |vp8_validate_buffer_arm|
17
18     INCLUDE vp8_asm_enc_offsets.asm
19
20     ARM
21     REQUIRE8
22     PRESERVE8
23
24     AREA    |.text|, CODE, READONLY
25
26     ; macro for validating write buffer position
27     ; needs vp8_writer in r0
28     ; start shall not be in r1
29     MACRO
30     VALIDATE_POS $start, $pos
31     push {r0-r3, r12, lr}        ; rest of regs are preserved by subroutine call
32     ldr  r2, [r0, #vp8_writer_buffer_end]
33     ldr  r3, [r0, #vp8_writer_error]
34     mov  r1, $pos
35     mov  r0, $start
36     bl   vp8_validate_buffer_arm
37     pop  {r0-r3, r12, lr}
38     MEND
39
40 ; r0 BOOL_CODER *br
41 ; r1 unsigned char *source
42 ; r2 unsigned char *source_end
43 |vp8_start_encode| PROC
44     str     r2,  [r0, #vp8_writer_buffer_end]
45     mov     r12, #0
46     mov     r3,  #255
47     mvn     r2,  #23
48     str     r12, [r0, #vp8_writer_lowvalue]
49     str     r3,  [r0, #vp8_writer_range]
50     str     r2,  [r0, #vp8_writer_count]
51     str     r12, [r0, #vp8_writer_pos]
52     str     r1,  [r0, #vp8_writer_buffer]
53     bx      lr
54     ENDP
55
56 ; r0 BOOL_CODER *br
57 ; r1 int bit
58 ; r2 int probability
59 |vp8_encode_bool| PROC
60     push    {r4-r10, lr}
61
62     mov     r4, r2
63
64     ldr     r2, [r0, #vp8_writer_lowvalue]
65     ldr     r5, [r0, #vp8_writer_range]
66     ldr     r3, [r0, #vp8_writer_count]
67
68     sub     r7, r5, #1                  ; range-1
69
70     cmp     r1, #0
71     mul     r6, r4, r7                  ; ((range-1) * probability)
72
73     mov     r7, #1
74     add     r4, r7, r6, lsr #8          ; 1 + (((range-1) * probability) >> 8)
75
76     addne   r2, r2, r4                  ; if  (bit) lowvalue += split
77     subne   r4, r5, r4                  ; if  (bit) range = range-split
78
79     ; Counting the leading zeros is used to normalize range.
80     clz     r6, r4
81     sub     r6, r6, #24                 ; shift
82
83     ; Flag is set on the sum of count.  This flag is used later
84     ; to determine if count >= 0
85     adds    r3, r3, r6                  ; count += shift
86     lsl     r5, r4, r6                  ; range <<= shift
87     bmi     token_count_lt_zero         ; if(count >= 0)
88
89     sub     r6, r6, r3                  ; offset = shift - count
90     sub     r4, r6, #1                  ; offset-1
91     lsls    r4, r2, r4                  ; if((lowvalue<<(offset-1)) & 0x80000000 )
92     bpl     token_high_bit_not_set
93
94     ldr     r4, [r0, #vp8_writer_pos]   ; x
95     sub     r4, r4, #1                  ; x = w->pos-1
96     b       token_zero_while_start
97 token_zero_while_loop
98     mov     r9, #0
99     strb    r9, [r7, r4]                ; w->buffer[x] =(unsigned char)0
100     sub     r4, r4, #1                  ; x--
101 token_zero_while_start
102     cmp     r4, #0
103     ldrge   r7, [r0, #vp8_writer_buffer]
104     ldrb    r1, [r7, r4]
105     cmpge   r1, #0xff
106     beq     token_zero_while_loop
107
108     ldr     r7, [r0, #vp8_writer_buffer]
109     ldrb    r9, [r7, r4]                ; w->buffer[x]
110     add     r9, r9, #1
111     strb    r9, [r7, r4]                ; w->buffer[x] + 1
112 token_high_bit_not_set
113     rsb     r4, r6, #24                 ; 24-offset
114     ldr     r9, [r0, #vp8_writer_buffer]
115     lsr     r7, r2, r4                  ; lowvalue >> (24-offset)
116     ldr     r4, [r0, #vp8_writer_pos]   ; w->pos
117     lsl     r2, r2, r6                  ; lowvalue <<= offset
118     mov     r6, r3                      ; shift = count
119     add     r1, r4, #1                  ; w->pos++
120     bic     r2, r2, #0xff000000         ; lowvalue &= 0xffffff
121     str     r1, [r0, #vp8_writer_pos]
122     sub     r3, r3, #8                  ; count -= 8
123
124     VALIDATE_POS r9, r1                 ; validate_buffer at pos
125
126     strb    r7, [r9, r4]                ; w->buffer[w->pos++]
127
128 token_count_lt_zero
129     lsl     r2, r2, r6                  ; lowvalue <<= shift
130
131     str     r2, [r0, #vp8_writer_lowvalue]
132     str     r5, [r0, #vp8_writer_range]
133     str     r3, [r0, #vp8_writer_count]
134     pop     {r4-r10, pc}
135     ENDP
136
137 ; r0 BOOL_CODER *br
138 |vp8_stop_encode| PROC
139     push    {r4-r10, lr}
140
141     ldr     r2, [r0, #vp8_writer_lowvalue]
142     ldr     r5, [r0, #vp8_writer_range]
143     ldr     r3, [r0, #vp8_writer_count]
144
145     mov     r10, #32
146
147 stop_encode_loop
148     sub     r7, r5, #1                  ; range-1
149
150     mov     r4, r7, lsl #7              ; ((range-1) * 128)
151
152     mov     r7, #1
153     add     r4, r7, r4, lsr #8          ; 1 + (((range-1) * 128) >> 8)
154
155     ; Counting the leading zeros is used to normalize range.
156     clz     r6, r4
157     sub     r6, r6, #24                 ; shift
158
159     ; Flag is set on the sum of count.  This flag is used later
160     ; to determine if count >= 0
161     adds    r3, r3, r6                  ; count += shift
162     lsl     r5, r4, r6                  ; range <<= shift
163     bmi     token_count_lt_zero_se      ; if(count >= 0)
164
165     sub     r6, r6, r3                  ; offset = shift - count
166     sub     r4, r6, #1                  ; offset-1
167     lsls    r4, r2, r4                  ; if((lowvalue<<(offset-1)) & 0x80000000 )
168     bpl     token_high_bit_not_set_se
169
170     ldr     r4, [r0, #vp8_writer_pos]   ; x
171     sub     r4, r4, #1                  ; x = w->pos-1
172     b       token_zero_while_start_se
173 token_zero_while_loop_se
174     mov     r9, #0
175     strb    r9, [r7, r4]                ; w->buffer[x] =(unsigned char)0
176     sub     r4, r4, #1                  ; x--
177 token_zero_while_start_se
178     cmp     r4, #0
179     ldrge   r7, [r0, #vp8_writer_buffer]
180     ldrb    r1, [r7, r4]
181     cmpge   r1, #0xff
182     beq     token_zero_while_loop_se
183
184     ldr     r7, [r0, #vp8_writer_buffer]
185     ldrb    r9, [r7, r4]                ; w->buffer[x]
186     add     r9, r9, #1
187     strb    r9, [r7, r4]                ; w->buffer[x] + 1
188 token_high_bit_not_set_se
189     rsb     r4, r6, #24                 ; 24-offset
190     ldr     r9, [r0, #vp8_writer_buffer]
191     lsr     r7, r2, r4                  ; lowvalue >> (24-offset)
192     ldr     r4, [r0, #vp8_writer_pos]   ; w->pos
193     lsl     r2, r2, r6                  ; lowvalue <<= offset
194     mov     r6, r3                      ; shift = count
195     add     r1, r4, #1                  ; w->pos++
196     bic     r2, r2, #0xff000000         ; lowvalue &= 0xffffff
197     str     r1, [r0, #vp8_writer_pos]
198     sub     r3, r3, #8                  ; count -= 8
199
200     VALIDATE_POS r9, r1                 ; validate_buffer at pos
201
202     strb    r7, [r9, r4]                ; w->buffer[w->pos++]
203
204 token_count_lt_zero_se
205     lsl     r2, r2, r6                  ; lowvalue <<= shift
206
207     subs    r10, r10, #1
208     bne     stop_encode_loop
209
210     str     r2, [r0, #vp8_writer_lowvalue]
211     str     r5, [r0, #vp8_writer_range]
212     str     r3, [r0, #vp8_writer_count]
213     pop     {r4-r10, pc}
214
215     ENDP
216
217 ; r0 BOOL_CODER *br
218 ; r1 int data
219 ; r2 int bits
220 |vp8_encode_value| PROC
221     push    {r4-r12, lr}
222
223     mov     r10, r2
224
225     ldr     r2, [r0, #vp8_writer_lowvalue]
226     ldr     r5, [r0, #vp8_writer_range]
227     ldr     r3, [r0, #vp8_writer_count]
228
229     rsb     r4, r10, #32                 ; 32-n
230
231     ; v is kept in r1 during the token pack loop
232     lsl     r1, r1, r4                  ; r1 = v << 32 - n
233
234 encode_value_loop
235     sub     r7, r5, #1                  ; range-1
236
237     ; Decisions are made based on the bit value shifted
238     ; off of v, so set a flag here based on this.
239     ; This value is refered to as "bb"
240     lsls    r1, r1, #1                  ; bit = v >> n
241     mov     r4, r7, lsl #7              ; ((range-1) * 128)
242
243     mov     r7, #1
244     add     r4, r7, r4, lsr #8          ; 1 + (((range-1) * 128) >> 8)
245
246     addcs   r2, r2, r4                  ; if  (bit) lowvalue += split
247     subcs   r4, r5, r4                  ; if  (bit) range = range-split
248
249     ; Counting the leading zeros is used to normalize range.
250     clz     r6, r4
251     sub     r6, r6, #24                 ; shift
252
253     ; Flag is set on the sum of count.  This flag is used later
254     ; to determine if count >= 0
255     adds    r3, r3, r6                  ; count += shift
256     lsl     r5, r4, r6                  ; range <<= shift
257     bmi     token_count_lt_zero_ev      ; if(count >= 0)
258
259     sub     r6, r6, r3                  ; offset = shift - count
260     sub     r4, r6, #1                  ; offset-1
261     lsls    r4, r2, r4                  ; if((lowvalue<<(offset-1)) & 0x80000000 )
262     bpl     token_high_bit_not_set_ev
263
264     ldr     r4, [r0, #vp8_writer_pos]   ; x
265     sub     r4, r4, #1                  ; x = w->pos-1
266     b       token_zero_while_start_ev
267 token_zero_while_loop_ev
268     mov     r9, #0
269     strb    r9, [r7, r4]                ; w->buffer[x] =(unsigned char)0
270     sub     r4, r4, #1                  ; x--
271 token_zero_while_start_ev
272     cmp     r4, #0
273     ldrge   r7, [r0, #vp8_writer_buffer]
274     ldrb    r11, [r7, r4]
275     cmpge   r11, #0xff
276     beq     token_zero_while_loop_ev
277
278     ldr     r7, [r0, #vp8_writer_buffer]
279     ldrb    r9, [r7, r4]                ; w->buffer[x]
280     add     r9, r9, #1
281     strb    r9, [r7, r4]                ; w->buffer[x] + 1
282 token_high_bit_not_set_ev
283     rsb     r4, r6, #24                 ; 24-offset
284     ldr     r9, [r0, #vp8_writer_buffer]
285     lsr     r7, r2, r4                  ; lowvalue >> (24-offset)
286     ldr     r4, [r0, #vp8_writer_pos]   ; w->pos
287     lsl     r2, r2, r6                  ; lowvalue <<= offset
288     mov     r6, r3                      ; shift = count
289     add     r11, r4, #1                 ; w->pos++
290     bic     r2, r2, #0xff000000         ; lowvalue &= 0xffffff
291     str     r11, [r0, #vp8_writer_pos]
292     sub     r3, r3, #8                  ; count -= 8
293
294     VALIDATE_POS r9, r11                ; validate_buffer at pos
295
296     strb    r7, [r9, r4]                ; w->buffer[w->pos++]
297
298 token_count_lt_zero_ev
299     lsl     r2, r2, r6                  ; lowvalue <<= shift
300
301     subs    r10, r10, #1
302     bne     encode_value_loop
303
304     str     r2, [r0, #vp8_writer_lowvalue]
305     str     r5, [r0, #vp8_writer_range]
306     str     r3, [r0, #vp8_writer_count]
307     pop     {r4-r12, pc}
308     ENDP
309
310     END