97259b460c
API was not returning correct partition sizes on arm targets. The armv5 token packing functions were not storing the information to the partition size table. As a fix, have one boolcoder instance allocated for each partition so that partition sizes are internally available after all partitions were encoded. This will also allow more flexibility in producing several partitions in parallel. Use buffer validation (overflow check) in all ARM bitpacking functions. Change-Id: I31c8a11d8a7613676f0ff50928cb2a2ab14fd169
312 lines
10 KiB
NASM
312 lines
10 KiB
NASM
;
|
|
; Copyright (c) 2010 The WebM project authors. All Rights Reserved.
|
|
;
|
|
; Use of this source code is governed by a BSD-style license
|
|
; that can be found in the LICENSE file in the root of the source
|
|
; tree. An additional intellectual property rights grant can be found
|
|
; in the file PATENTS. All contributing project authors may
|
|
; be found in the AUTHORS file in the root of the source tree.
|
|
;
|
|
|
|
|
|
EXPORT |vp8_start_encode|
|
|
EXPORT |vp8_encode_bool|
|
|
EXPORT |vp8_stop_encode|
|
|
EXPORT |vp8_encode_value|
|
|
IMPORT |vp8_validate_buffer_arm|
|
|
|
|
INCLUDE asm_enc_offsets.asm
|
|
|
|
ARM
|
|
REQUIRE8
|
|
PRESERVE8
|
|
|
|
AREA |.text|, CODE, READONLY
|
|
|
|
; macro for validating write buffer position
|
|
; needs vp8_writer in r0
|
|
; start shall not be in r1
|
|
MACRO
|
|
VALIDATE_POS $start, $pos
|
|
push {r0-r3, r12, lr} ; rest of regs are preserved by subroutine call
|
|
ldr r2, [r0, #vp8_writer_buffer_end]
|
|
ldr r3, [r0, #vp8_writer_error]
|
|
mov r1, $pos
|
|
mov r0, $start
|
|
bl vp8_validate_buffer_arm
|
|
pop {r0-r3, r12, lr}
|
|
MEND
|
|
|
|
; r0 BOOL_CODER *br
|
|
; r1 unsigned char *source
|
|
; r2 unsigned char *source_end
|
|
|vp8_start_encode| PROC
|
|
str r2, [r0, #vp8_writer_buffer_end]
|
|
mov r12, #0
|
|
mov r3, #255
|
|
mvn r2, #23
|
|
str r12, [r0, #vp8_writer_lowvalue]
|
|
str r3, [r0, #vp8_writer_range]
|
|
str r12, [r0, #vp8_writer_value]
|
|
str r2, [r0, #vp8_writer_count]
|
|
str r12, [r0, #vp8_writer_pos]
|
|
str r1, [r0, #vp8_writer_buffer]
|
|
bx lr
|
|
ENDP
|
|
|
|
; r0 BOOL_CODER *br
|
|
; r1 int bit
|
|
; r2 int probability
|
|
|vp8_encode_bool| PROC
|
|
push {r4-r10, lr}
|
|
|
|
mov r4, r2
|
|
|
|
ldr r2, [r0, #vp8_writer_lowvalue]
|
|
ldr r5, [r0, #vp8_writer_range]
|
|
ldr r3, [r0, #vp8_writer_count]
|
|
|
|
sub r7, r5, #1 ; range-1
|
|
|
|
cmp r1, #0
|
|
mul r6, r4, r7 ; ((range-1) * probability)
|
|
|
|
mov r7, #1
|
|
add r4, r7, r6, lsr #8 ; 1 + (((range-1) * probability) >> 8)
|
|
|
|
addne r2, r2, r4 ; if (bit) lowvalue += split
|
|
subne r4, r5, r4 ; if (bit) range = range-split
|
|
|
|
; Counting the leading zeros is used to normalize range.
|
|
clz r6, r4
|
|
sub r6, r6, #24 ; shift
|
|
|
|
; Flag is set on the sum of count. This flag is used later
|
|
; to determine if count >= 0
|
|
adds r3, r3, r6 ; count += shift
|
|
lsl r5, r4, r6 ; range <<= shift
|
|
bmi token_count_lt_zero ; if(count >= 0)
|
|
|
|
sub r6, r6, r3 ; offset = shift - count
|
|
sub r4, r6, #1 ; offset-1
|
|
lsls r4, r2, r4 ; if((lowvalue<<(offset-1)) & 0x80000000 )
|
|
bpl token_high_bit_not_set
|
|
|
|
ldr r4, [r0, #vp8_writer_pos] ; x
|
|
sub r4, r4, #1 ; x = w->pos-1
|
|
b token_zero_while_start
|
|
token_zero_while_loop
|
|
mov r9, #0
|
|
strb r9, [r7, r4] ; w->buffer[x] =(unsigned char)0
|
|
sub r4, r4, #1 ; x--
|
|
token_zero_while_start
|
|
cmp r4, #0
|
|
ldrge r7, [r0, #vp8_writer_buffer]
|
|
ldrb r1, [r7, r4]
|
|
cmpge r1, #0xff
|
|
beq token_zero_while_loop
|
|
|
|
ldr r7, [r0, #vp8_writer_buffer]
|
|
ldrb r9, [r7, r4] ; w->buffer[x]
|
|
add r9, r9, #1
|
|
strb r9, [r7, r4] ; w->buffer[x] + 1
|
|
token_high_bit_not_set
|
|
rsb r4, r6, #24 ; 24-offset
|
|
ldr r9, [r0, #vp8_writer_buffer]
|
|
lsr r7, r2, r4 ; lowvalue >> (24-offset)
|
|
ldr r4, [r0, #vp8_writer_pos] ; w->pos
|
|
lsl r2, r2, r6 ; lowvalue <<= offset
|
|
mov r6, r3 ; shift = count
|
|
add r1, r4, #1 ; w->pos++
|
|
bic r2, r2, #0xff000000 ; lowvalue &= 0xffffff
|
|
str r1, [r0, #vp8_writer_pos]
|
|
sub r3, r3, #8 ; count -= 8
|
|
|
|
VALIDATE_POS r9, r1 ; validate_buffer at pos
|
|
|
|
strb r7, [r9, r4] ; w->buffer[w->pos++]
|
|
|
|
token_count_lt_zero
|
|
lsl r2, r2, r6 ; lowvalue <<= shift
|
|
|
|
str r2, [r0, #vp8_writer_lowvalue]
|
|
str r5, [r0, #vp8_writer_range]
|
|
str r3, [r0, #vp8_writer_count]
|
|
pop {r4-r10, pc}
|
|
ENDP
|
|
|
|
; r0 BOOL_CODER *br
|
|
|vp8_stop_encode| PROC
|
|
push {r4-r10, lr}
|
|
|
|
ldr r2, [r0, #vp8_writer_lowvalue]
|
|
ldr r5, [r0, #vp8_writer_range]
|
|
ldr r3, [r0, #vp8_writer_count]
|
|
|
|
mov r10, #32
|
|
|
|
stop_encode_loop
|
|
sub r7, r5, #1 ; range-1
|
|
|
|
mov r4, r7, lsl #7 ; ((range-1) * 128)
|
|
|
|
mov r7, #1
|
|
add r4, r7, r4, lsr #8 ; 1 + (((range-1) * 128) >> 8)
|
|
|
|
; Counting the leading zeros is used to normalize range.
|
|
clz r6, r4
|
|
sub r6, r6, #24 ; shift
|
|
|
|
; Flag is set on the sum of count. This flag is used later
|
|
; to determine if count >= 0
|
|
adds r3, r3, r6 ; count += shift
|
|
lsl r5, r4, r6 ; range <<= shift
|
|
bmi token_count_lt_zero_se ; if(count >= 0)
|
|
|
|
sub r6, r6, r3 ; offset = shift - count
|
|
sub r4, r6, #1 ; offset-1
|
|
lsls r4, r2, r4 ; if((lowvalue<<(offset-1)) & 0x80000000 )
|
|
bpl token_high_bit_not_set_se
|
|
|
|
ldr r4, [r0, #vp8_writer_pos] ; x
|
|
sub r4, r4, #1 ; x = w->pos-1
|
|
b token_zero_while_start_se
|
|
token_zero_while_loop_se
|
|
mov r9, #0
|
|
strb r9, [r7, r4] ; w->buffer[x] =(unsigned char)0
|
|
sub r4, r4, #1 ; x--
|
|
token_zero_while_start_se
|
|
cmp r4, #0
|
|
ldrge r7, [r0, #vp8_writer_buffer]
|
|
ldrb r1, [r7, r4]
|
|
cmpge r1, #0xff
|
|
beq token_zero_while_loop_se
|
|
|
|
ldr r7, [r0, #vp8_writer_buffer]
|
|
ldrb r9, [r7, r4] ; w->buffer[x]
|
|
add r9, r9, #1
|
|
strb r9, [r7, r4] ; w->buffer[x] + 1
|
|
token_high_bit_not_set_se
|
|
rsb r4, r6, #24 ; 24-offset
|
|
ldr r9, [r0, #vp8_writer_buffer]
|
|
lsr r7, r2, r4 ; lowvalue >> (24-offset)
|
|
ldr r4, [r0, #vp8_writer_pos] ; w->pos
|
|
lsl r2, r2, r6 ; lowvalue <<= offset
|
|
mov r6, r3 ; shift = count
|
|
add r1, r4, #1 ; w->pos++
|
|
bic r2, r2, #0xff000000 ; lowvalue &= 0xffffff
|
|
str r1, [r0, #vp8_writer_pos]
|
|
sub r3, r3, #8 ; count -= 8
|
|
|
|
VALIDATE_POS r9, r1 ; validate_buffer at pos
|
|
|
|
strb r7, [r9, r4] ; w->buffer[w->pos++]
|
|
|
|
token_count_lt_zero_se
|
|
lsl r2, r2, r6 ; lowvalue <<= shift
|
|
|
|
subs r10, r10, #1
|
|
bne stop_encode_loop
|
|
|
|
str r2, [r0, #vp8_writer_lowvalue]
|
|
str r5, [r0, #vp8_writer_range]
|
|
str r3, [r0, #vp8_writer_count]
|
|
pop {r4-r10, pc}
|
|
|
|
ENDP
|
|
|
|
; r0 BOOL_CODER *br
|
|
; r1 int data
|
|
; r2 int bits
|
|
|vp8_encode_value| PROC
|
|
push {r4-r12, lr}
|
|
|
|
mov r10, r2
|
|
|
|
ldr r2, [r0, #vp8_writer_lowvalue]
|
|
ldr r5, [r0, #vp8_writer_range]
|
|
ldr r3, [r0, #vp8_writer_count]
|
|
|
|
rsb r4, r10, #32 ; 32-n
|
|
|
|
; v is kept in r1 during the token pack loop
|
|
lsl r1, r1, r4 ; r1 = v << 32 - n
|
|
|
|
encode_value_loop
|
|
sub r7, r5, #1 ; range-1
|
|
|
|
; Decisions are made based on the bit value shifted
|
|
; off of v, so set a flag here based on this.
|
|
; This value is refered to as "bb"
|
|
lsls r1, r1, #1 ; bit = v >> n
|
|
mov r4, r7, lsl #7 ; ((range-1) * 128)
|
|
|
|
mov r7, #1
|
|
add r4, r7, r4, lsr #8 ; 1 + (((range-1) * 128) >> 8)
|
|
|
|
addcs r2, r2, r4 ; if (bit) lowvalue += split
|
|
subcs r4, r5, r4 ; if (bit) range = range-split
|
|
|
|
; Counting the leading zeros is used to normalize range.
|
|
clz r6, r4
|
|
sub r6, r6, #24 ; shift
|
|
|
|
; Flag is set on the sum of count. This flag is used later
|
|
; to determine if count >= 0
|
|
adds r3, r3, r6 ; count += shift
|
|
lsl r5, r4, r6 ; range <<= shift
|
|
bmi token_count_lt_zero_ev ; if(count >= 0)
|
|
|
|
sub r6, r6, r3 ; offset = shift - count
|
|
sub r4, r6, #1 ; offset-1
|
|
lsls r4, r2, r4 ; if((lowvalue<<(offset-1)) & 0x80000000 )
|
|
bpl token_high_bit_not_set_ev
|
|
|
|
ldr r4, [r0, #vp8_writer_pos] ; x
|
|
sub r4, r4, #1 ; x = w->pos-1
|
|
b token_zero_while_start_ev
|
|
token_zero_while_loop_ev
|
|
mov r9, #0
|
|
strb r9, [r7, r4] ; w->buffer[x] =(unsigned char)0
|
|
sub r4, r4, #1 ; x--
|
|
token_zero_while_start_ev
|
|
cmp r4, #0
|
|
ldrge r7, [r0, #vp8_writer_buffer]
|
|
ldrb r11, [r7, r4]
|
|
cmpge r11, #0xff
|
|
beq token_zero_while_loop_ev
|
|
|
|
ldr r7, [r0, #vp8_writer_buffer]
|
|
ldrb r9, [r7, r4] ; w->buffer[x]
|
|
add r9, r9, #1
|
|
strb r9, [r7, r4] ; w->buffer[x] + 1
|
|
token_high_bit_not_set_ev
|
|
rsb r4, r6, #24 ; 24-offset
|
|
ldr r9, [r0, #vp8_writer_buffer]
|
|
lsr r7, r2, r4 ; lowvalue >> (24-offset)
|
|
ldr r4, [r0, #vp8_writer_pos] ; w->pos
|
|
lsl r2, r2, r6 ; lowvalue <<= offset
|
|
mov r6, r3 ; shift = count
|
|
add r11, r4, #1 ; w->pos++
|
|
bic r2, r2, #0xff000000 ; lowvalue &= 0xffffff
|
|
str r11, [r0, #vp8_writer_pos]
|
|
sub r3, r3, #8 ; count -= 8
|
|
|
|
VALIDATE_POS r9, r11 ; validate_buffer at pos
|
|
|
|
strb r7, [r9, r4] ; w->buffer[w->pos++]
|
|
|
|
token_count_lt_zero_ev
|
|
lsl r2, r2, r6 ; lowvalue <<= shift
|
|
|
|
subs r10, r10, #1
|
|
bne encode_value_loop
|
|
|
|
str r2, [r0, #vp8_writer_lowvalue]
|
|
str r5, [r0, #vp8_writer_range]
|
|
str r3, [r0, #vp8_writer_count]
|
|
pop {r4-r12, pc}
|
|
ENDP
|
|
|
|
END
|