ARM: allow building in Thumb2 mode
[ffmpeg.git] / libavcodec / arm / vp56_arith.h
1 /*
2  * Copyright (C) 2010 Mans Rullgard <mans@mansr.com>
3  *
4  * This file is part of Libav.
5  *
6  * Libav is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * Libav is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with Libav; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20
21 #ifndef AVCODEC_ARM_VP56_ARITH_H
22 #define AVCODEC_ARM_VP56_ARITH_H
23
24 #if CONFIG_THUMB
25 #   define A(x)
26 #   define T(x) x
27 #else
28 #   define A(x) x
29 #   define T(x)
30 #endif
31
32 #if HAVE_ARMV6 && HAVE_INLINE_ASM
33
34 #define vp56_rac_get_prob vp56_rac_get_prob_armv6
35 static inline int vp56_rac_get_prob_armv6(VP56RangeCoder *c, int pr)
36 {
37     unsigned shift     = ff_vp56_norm_shift[c->high];
38     unsigned code_word = c->code_word << shift;
39     unsigned high      = c->high << shift;
40     unsigned bit;
41
42     __asm__ ("adds    %3,  %3,  %0           \n"
43              "itt     cs                     \n"
44              "cmpcs   %7,  %4                \n"
45            A("ldrcsh  %2,  [%4], #2          \n")
46            T("ldrhcs  %2,  [%4], #2          \n")
47              "rsb     %0,  %6,  #256         \n"
48              "smlabb  %0,  %5,  %6,  %0      \n"
49            T("itttt   cs                     \n")
50              "rev16cs %2,  %2                \n"
51            T("lslcs   %2,  %2,  %3           \n")
52            T("orrcs   %1,  %1,  %2           \n")
53            A("orrcs   %1,  %1,  %2,  lsl %3  \n")
54              "subcs   %3,  %3,  #16          \n"
55              "lsr     %0,  %0,  #8           \n"
56              "cmp     %1,  %0,  lsl #16      \n"
57              "ittte   ge                     \n"
58              "subge   %1,  %1,  %0,  lsl #16 \n"
59              "subge   %0,  %5,  %0           \n"
60              "movge   %2,  #1                \n"
61              "movlt   %2,  #0                \n"
62              : "=&r"(c->high), "=&r"(c->code_word), "=&r"(bit),
63                "+&r"(c->bits), "+&r"(c->buffer)
64              : "r"(high), "r"(pr), "r"(c->end - 1),
65                "0"(shift), "1"(code_word)
66              : "cc");
67
68     return bit;
69 }
70
71 #define vp56_rac_get_prob_branchy vp56_rac_get_prob_branchy_armv6
72 static inline int vp56_rac_get_prob_branchy_armv6(VP56RangeCoder *c, int pr)
73 {
74     unsigned shift     = ff_vp56_norm_shift[c->high];
75     unsigned code_word = c->code_word << shift;
76     unsigned high      = c->high << shift;
77     unsigned low;
78     unsigned tmp;
79
80     __asm__ ("adds    %3,  %3,  %0           \n"
81              "itt     cs                     \n"
82              "cmpcs   %7,  %4                \n"
83            A("ldrcsh  %2,  [%4], #2          \n")
84            T("ldrhcs  %2,  [%4], #2          \n")
85              "rsb     %0,  %6,  #256         \n"
86              "smlabb  %0,  %5,  %6,  %0      \n"
87            T("itttt   cs                     \n")
88              "rev16cs %2,  %2                \n"
89            T("lslcs   %2,  %2,  %3           \n")
90            T("orrcs   %1,  %1,  %2           \n")
91            A("orrcs   %1,  %1,  %2,  lsl %3  \n")
92              "subcs   %3,  %3,  #16          \n"
93              "lsr     %0,  %0,  #8           \n"
94              "lsl     %2,  %0,  #16          \n"
95              : "=&r"(low), "+&r"(code_word), "=&r"(tmp),
96                "+&r"(c->bits), "+&r"(c->buffer)
97              : "r"(high), "r"(pr), "r"(c->end - 1), "0"(shift)
98              : "cc");
99
100     if (code_word >= tmp) {
101         c->high      = high - low;
102         c->code_word = code_word - tmp;
103         return 1;
104     }
105
106     c->high      = low;
107     c->code_word = code_word;
108     return 0;
109 }
110
111 #endif
112
113 #endif /* AVCODEC_ARM_VP56_ARITH_H */