1 /*
2 * Loongson SIMD optimized h264chroma
3 *
4 * Copyright (c) 2018 Loongson Technology Corporation Limited
5 * Contributed by Shiyou Yin <yinshiyou-hf@loongson.cn>
6 * Gu Xiwei(guxiwei-hf@loongson.cn)
7 *
8 * This file is part of FFmpeg.
9 *
10 * FFmpeg is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
14 *
15 * FFmpeg is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with FFmpeg; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
25 #ifndef AVCODEC_MIPS_CABAC_H
26 #define AVCODEC_MIPS_CABAC_H
27
28 #include "libavutil/attributes.h"
29 #include "libavcodec/cabac.h"
30 #include "libavutil/mips/mmiutils.h"
31 #include "config.h"
32
33 #define get_cabac_inline get_cabac_inline_mips
get_cabac_inline_mips(CABACContext * c,uint8_t * const state)34 static av_always_inline int get_cabac_inline_mips(CABACContext *c,
35 uint8_t * const state){
36 mips_reg tmp0, tmp1, tmp2, bit;
37
38 __asm__ volatile (
39 "lbu %[bit], 0(%[state]) \n\t"
40 "and %[tmp0], %[c_range], 0xC0 \n\t"
41 PTR_SLL "%[tmp0], %[tmp0], 0x01 \n\t"
42 PTR_ADDU "%[tmp0], %[tmp0], %[tables] \n\t"
43 PTR_ADDU "%[tmp0], %[tmp0], %[bit] \n\t"
44 /* tmp1: RangeLPS */
45 "lbu %[tmp1], %[lps_off](%[tmp0]) \n\t"
46
47 PTR_SUBU "%[c_range], %[c_range], %[tmp1] \n\t"
48 PTR_SLL "%[tmp0], %[c_range], 0x11 \n\t"
49 "slt %[tmp2], %[tmp0], %[c_low] \n\t"
50 "beqz %[tmp2], 1f \n\t"
51 "move %[c_range], %[tmp1] \n\t"
52 "not %[bit], %[bit] \n\t"
53 PTR_SUBU "%[c_low], %[c_low], %[tmp0] \n\t"
54
55 "1: \n\t"
56 /* tmp1: *state */
57 PTR_ADDU "%[tmp0], %[tables], %[bit] \n\t"
58 "lbu %[tmp1], %[mlps_off](%[tmp0]) \n\t"
59 /* tmp2: lps_mask */
60 PTR_ADDU "%[tmp0], %[tables], %[c_range] \n\t"
61 "lbu %[tmp2], %[norm_off](%[tmp0]) \n\t"
62
63 "sb %[tmp1], 0(%[state]) \n\t"
64 "and %[bit], %[bit], 0x01 \n\t"
65 PTR_SLL "%[c_range], %[c_range], %[tmp2] \n\t"
66 PTR_SLL "%[c_low], %[c_low], %[tmp2] \n\t"
67
68 "and %[tmp1], %[c_low], %[cabac_mask] \n\t"
69 "bnez %[tmp1], 1f \n\t"
70 PTR_ADDIU "%[tmp0], %[c_low], -0X01 \n\t"
71 "xor %[tmp0], %[c_low], %[tmp0] \n\t"
72 PTR_SRA "%[tmp0], %[tmp0], 0x0f \n\t"
73 PTR_ADDU "%[tmp0], %[tmp0], %[tables] \n\t"
74 /* tmp2: ff_h264_norm_shift[x >> (CABAC_BITS - 1)] */
75 "lbu %[tmp2], %[norm_off](%[tmp0]) \n\t"
76 #if HAVE_BIGENDIAN
77 "lhu %[tmp0], 0(%[c_bytestream]) \n\t"
78 #else
79 "lhu %[tmp0], 0(%[c_bytestream]) \n\t"
80 #if HAVE_MIPS32R2 || HAVE_MIPS64R2
81 "wsbh %[tmp0], %[tmp0] \n\t"
82 #else
83 "and %[tmp1], %[tmp0], 0xff00ff00 \n\t"
84 "srl %[tmp1], %[tmp1], 8 \n\t"
85 "and %[tmp0], %[tmp0], 0x00ff00ff \n\t"
86 "sll %[tmp0], %[tmp0], 8 \n\t"
87 "or %[tmp0], %[tmp0], %[tmp1] \n\t"
88 #endif
89 #endif
90 PTR_SLL "%[tmp0], %[tmp0], 0x01 \n\t"
91 PTR_SUBU "%[tmp0], %[tmp0], %[cabac_mask] \n\t"
92
93 "li %[tmp1], 0x07 \n\t"
94 PTR_SUBU "%[tmp1], %[tmp1], %[tmp2] \n\t"
95 PTR_SLL "%[tmp0], %[tmp0], %[tmp1] \n\t"
96 PTR_ADDU "%[c_low], %[c_low], %[tmp0] \n\t"
97
98 #if UNCHECKED_BITSTREAM_READER
99 PTR_ADDIU "%[c_bytestream], %[c_bytestream], 0x02 \n\t"
100 #else
101 "slt %[tmp0], %[c_bytestream], %[c_bytestream_end] \n\t"
102 PTR_ADDIU "%[tmp2], %[c_bytestream], 0x02 \n\t"
103 "movn %[c_bytestream], %[tmp2], %[tmp0] \n\t"
104 #endif
105 "1: \n\t"
106 : [bit]"=&r"(bit), [tmp0]"=&r"(tmp0), [tmp1]"=&r"(tmp1), [tmp2]"=&r"(tmp2),
107 [c_range]"+&r"(c->range), [c_low]"+&r"(c->low),
108 [c_bytestream]"+&r"(c->bytestream)
109 : [state]"r"(state), [tables]"r"(ff_h264_cabac_tables),
110 #if !UNCHECKED_BITSTREAM_READER
111 [c_bytestream_end]"r"(c->bytestream_end),
112 #endif
113 [lps_off]"i"(H264_LPS_RANGE_OFFSET),
114 [mlps_off]"i"(H264_MLPS_STATE_OFFSET + 128),
115 [norm_off]"i"(H264_NORM_SHIFT_OFFSET),
116 [cabac_mask]"r"(CABAC_MASK)
117 : "memory"
118 );
119
120 return bit;
121 }
122
123 #define get_cabac_bypass get_cabac_bypass_mips
get_cabac_bypass_mips(CABACContext * c)124 static av_always_inline int get_cabac_bypass_mips(CABACContext *c)
125 {
126 mips_reg tmp0, tmp1;
127 int res = 0;
128 __asm__ volatile(
129 PTR_SLL "%[c_low], %[c_low], 0x01 \n\t"
130 "and %[tmp0], %[c_low], %[cabac_mask] \n\t"
131 "bnez %[tmp0], 1f \n\t"
132 #if HAVE_BIGENDIAN
133 "lhu %[tmp1], 0(%[c_bytestream]) \n\t"
134 #else
135 "lhu %[tmp1], 0(%[c_bytestream]) \n\t"
136 #if HAVE_MIPS32R2 || HAVE_MIPS64R2
137 "wsbh %[tmp1], %[tmp1] \n\t"
138 #else
139 "and %[tmp0], %[tmp1], 0xff00ff00 \n\t"
140 "srl %[tmp0], %[tmp0], 8 \n\t"
141 "and %[tmp1], %[tmp1], 0x00ff00ff \n\t"
142 "sll %[tmp1], %[tmp1], 8 \n\t"
143 "or %[tmp1], %[tmp1], %[tmp0] \n\t"
144 #endif
145 #endif
146 PTR_SLL "%[tmp1], %[tmp1], 0x01 \n\t"
147 PTR_SUBU "%[tmp1], %[tmp1], %[cabac_mask] \n\t"
148 PTR_ADDU "%[c_low], %[c_low], %[tmp1] \n\t"
149 #if UNCHECKED_BITSTREAM_READER
150 PTR_ADDIU "%[c_bytestream], %[c_bytestream], 0x02 \n\t"
151 #else
152 "slt %[tmp0], %[c_bytestream], %[c_bytestream_end] \n\t"
153 PTR_ADDIU "%[tmp1], %[c_bytestream], 0x02 \n\t"
154 "movn %[c_bytestream], %[tmp1], %[tmp0] \n\t"
155 #endif
156 "1: \n\t"
157 PTR_SLL "%[tmp1], %[c_range], 0x11 \n\t"
158 "slt %[tmp0], %[c_low], %[tmp1] \n\t"
159 PTR_SUBU "%[tmp1], %[c_low], %[tmp1] \n\t"
160 "movz %[res], %[one], %[tmp0] \n\t"
161 "movz %[c_low], %[tmp1], %[tmp0] \n\t"
162 : [tmp0]"=&r"(tmp0), [tmp1]"=&r"(tmp1), [res]"+&r"(res),
163 [c_range]"+&r"(c->range), [c_low]"+&r"(c->low),
164 [c_bytestream]"+&r"(c->bytestream)
165 : [cabac_mask]"r"(CABAC_MASK),
166 #if !UNCHECKED_BITSTREAM_READER
167 [c_bytestream_end]"r"(c->bytestream_end),
168 #endif
169 [one]"r"(0x01)
170 : "memory"
171 );
172 return res;
173 }
174
175 #define get_cabac_bypass_sign get_cabac_bypass_sign_mips
get_cabac_bypass_sign_mips(CABACContext * c,int val)176 static av_always_inline int get_cabac_bypass_sign_mips(CABACContext *c, int val)
177 {
178 mips_reg tmp0, tmp1;
179 int res = val;
180 __asm__ volatile(
181 PTR_SLL "%[c_low], %[c_low], 0x01 \n\t"
182 "and %[tmp0], %[c_low], %[cabac_mask] \n\t"
183 "bnez %[tmp0], 1f \n\t"
184 #if HAVE_BIGENDIAN
185 "lhu %[tmp1], 0(%[c_bytestream]) \n\t"
186 #else
187 "lhu %[tmp1], 0(%[c_bytestream]) \n\t"
188 #if HAVE_MIPS32R2 || HAVE_MIPS64R2
189 "wsbh %[tmp1], %[tmp1] \n\t"
190 #else
191 "and %[tmp0], %[tmp1], 0xff00ff00 \n\t"
192 "srl %[tmp0], %[tmp0], 8 \n\t"
193 "and %[tmp1], %[tmp1], 0x00ff00ff \n\t"
194 "sll %[tmp1], %[tmp1], 8 \n\t"
195 "or %[tmp1], %[tmp1], %[tmp0] \n\t"
196 #endif
197 #endif
198 PTR_SLL "%[tmp1], %[tmp1], 0x01 \n\t"
199 PTR_SUBU "%[tmp1], %[tmp1], %[cabac_mask] \n\t"
200 PTR_ADDU "%[c_low], %[c_low], %[tmp1] \n\t"
201 #if UNCHECKED_BITSTREAM_READER
202 PTR_ADDIU "%[c_bytestream], %[c_bytestream], 0x02 \n\t"
203 #else
204 "slt %[tmp0], %[c_bytestream], %[c_bytestream_end] \n\t"
205 PTR_ADDIU "%[tmp1], %[c_bytestream], 0x02 \n\t"
206 "movn %[c_bytestream], %[tmp1], %[tmp0] \n\t"
207 #endif
208 "1: \n\t"
209 PTR_SLL "%[tmp1], %[c_range], 0x11 \n\t"
210 "slt %[tmp0], %[c_low], %[tmp1] \n\t"
211 PTR_SUBU "%[tmp1], %[c_low], %[tmp1] \n\t"
212 "movz %[c_low], %[tmp1], %[tmp0] \n\t"
213 PTR_SUBU "%[tmp1], %[zero], %[res] \n\t"
214 "movn %[res], %[tmp1], %[tmp0] \n\t"
215 : [tmp0]"=&r"(tmp0), [tmp1]"=&r"(tmp1), [res]"+&r"(res),
216 [c_range]"+&r"(c->range), [c_low]"+&r"(c->low),
217 [c_bytestream]"+&r"(c->bytestream)
218 : [cabac_mask]"r"(CABAC_MASK),
219 #if !UNCHECKED_BITSTREAM_READER
220 [c_bytestream_end]"r"(c->bytestream_end),
221 #endif
222 [zero]"r"(0x0)
223 : "memory"
224 );
225
226 return res;
227 }
228 #endif /* AVCODEC_MIPS_CABAC_H */
229