| /* | |
| * 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 |