/* * Copyright (c) 2013 RISC OS Open Ltd * Author: Ben Avison <bavison@riscosopen.org> * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libavutil/arm/asm.S" RESULT .req a1BUF .req a1SIZE .req a2PATTERN .req a3PTR .req a4DAT0 .req v1DAT1 .req v2DAT2 .req v3DAT3 .req v4TMP0 .req v5TMP1 .req v6TMP2 .req ipTMP3 .req lr #define PRELOAD_DISTANCE 4 .macro innerloop4 ldr DAT0, [PTR], #4 subs SIZE, SIZE, #4 @ C flag survives rest of macro sub TMP0, DAT0, PATTERN, lsr #14 bic TMP0, TMP0, DAT0 ands TMP0, TMP0, PATTERN.endm .macro innerloop16 decrement, do_preload ldmia PTR!, {DAT0,DAT1,DAT2,DAT3} .ifnc "\do_preload","" pld [PTR, #PRELOAD_DISTANCE*32] .endif .ifnc "\decrement","" subs SIZE, SIZE, #\decrement @ C flag survives rest of macro .endif sub TMP0, DAT0, PATTERN, lsr #14 sub TMP1, DAT1, PATTERN, lsr #14 bic TMP0, TMP0, DAT0 bic TMP1, TMP1, DAT1 sub TMP2, DAT2, PATTERN, lsr #14 sub TMP3, DAT3, PATTERN, lsr #14 ands TMP0, TMP0, PATTERN bic TMP2, TMP2, DAT2 it eq andseq TMP1, TMP1, PATTERN bic TMP3, TMP3, DAT3 itt eq andseq TMP2, TMP2, PATTERN andseq TMP3, TMP3, PATTERN.endm /* int ff_startcode_find_candidate_armv6(const uint8_t *buf, int size) */function ff_startcode_find_candidate_armv6, export=1 push {v1-v6,lr} mov PTR, BUF @ Ensure there are at least (PRELOAD_DISTANCE+2) complete cachelines to go @ before using code that does preloads cmp SIZE, #(PRELOAD_DISTANCE+3)*32 - 1 blo 60f @ Get to word-alignment, 1 byte at a time tst PTR, #3 beq 2f1: ldrb DAT0, [PTR], #1 sub SIZE, SIZE, #1 teq DAT0, #0 beq 90f tst PTR, #3 bne 1b2: @ Get to 4-word alignment, 1 word at a time ldr PATTERN, =0x80008000 setend be tst PTR, #12 beq 4f3: innerloop4 bne 91f tst PTR, #12 bne 3b4: @ Get to cacheline (8-word) alignment tst PTR, #16 beq 5f innerloop16 16 bne 93f5: @ Check complete cachelines, with preloading @ We need to stop when there are still (PRELOAD_DISTANCE+1) @ complete cachelines to go sub SIZE, SIZE, #(PRELOAD_DISTANCE+2)*326: innerloop16 , do_preload bne 93f innerloop16 32 bne 93f bcs 6b @ Preload trailing part-cacheline, if any tst SIZE, #31 beq 7f pld [PTR, #(PRELOAD_DISTANCE+1)*32] @ Check remaining data without doing any more preloads. First @ do in chunks of 4 words:7: adds SIZE, SIZE, #(PRELOAD_DISTANCE+2)*32 - 16 bmi 9f8: innerloop16 16 bne 93f bcs 8b @ Then in words:9: adds SIZE, SIZE, #16 - 4 bmi 11f10: innerloop4 bne 91f bcs 10b11: setend le @ Check second byte of final halfword ldrb DAT0, [PTR, #-1] teq DAT0, #0 beq 90f @ Check any remaining bytes tst SIZE, #3 beq 13f12: ldrb DAT0, [PTR], #1 sub SIZE, SIZE, #1 teq DAT0, #0 beq 90f tst SIZE, #3 bne 12b @ No candidate found13: sub RESULT, PTR, BUF b 99f 60: @ Small buffer - simply check by looping over bytes subs SIZE, SIZE, #1 bcc 99f61: ldrb DAT0, [PTR], #1 subs SIZE, SIZE, #1 teq DAT0, #0 beq 90f bcs 61b @ No candidate found sub RESULT, PTR, BUF b 99f 90: @ Found a candidate at the preceding byte sub RESULT, PTR, BUF sub RESULT, RESULT, #1 b 99f 91: @ Found a candidate somewhere in the preceding 4 bytes sub RESULT, PTR, BUF sub RESULT, RESULT, #4 sub TMP0, DAT0, #0x20000 bics TMP0, TMP0, DAT0 itt pl ldrbpl DAT0, [PTR, #-3] addpl RESULT, RESULT, #2 bpl 92f teq RESULT, #0 beq 98f @ don't look back a byte if found at first byte in buffer ldrb DAT0, [PTR, #-5]92: teq DAT0, #0 it eq subeq RESULT, RESULT, #1 b 98f 93: @ Found a candidate somewhere in the preceding 16 bytes sub RESULT, PTR, BUF sub RESULT, RESULT, #16 teq TMP0, #0 beq 95f @ not in first 4 bytes sub TMP0, DAT0, #0x20000 bics TMP0, TMP0, DAT0 itt pl ldrbpl DAT0, [PTR, #-15] addpl RESULT, RESULT, #2 bpl 94f teq RESULT, #0 beq 98f @ don't look back a byte if found at first byte in buffer ldrb DAT0, [PTR, #-17]94: teq DAT0, #0 it eq subeq RESULT, RESULT, #1 b 98f95: add RESULT, RESULT, #4 teq TMP1, #0 beq 96f @ not in next 4 bytes sub TMP1, DAT1, #0x20000 bics TMP1, TMP1, DAT1 itee mi ldrbmi DAT0, [PTR, #-13] ldrbpl DAT0, [PTR, #-11] addpl RESULT, RESULT, #2 teq DAT0, #0 it eq subeq RESULT, RESULT, #1 b 98f96: add RESULT, RESULT, #4 teq TMP2, #0 beq 97f @ not in next 4 bytes sub TMP2, DAT2, #0x20000 bics TMP2, TMP2, DAT2 itee mi ldrbmi DAT0, [PTR, #-9] ldrbpl DAT0, [PTR, #-7] addpl RESULT, RESULT, #2 teq DAT0, #0 it eq subeq RESULT, RESULT, #1 b 98f97: add RESULT, RESULT, #4 sub TMP3, DAT3, #0x20000 bics TMP3, TMP3, DAT3 itee mi ldrbmi DAT0, [PTR, #-5] ldrbpl DAT0, [PTR, #-3] addpl RESULT, RESULT, #2 teq DAT0, #0 it eq subeq RESULT, RESULT, #1 @ drop through to 98f98: setend le99: pop {v1-v6,pc}endfunc .unreq RESULT .unreq BUF .unreq SIZE .unreq PATTERN .unreq PTR .unreq DAT0 .unreq DAT1 .unreq DAT2 .unreq DAT3 .unreq TMP0 .unreq TMP1 .unreq TMP2 .unreq TMP3
/*
* Copyright (c) 2013 RISC OS Open Ltd
* Author: Ben Avison <bavison@riscosopen.org>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "libavutil/arm/asm.S"
RESULT .req a1
BUF .req a1
SIZE .req a2
PATTERN .req a3
PTR .req a4
DAT0 .req v1
DAT1 .req v2
DAT2 .req v3
DAT3 .req v4
TMP0 .req v5
TMP1 .req v6
TMP2 .req ip
TMP3 .req lr
#define PRELOAD_DISTANCE 4
.macro innerloop4
ldr DAT0, [PTR], #4
subs SIZE, SIZE, #4 @ C flag survives rest of macro
sub TMP0, DAT0, PATTERN, lsr #14
bic TMP0, TMP0, DAT0
ands TMP0, TMP0, PATTERN
.endm
.macro innerloop16 decrement, do_preload
ldmia PTR!, {DAT0,DAT1,DAT2,DAT3}
.ifnc "\do_preload",""
pld [PTR, #PRELOAD_DISTANCE*32]
.endif
.ifnc "\decrement",""
subs SIZE, SIZE, #\decrement @ C flag survives rest of macro
.endif
sub TMP0, DAT0, PATTERN, lsr #14
sub TMP1, DAT1, PATTERN, lsr #14
bic TMP0, TMP0, DAT0
bic TMP1, TMP1, DAT1
sub TMP2, DAT2, PATTERN, lsr #14
sub TMP3, DAT3, PATTERN, lsr #14
ands TMP0, TMP0, PATTERN
bic TMP2, TMP2, DAT2
it eq
andseq TMP1, TMP1, PATTERN
bic TMP3, TMP3, DAT3
itt eq
andseq TMP2, TMP2, PATTERN
andseq TMP3, TMP3, PATTERN
.endm
/* int ff_startcode_find_candidate_armv6(const uint8_t *buf, int size) */
function ff_startcode_find_candidate_armv6, export=1
push {v1-v6,lr}
mov PTR, BUF
@ Ensure there are at least (PRELOAD_DISTANCE+2) complete cachelines to go
@ before using code that does preloads
cmp SIZE, #(PRELOAD_DISTANCE+3)*32 - 1
blo 60f
@ Get to word-alignment, 1 byte at a time
tst PTR, #3
beq 2f
1: ldrb DAT0, [PTR], #1
sub SIZE, SIZE, #1
teq DAT0, #0
beq 90f
tst PTR, #3
bne 1b
2: @ Get to 4-word alignment, 1 word at a time
ldr PATTERN, =0x80008000
setend be
tst PTR, #12
beq 4f
3: innerloop4
bne 91f
tst PTR, #12
bne 3b
4: @ Get to cacheline (8-word) alignment
tst PTR, #16
beq 5f
innerloop16 16
bne 93f
5: @ Check complete cachelines, with preloading
@ We need to stop when there are still (PRELOAD_DISTANCE+1)
@ complete cachelines to go
sub SIZE, SIZE, #(PRELOAD_DISTANCE+2)*32
6: innerloop16 , do_preload
bne 93f
innerloop16 32
bne 93f
bcs 6b
@ Preload trailing part-cacheline, if any
tst SIZE, #31
beq 7f
pld [PTR, #(PRELOAD_DISTANCE+1)*32]
@ Check remaining data without doing any more preloads. First
@ do in chunks of 4 words:
7: adds SIZE, SIZE, #(PRELOAD_DISTANCE+2)*32 - 16
bmi 9f
8: innerloop16 16
bne 93f
bcs 8b
@ Then in words:
9: adds SIZE, SIZE, #16 - 4
bmi 11f
10: innerloop4
bne 91f
bcs 10b
11: setend le
@ Check second byte of final halfword
ldrb DAT0, [PTR, #-1]
teq DAT0, #0
beq 90f
@ Check any remaining bytes
tst SIZE, #3
beq 13f
12: ldrb DAT0, [PTR], #1
sub SIZE, SIZE, #1
teq DAT0, #0
beq 90f
tst SIZE, #3
bne 12b
@ No candidate found
13: sub RESULT, PTR, BUF
b 99f
60: @ Small buffer - simply check by looping over bytes
subs SIZE, SIZE, #1
bcc 99f
61: ldrb DAT0, [PTR], #1
subs SIZE, SIZE, #1
teq DAT0, #0
beq 90f
bcs 61b
@ No candidate found
sub RESULT, PTR, BUF
b 99f
90: @ Found a candidate at the preceding byte
sub RESULT, PTR, BUF
sub RESULT, RESULT, #1
b 99f
91: @ Found a candidate somewhere in the preceding 4 bytes
sub RESULT, PTR, BUF
sub RESULT, RESULT, #4
sub TMP0, DAT0, #0x20000
bics TMP0, TMP0, DAT0
itt pl
ldrbpl DAT0, [PTR, #-3]
addpl RESULT, RESULT, #2
bpl 92f
teq RESULT, #0
beq 98f @ don't look back a byte if found at first byte in buffer
ldrb DAT0, [PTR, #-5]
92: teq DAT0, #0
it eq
subeq RESULT, RESULT, #1
b 98f
93: @ Found a candidate somewhere in the preceding 16 bytes
sub RESULT, PTR, BUF
sub RESULT, RESULT, #16
teq TMP0, #0
beq 95f @ not in first 4 bytes
sub TMP0, DAT0, #0x20000
bics TMP0, TMP0, DAT0
itt pl
ldrbpl DAT0, [PTR, #-15]
addpl RESULT, RESULT, #2
bpl 94f
teq RESULT, #0
beq 98f @ don't look back a byte if found at first byte in buffer
ldrb DAT0, [PTR, #-17]
94: teq DAT0, #0
it eq
subeq RESULT, RESULT, #1
b 98f
95: add RESULT, RESULT, #4
teq TMP1, #0
beq 96f @ not in next 4 bytes
sub TMP1, DAT1, #0x20000
bics TMP1, TMP1, DAT1
itee mi
ldrbmi DAT0, [PTR, #-13]
ldrbpl DAT0, [PTR, #-11]
addpl RESULT, RESULT, #2
teq DAT0, #0
it eq
subeq RESULT, RESULT, #1
b 98f
96: add RESULT, RESULT, #4
teq TMP2, #0
beq 97f @ not in next 4 bytes
sub TMP2, DAT2, #0x20000
bics TMP2, TMP2, DAT2
itee mi
ldrbmi DAT0, [PTR, #-9]
ldrbpl DAT0, [PTR, #-7]
addpl RESULT, RESULT, #2
teq DAT0, #0
it eq
subeq RESULT, RESULT, #1
b 98f
97: add RESULT, RESULT, #4
sub TMP3, DAT3, #0x20000
bics TMP3, TMP3, DAT3
itee mi
ldrbmi DAT0, [PTR, #-5]
ldrbpl DAT0, [PTR, #-3]
addpl RESULT, RESULT, #2
teq DAT0, #0
it eq
subeq RESULT, RESULT, #1
@ drop through to 98f
98: setend le
99: pop {v1-v6,pc}
endfunc
.unreq RESULT
.unreq BUF
.unreq SIZE
.unreq PATTERN
.unreq PTR
.unreq DAT0
.unreq DAT1
.unreq DAT2
.unreq DAT3
.unreq TMP0
.unreq TMP1
.unreq TMP2
.unreq TMP3