1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * This file is part of FFmpeg.
3cabdff1aSopenharmony_ci *
4cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or
5cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public
6cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either
7cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version.
8cabdff1aSopenharmony_ci *
9cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful,
10cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
11cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12cabdff1aSopenharmony_ci * Lesser General Public License for more details.
13cabdff1aSopenharmony_ci *
14cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public
15cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software
16cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17cabdff1aSopenharmony_ci */
18cabdff1aSopenharmony_ci
19cabdff1aSopenharmony_ci#ifndef AVCODEC_AARCH64_CABAC_H
20cabdff1aSopenharmony_ci#define AVCODEC_AARCH64_CABAC_H
21cabdff1aSopenharmony_ci
22cabdff1aSopenharmony_ci#include "config.h"
23cabdff1aSopenharmony_ci#if HAVE_INLINE_ASM
24cabdff1aSopenharmony_ci
25cabdff1aSopenharmony_ci#include "libavutil/attributes.h"
26cabdff1aSopenharmony_ci#include "libavutil/internal.h"
27cabdff1aSopenharmony_ci#include "libavcodec/cabac.h"
28cabdff1aSopenharmony_ci
29cabdff1aSopenharmony_ci#define get_cabac_inline get_cabac_inline_aarch64
30cabdff1aSopenharmony_cistatic av_always_inline int get_cabac_inline_aarch64(CABACContext *c,
31cabdff1aSopenharmony_ci                                                     uint8_t *const state)
32cabdff1aSopenharmony_ci{
33cabdff1aSopenharmony_ci    int bit;
34cabdff1aSopenharmony_ci    void *reg_a, *reg_b, *reg_c, *tmp;
35cabdff1aSopenharmony_ci
36cabdff1aSopenharmony_ci    __asm__ volatile(
37cabdff1aSopenharmony_ci        "ldrb       %w[bit]       , [%[state]]                  \n\t"
38cabdff1aSopenharmony_ci        "add        %[r_b]        , %[tables]   , %[lps_off]    \n\t"
39cabdff1aSopenharmony_ci        "mov        %w[tmp]       , %w[range]                   \n\t"
40cabdff1aSopenharmony_ci        "and        %w[range]     , %w[range]   , #0xC0         \n\t"
41cabdff1aSopenharmony_ci        "lsl        %w[r_c]       , %w[range]   , #1            \n\t"
42cabdff1aSopenharmony_ci        "add        %[r_b]        , %[r_b]      , %w[bit], UXTW \n\t"
43cabdff1aSopenharmony_ci        "ldrb       %w[range]     , [%[r_b], %w[r_c], SXTW]     \n\t"
44cabdff1aSopenharmony_ci        "sub        %w[r_c]       , %w[tmp]     , %w[range]     \n\t"
45cabdff1aSopenharmony_ci        "lsl        %w[tmp]       , %w[r_c]     , #17           \n\t"
46cabdff1aSopenharmony_ci        "cmp        %w[tmp]       , %w[low]                     \n\t"
47cabdff1aSopenharmony_ci        "csel       %w[tmp]       , %w[tmp]     , wzr      , cc \n\t"
48cabdff1aSopenharmony_ci        "csel       %w[range]     , %w[r_c]     , %w[range], gt \n\t"
49cabdff1aSopenharmony_ci        "cinv       %w[bit]       , %w[bit]     , cc            \n\t"
50cabdff1aSopenharmony_ci        "sub        %w[low]       , %w[low]     , %w[tmp]       \n\t"
51cabdff1aSopenharmony_ci        "add        %[r_b]        , %[tables]   , %[norm_off]   \n\t"
52cabdff1aSopenharmony_ci        "add        %[r_a]        , %[tables]   , %[mlps_off]   \n\t"
53cabdff1aSopenharmony_ci        "ldrb       %w[tmp]       , [%[r_b], %w[range], SXTW]   \n\t"
54cabdff1aSopenharmony_ci        "ldrb       %w[r_a]       , [%[r_a], %w[bit], SXTW]     \n\t"
55cabdff1aSopenharmony_ci        "lsl        %w[low]       , %w[low]     , %w[tmp]       \n\t"
56cabdff1aSopenharmony_ci        "lsl        %w[range]     , %w[range]   , %w[tmp]       \n\t"
57cabdff1aSopenharmony_ci        "uxth       %w[r_c]       , %w[low]                     \n\t"
58cabdff1aSopenharmony_ci        "strb       %w[r_a]       , [%[state]]                  \n\t"
59cabdff1aSopenharmony_ci        "cbnz       %w[r_c]       , 2f                          \n\t"
60cabdff1aSopenharmony_ci        "ldr        %[r_c]        , [%[c], %[byte]]             \n\t"
61cabdff1aSopenharmony_ci        "ldr        %[r_a]        , [%[c], %[end]]              \n\t"
62cabdff1aSopenharmony_ci        "ldrh       %w[tmp]       , [%[r_c]]                    \n\t"
63cabdff1aSopenharmony_ci        "cmp        %[r_c]        , %[r_a]                      \n\t"
64cabdff1aSopenharmony_ci        "b.ge       1f                                          \n\t"
65cabdff1aSopenharmony_ci        "add        %[r_a]        , %[r_c]      , #2            \n\t"
66cabdff1aSopenharmony_ci        "str        %[r_a]        , [%[c], %[byte]]             \n\t"
67cabdff1aSopenharmony_ci        "1:                                                     \n\t"
68cabdff1aSopenharmony_ci        "sub        %w[r_c]       , %w[low]     , #1            \n\t"
69cabdff1aSopenharmony_ci        "eor        %w[r_c]       , %w[r_c]     , %w[low]       \n\t"
70cabdff1aSopenharmony_ci        "rev        %w[tmp]       , %w[tmp]                     \n\t"
71cabdff1aSopenharmony_ci        "lsr        %w[r_c]       , %w[r_c]     , #15           \n\t"
72cabdff1aSopenharmony_ci        "lsr        %w[tmp]       , %w[tmp]     , #15           \n\t"
73cabdff1aSopenharmony_ci        "ldrb       %w[r_c]       , [%[r_b], %w[r_c], SXTW]     \n\t"
74cabdff1aSopenharmony_ci        "mov        %w[r_b]       , #0xFFFF                     \n\t"
75cabdff1aSopenharmony_ci        "mov        %w[r_a]       , #7                          \n\t"
76cabdff1aSopenharmony_ci        "sub        %w[tmp]       , %w[tmp]     , %w[r_b]       \n\t"
77cabdff1aSopenharmony_ci        "sub        %w[r_c]       , %w[r_a]     , %w[r_c]       \n\t"
78cabdff1aSopenharmony_ci        "lsl        %w[tmp]       , %w[tmp]     , %w[r_c]       \n\t"
79cabdff1aSopenharmony_ci        "add        %w[low]       , %w[low]     , %w[tmp]       \n\t"
80cabdff1aSopenharmony_ci        "2:                                                     \n\t"
81cabdff1aSopenharmony_ci        :    [bit]"=&r"(bit),
82cabdff1aSopenharmony_ci             [low]"+&r"(c->low),
83cabdff1aSopenharmony_ci           [range]"+&r"(c->range),
84cabdff1aSopenharmony_ci             [r_a]"=&r"(reg_a),
85cabdff1aSopenharmony_ci             [r_b]"=&r"(reg_b),
86cabdff1aSopenharmony_ci             [r_c]"=&r"(reg_c),
87cabdff1aSopenharmony_ci             [tmp]"=&r"(tmp)
88cabdff1aSopenharmony_ci        :        [c]"r"(c),
89cabdff1aSopenharmony_ci             [state]"r"(state),
90cabdff1aSopenharmony_ci            [tables]"r"(ff_h264_cabac_tables),
91cabdff1aSopenharmony_ci              [byte]"i"(offsetof(CABACContext, bytestream)),
92cabdff1aSopenharmony_ci               [end]"i"(offsetof(CABACContext, bytestream_end)),
93cabdff1aSopenharmony_ci          [norm_off]"I"(H264_NORM_SHIFT_OFFSET),
94cabdff1aSopenharmony_ci           [lps_off]"I"(H264_LPS_RANGE_OFFSET),
95cabdff1aSopenharmony_ci          [mlps_off]"I"(H264_MLPS_STATE_OFFSET + 128)
96cabdff1aSopenharmony_ci        : "memory", "cc"
97cabdff1aSopenharmony_ci        );
98cabdff1aSopenharmony_ci
99cabdff1aSopenharmony_ci    return bit & 1;
100cabdff1aSopenharmony_ci}
101cabdff1aSopenharmony_ci
102cabdff1aSopenharmony_ci#endif /* HAVE_INLINE_ASM */
103cabdff1aSopenharmony_ci
104cabdff1aSopenharmony_ci#endif /* AVCODEC_AARCH64_CABAC_H */
105