avcodec/mips: MSA (MIPS-SIMD-Arch) optimizations for HEVC horizontal and vertical...
[ffmpeg.git] / libavutil / mips / generic_macros_msa.h
1 /*
2  * Copyright (c) 2015 Manojkumar Bhosale (Manojkumar.Bhosale@imgtec.com)
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg 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  * FFmpeg 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 FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20
21 #ifndef AVUTIL_MIPS_GENERIC_MACROS_MSA_H
22 #define AVUTIL_MIPS_GENERIC_MACROS_MSA_H
23
24 #include <stdint.h>
25 #include <msa.h>
26
27 #define LOAD_UB(psrc)             \
28 ( {                               \
29     v16u8 out_m;                  \
30     out_m = *((v16u8 *) (psrc));  \
31     out_m;                        \
32 } )
33
34 #define LOAD_SB(psrc)             \
35 ( {                               \
36     v16i8 out_m;                  \
37     out_m = *((v16i8 *) (psrc));  \
38     out_m;                        \
39 } )
40
41 #define LOAD_SH(psrc)             \
42 ( {                               \
43     v8i16 out_m;                  \
44     out_m = *((v8i16 *) (psrc));  \
45     out_m;                        \
46 } )
47
48 #define STORE_SH(vec, pdest)       \
49 {                                  \
50     *((v8i16 *) (pdest)) = (vec);  \
51 }
52
53 #if (__mips_isa_rev >= 6)
54     #define STORE_DWORD(pdst, val)                \
55     {                                             \
56         uint8_t *dst_ptr_m = (uint8_t *) (pdst);  \
57         uint64_t val_m = (val);                   \
58                                                   \
59         __asm__ __volatile__ (                    \
60             "sd  %[val_m],  %[dst_ptr_m]  \n\t"   \
61                                                   \
62             : [dst_ptr_m] "=m" (*dst_ptr_m)       \
63             : [val_m] "r" (val_m)                 \
64         );                                        \
65     }
66 #else
67     #define STORE_DWORD(pdst, val)                                 \
68     {                                                              \
69         uint8_t *dst1_m = (uint8_t *) (pdst);                      \
70         uint8_t *dst2_m = ((uint8_t *) (pdst)) + 4;                \
71         uint32_t val0_m, val1_m;                                   \
72                                                                    \
73         val0_m = (uint32_t) ((val) & 0x00000000FFFFFFFF);          \
74         val1_m = (uint32_t) (((val) >> 32) & 0x00000000FFFFFFFF);  \
75                                                                    \
76         __asm__ __volatile__ (                                     \
77             "usw  %[val0_m],  %[dst1_m]  \n\t"                     \
78             "usw  %[val1_m],  %[dst2_m]  \n\t"                     \
79                                                                    \
80             : [dst1_m] "=m" (*dst1_m), [dst2_m] "=m" (*dst2_m)     \
81             : [val0_m] "r" (val0_m), [val1_m] "r" (val1_m)         \
82         );                                                         \
83     }
84 #endif
85
86 #define LOAD_4VECS_SB(psrc, stride,            \
87                       val0, val1, val2, val3)  \
88 {                                              \
89     val0 = LOAD_SB(psrc + 0 * stride);         \
90     val1 = LOAD_SB(psrc + 1 * stride);         \
91     val2 = LOAD_SB(psrc + 2 * stride);         \
92     val3 = LOAD_SB(psrc + 3 * stride);         \
93 }
94
95 #define LOAD_7VECS_SB(psrc, stride,            \
96                       val0, val1, val2, val3,  \
97                       val4, val5, val6)        \
98 {                                              \
99     val0 = LOAD_SB((psrc) + 0 * (stride));     \
100     val1 = LOAD_SB((psrc) + 1 * (stride));     \
101     val2 = LOAD_SB((psrc) + 2 * (stride));     \
102     val3 = LOAD_SB((psrc) + 3 * (stride));     \
103     val4 = LOAD_SB((psrc) + 4 * (stride));     \
104     val5 = LOAD_SB((psrc) + 5 * (stride));     \
105     val6 = LOAD_SB((psrc) + 6 * (stride));     \
106 }
107
108 #define LOAD_8VECS_SB(psrc, stride,                 \
109                       out0, out1, out2, out3,       \
110                       out4, out5, out6, out7)       \
111 {                                                   \
112     LOAD_4VECS_SB((psrc), (stride),                 \
113                   (out0), (out1), (out2), (out3));  \
114     LOAD_4VECS_SB((psrc + 4 * stride), (stride),    \
115                   (out4), (out5), (out6), (out7));  \
116 }
117
118 #define ILVR_B_2VECS_SB(in0_r, in1_r, in0_l, in1_l,         \
119                         out0, out1)                         \
120 {                                                           \
121     out0 = __msa_ilvr_b((v16i8) (in0_l), (v16i8) (in0_r));  \
122     out1 = __msa_ilvr_b((v16i8) (in1_l), (v16i8) (in1_r));  \
123 }
124
125 #define ILVR_B_4VECS_SB(in0_r, in1_r, in2_r, in3_r,  \
126                         in0_l, in1_l, in2_l, in3_l,  \
127                         out0, out1, out2, out3)      \
128 {                                                    \
129     ILVR_B_2VECS_SB(in0_r, in1_r, in0_l, in1_l,      \
130                     out0, out1);                     \
131     ILVR_B_2VECS_SB(in2_r, in3_r, in2_l, in3_l,      \
132                     out2, out3);                     \
133 }
134
135 #define ILVR_B_6VECS_SB(in0_r, in1_r, in2_r,     \
136                         in3_r, in4_r, in5_r,     \
137                         in0_l, in1_l, in2_l,     \
138                         in3_l, in4_l, in5_l,     \
139                         out0, out1, out2,        \
140                         out3, out4, out5)        \
141 {                                                \
142     ILVR_B_2VECS_SB(in0_r, in1_r, in0_l, in1_l,  \
143                     out0, out1);                 \
144     ILVR_B_2VECS_SB(in2_r, in3_r, in2_l, in3_l,  \
145                     out2, out3);                 \
146     ILVR_B_2VECS_SB(in4_r, in5_r, in4_l, in5_l,  \
147                     out4, out5);                 \
148 }
149
150 #define ILVR_B_8VECS_SB(in0_r, in1_r, in2_r, in3_r,  \
151                         in4_r, in5_r, in6_r, in7_r,  \
152                         in0_l, in1_l, in2_l, in3_l,  \
153                         in4_l, in5_l, in6_l, in7_l,  \
154                         out0, out1, out2, out3,      \
155                         out4, out5, out6, out7)      \
156 {                                                    \
157     ILVR_B_2VECS_SB(in0_r, in1_r, in0_l, in1_l,      \
158                     out0, out1);                     \
159     ILVR_B_2VECS_SB(in2_r, in3_r, in2_l, in3_l,      \
160                     out2, out3);                     \
161     ILVR_B_2VECS_SB(in4_r, in5_r, in4_l, in5_l,      \
162                     out4, out5);                     \
163     ILVR_B_2VECS_SB(in6_r, in7_r, in6_l, in7_l,      \
164                     out6, out7);                     \
165 }
166
167 #define ILVL_B_2VECS_SB(in0_r, in1_r, in0_l, in1_l,         \
168                         out0, out1)                         \
169 {                                                           \
170     out0 = __msa_ilvl_b((v16i8) (in0_l), (v16i8) (in0_r));  \
171     out1 = __msa_ilvl_b((v16i8) (in1_l), (v16i8) (in1_r));  \
172 }
173
174 #define ILVL_B_4VECS_SB(in0_r, in1_r, in2_r, in3_r,  \
175                         in0_l, in1_l, in2_l, in3_l,  \
176                         out0, out1, out2, out3)      \
177 {                                                    \
178     ILVL_B_2VECS_SB(in0_r, in1_r, in0_l, in1_l,      \
179                     out0, out1);                     \
180     ILVL_B_2VECS_SB(in2_r, in3_r, in2_l, in3_l,      \
181                     out2, out3);                     \
182 }
183
184 #define ILVL_B_6VECS_SB(in0_r, in1_r, in2_r,     \
185                         in3_r, in4_r, in5_r,     \
186                         in0_l, in1_l, in2_l,     \
187                         in3_l, in4_l, in5_l,     \
188                         out0, out1, out2,        \
189                         out3, out4, out5)        \
190 {                                                \
191     ILVL_B_2VECS_SB(in0_r, in1_r, in0_l, in1_l,  \
192                     out0, out1);                 \
193     ILVL_B_2VECS_SB(in2_r, in3_r, in2_l, in3_l,  \
194                     out2, out3);                 \
195     ILVL_B_2VECS_SB(in4_r, in5_r, in4_l, in5_l,  \
196                     out4, out5);                 \
197 }
198
199 #define ILVR_D_2VECS_SB(out0, in0_l, in0_r,                         \
200                         out1, in1_l, in1_r)                         \
201 {                                                                   \
202     out0 = (v16i8) __msa_ilvr_d((v2i64) (in0_l), (v2i64) (in0_r));  \
203     out1 = (v16i8) __msa_ilvr_d((v2i64) (in1_l), (v2i64) (in1_r));  \
204 }
205
206 #define ILVR_D_3VECS_SB(out0, in0_l, in0_r,                         \
207                         out1, in1_l, in1_r,                         \
208                         out2, in2_l, in2_r)                         \
209 {                                                                   \
210     ILVR_D_2VECS_SB(out0, in0_l, in0_r,                             \
211                     out1, in1_l, in1_r);                            \
212     out2 = (v16i8) __msa_ilvr_d((v2i64) (in2_l), (v2i64) (in2_r));  \
213 }
214
215 #define ILVR_D_4VECS_SB(out0, in0_l, in0_r,  \
216                         out1, in1_l, in1_r,  \
217                         out2, in2_l, in2_r,  \
218                         out3, in3_l, in3_r)  \
219 {                                            \
220     ILVR_D_2VECS_SB(out0, in0_l, in0_r,      \
221                     out1, in1_l, in1_r);     \
222     ILVR_D_2VECS_SB(out2, in2_l, in2_r,      \
223                     out3, in3_l, in3_r);     \
224 }
225
226 #define XORI_B_2VECS_SB(val0, val1,                          \
227                         out0, out1, xor_val)                 \
228 {                                                            \
229     out0 = (v16i8) __msa_xori_b((v16u8) (val0), (xor_val));  \
230     out1 = (v16i8) __msa_xori_b((v16u8) (val1), (xor_val));  \
231 }
232
233 #define XORI_B_3VECS_SB(val0, val1, val2,                    \
234                         out0, out1, out2,                    \
235                         xor_val)                             \
236 {                                                            \
237     XORI_B_2VECS_SB(val0, val1,                              \
238                     out0, out1, xor_val);                    \
239     out2 = (v16i8) __msa_xori_b((v16u8) (val2), (xor_val));  \
240 }
241
242 #define XORI_B_4VECS_SB(val0, val1, val2, val3,  \
243                         out0, out1, out2, out3,  \
244                         xor_val)                 \
245 {                                                \
246     XORI_B_2VECS_SB(val0, val1,                  \
247                     out0, out1, xor_val);        \
248     XORI_B_2VECS_SB(val2, val3,                  \
249                     out2, out3, xor_val);        \
250 }
251
252 #define XORI_B_5VECS_SB(val0, val1, val2, val3, val4,  \
253                         out0, out1, out2, out3, out4,  \
254                         xor_val)                       \
255 {                                                      \
256     XORI_B_3VECS_SB(val0, val1, val2,                  \
257                     out0, out1, out2, xor_val);        \
258     XORI_B_2VECS_SB(val3, val4,                        \
259                     out3, out4, xor_val);              \
260 }
261
262 #define XORI_B_7VECS_SB(val0, val1, val2, val3,        \
263                         val4, val5, val6,              \
264                         out0, out1, out2, out3,        \
265                         out4, out5, out6,              \
266                         xor_val)                       \
267 {                                                      \
268     XORI_B_4VECS_SB(val0, val1, val2, val3,            \
269                     out0, out1, out2, out3, xor_val);  \
270     XORI_B_3VECS_SB(val4, val5, val6,                  \
271                     out4, out5, out6, xor_val);        \
272 }
273
274 #define XORI_B_8VECS_SB(val0, val1, val2, val3,           \
275                         val4, val5, val6, val7,           \
276                         out0, out1, out2, out3,           \
277                         out4, out5, out6, out7, xor_val)  \
278 {                                                         \
279     XORI_B_4VECS_SB(val0, val1, val2, val3,               \
280                     out0, out1, out2, out3, xor_val);     \
281     XORI_B_4VECS_SB(val4, val5, val6, val7,               \
282                     out4, out5, out6, out7, xor_val);     \
283 }
284
285 #endif  /* AVUTIL_MIPS_GENERIC_MACROS_MSA_H */