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
97token_zero_while_loop
98    mov     r9, #0
99    strb    r9, [r7, r4]                ; w->buffer[x] =(unsigned char)0
100    sub     r4, r4, #1                  ; x--
101token_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
112token_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
128token_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
147stop_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
173token_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--
177token_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
188token_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
204token_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
234encode_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
267token_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--
271token_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
282token_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
298token_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
311