]> git.sesse.net Git - ffmpeg/blob - libavutil/mips/generic_macros_msa.h
avcodec/mips: Improve hevc uni-w copy mc msa functions
[ffmpeg] / 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 ALIGNMENT           16
28 #define ALLOC_ALIGNED(align) __attribute__ ((aligned((align) << 1)))
29
30 #define LD_V(RTYPE, psrc) *((RTYPE *)(psrc))
31 #define LD_UB(...) LD_V(v16u8, __VA_ARGS__)
32 #define LD_SB(...) LD_V(v16i8, __VA_ARGS__)
33 #define LD_UH(...) LD_V(v8u16, __VA_ARGS__)
34 #define LD_SH(...) LD_V(v8i16, __VA_ARGS__)
35 #define LD_UW(...) LD_V(v4u32, __VA_ARGS__)
36 #define LD_SW(...) LD_V(v4i32, __VA_ARGS__)
37
38 #define ST_V(RTYPE, in, pdst) *((RTYPE *)(pdst)) = (in)
39 #define ST_UB(...) ST_V(v16u8, __VA_ARGS__)
40 #define ST_SB(...) ST_V(v16i8, __VA_ARGS__)
41 #define ST_UH(...) ST_V(v8u16, __VA_ARGS__)
42 #define ST_SH(...) ST_V(v8i16, __VA_ARGS__)
43 #define ST_UW(...) ST_V(v4u32, __VA_ARGS__)
44 #define ST_SW(...) ST_V(v4i32, __VA_ARGS__)
45
46 #if (__mips_isa_rev >= 6)
47     #define LH(psrc)                              \
48     ( {                                           \
49         uint16_t val_lh_m = *(uint16_t *)(psrc);  \
50         val_lh_m;                                 \
51     } )
52
53     #define LW(psrc)                              \
54     ( {                                           \
55         uint32_t val_lw_m = *(uint32_t *)(psrc);  \
56         val_lw_m;                                 \
57     } )
58
59     #if (__mips == 64)
60         #define LD(psrc)                               \
61         ( {                                            \
62             uint64_t val_ld_m =  *(uint64_t *)(psrc);  \
63             val_ld_m;                                  \
64         } )
65     #else  // !(__mips == 64)
66         #define LD(psrc)                                                    \
67         ( {                                                                 \
68             uint8_t *psrc_ld_m = (uint8_t *) (psrc);                        \
69             uint32_t val0_ld_m, val1_ld_m;                                  \
70             uint64_t val_ld_m = 0;                                          \
71                                                                             \
72             val0_ld_m = LW(psrc_ld_m);                                      \
73             val1_ld_m = LW(psrc_ld_m + 4);                                  \
74                                                                             \
75             val_ld_m = (uint64_t) (val1_ld_m);                              \
76             val_ld_m = (uint64_t) ((val_ld_m << 32) & 0xFFFFFFFF00000000);  \
77             val_ld_m = (uint64_t) (val_ld_m | (uint64_t) val0_ld_m);        \
78                                                                             \
79             val_ld_m;                                                       \
80         } )
81     #endif  // (__mips == 64)
82
83     #define SH(val, pdst)  *(uint16_t *)(pdst) = (val);
84     #define SW(val, pdst)  *(uint32_t *)(pdst) = (val);
85     #define SD(val, pdst)  *(uint64_t *)(pdst) = (val);
86
87 #else  // !(__mips_isa_rev >= 6)
88     #define LH(psrc)                                 \
89     ( {                                              \
90         uint8_t *psrc_lh_m = (uint8_t *) (psrc);     \
91         uint16_t val_lh_m;                           \
92                                                      \
93         __asm__ volatile (                           \
94             "ulh  %[val_lh_m],  %[psrc_lh_m]  \n\t"  \
95                                                      \
96             : [val_lh_m] "=r" (val_lh_m)             \
97             : [psrc_lh_m] "m" (*psrc_lh_m)           \
98         );                                           \
99                                                      \
100         val_lh_m;                                    \
101     } )
102
103     #define LW(psrc)                                 \
104     ( {                                              \
105         uint8_t *psrc_lw_m = (uint8_t *) (psrc);     \
106         uint32_t val_lw_m;                           \
107                                                      \
108         __asm__ volatile (                           \
109             "ulw  %[val_lw_m],  %[psrc_lw_m]  \n\t"  \
110                                                      \
111             : [val_lw_m] "=r" (val_lw_m)             \
112             : [psrc_lw_m] "m" (*psrc_lw_m)           \
113         );                                           \
114                                                      \
115         val_lw_m;                                    \
116     } )
117
118     #if (__mips == 64)
119         #define LD(psrc)                                 \
120         ( {                                              \
121             uint8_t *psrc_ld_m = (uint8_t *) (psrc);     \
122             uint64_t val_ld_m = 0;                       \
123                                                          \
124             __asm__ volatile (                           \
125                 "uld  %[val_ld_m],  %[psrc_ld_m]  \n\t"  \
126                                                          \
127                 : [val_ld_m] "=r" (val_ld_m)             \
128                 : [psrc_ld_m] "m" (*psrc_ld_m)           \
129             );                                           \
130                                                          \
131             val_ld_m;                                    \
132         } )
133     #else  // !(__mips == 64)
134         #define LD(psrc)                                                    \
135         ( {                                                                 \
136             uint8_t *psrc_ld_m = (uint8_t *) (psrc);                        \
137             uint32_t val0_ld_m, val1_ld_m;                                  \
138             uint64_t val_ld_m = 0;                                          \
139                                                                             \
140             val0_ld_m = LW(psrc_ld_m);                                      \
141             val1_ld_m = LW(psrc_ld_m + 4);                                  \
142                                                                             \
143             val_ld_m = (uint64_t) (val1_ld_m);                              \
144             val_ld_m = (uint64_t) ((val_ld_m << 32) & 0xFFFFFFFF00000000);  \
145             val_ld_m = (uint64_t) (val_ld_m | (uint64_t) val0_ld_m);        \
146                                                                             \
147             val_ld_m;                                                       \
148         } )
149     #endif  // (__mips == 64)
150
151     #define SH(val, pdst)                            \
152     {                                                \
153         uint8_t *pdst_sh_m = (uint8_t *) (pdst);     \
154         uint16_t val_sh_m = (val);                   \
155                                                      \
156         __asm__ volatile (                           \
157             "ush  %[val_sh_m],  %[pdst_sh_m]  \n\t"  \
158                                                      \
159             : [pdst_sh_m] "=m" (*pdst_sh_m)          \
160             : [val_sh_m] "r" (val_sh_m)              \
161         );                                           \
162     }
163
164     #define SW(val, pdst)                            \
165     {                                                \
166         uint8_t *pdst_sw_m = (uint8_t *) (pdst);     \
167         uint32_t val_sw_m = (val);                   \
168                                                      \
169         __asm__ volatile (                           \
170             "usw  %[val_sw_m],  %[pdst_sw_m]  \n\t"  \
171                                                      \
172             : [pdst_sw_m] "=m" (*pdst_sw_m)          \
173             : [val_sw_m] "r" (val_sw_m)              \
174         );                                           \
175     }
176
177     #define SD(val, pdst)                                             \
178     {                                                                 \
179         uint8_t *pdst_sd_m = (uint8_t *) (pdst);                      \
180         uint32_t val0_sd_m, val1_sd_m;                                \
181                                                                       \
182         val0_sd_m = (uint32_t) ((val) & 0x00000000FFFFFFFF);          \
183         val1_sd_m = (uint32_t) (((val) >> 32) & 0x00000000FFFFFFFF);  \
184                                                                       \
185         SW(val0_sd_m, pdst_sd_m);                                     \
186         SW(val1_sd_m, pdst_sd_m + 4);                                 \
187     }
188 #endif // (__mips_isa_rev >= 6)
189
190 /* Description : Load 4 words with stride
191    Arguments   : Inputs  - psrc    (source pointer to load from)
192                          - stride
193                  Outputs - out0, out1, out2, out3
194    Details     : Loads word in 'out0' from (psrc)
195                  Loads word in 'out1' from (psrc + stride)
196                  Loads word in 'out2' from (psrc + 2 * stride)
197                  Loads word in 'out3' from (psrc + 3 * stride)
198 */
199 #define LW4(psrc, stride, out0, out1, out2, out3)  \
200 {                                                  \
201     out0 = LW((psrc));                             \
202     out1 = LW((psrc) + stride);                    \
203     out2 = LW((psrc) + 2 * stride);                \
204     out3 = LW((psrc) + 3 * stride);                \
205 }
206
207 #define LW2(psrc, stride, out0, out1)  \
208 {                                      \
209     out0 = LW((psrc));                 \
210     out1 = LW((psrc) + stride);        \
211 }
212
213 /* Description : Load double words with stride
214    Arguments   : Inputs  - psrc    (source pointer to load from)
215                          - stride
216                  Outputs - out0, out1
217    Details     : Loads double word in 'out0' from (psrc)
218                  Loads double word in 'out1' from (psrc + stride)
219 */
220 #define LD2(psrc, stride, out0, out1)  \
221 {                                      \
222     out0 = LD((psrc));                 \
223     out1 = LD((psrc) + stride);        \
224 }
225 #define LD4(psrc, stride, out0, out1, out2, out3)  \
226 {                                                  \
227     LD2((psrc), stride, out0, out1);               \
228     LD2((psrc) + 2 * stride, stride, out2, out3);  \
229 }
230
231 /* Description : Store 4 words with stride
232    Arguments   : Inputs  - in0, in1, in2, in3, pdst, stride
233    Details     : Stores word from 'in0' to (pdst)
234                  Stores word from 'in1' to (pdst + stride)
235                  Stores word from 'in2' to (pdst + 2 * stride)
236                  Stores word from 'in3' to (pdst + 3 * stride)
237 */
238 #define SW4(in0, in1, in2, in3, pdst, stride)  \
239 {                                              \
240     SW(in0, (pdst))                            \
241     SW(in1, (pdst) + stride);                  \
242     SW(in2, (pdst) + 2 * stride);              \
243     SW(in3, (pdst) + 3 * stride);              \
244 }
245
246 /* Description : Store 4 double words with stride
247    Arguments   : Inputs  - in0, in1, in2, in3, pdst, stride
248    Details     : Stores double word from 'in0' to (pdst)
249                  Stores double word from 'in1' to (pdst + stride)
250                  Stores double word from 'in2' to (pdst + 2 * stride)
251                  Stores double word from 'in3' to (pdst + 3 * stride)
252 */
253 #define SD4(in0, in1, in2, in3, pdst, stride)  \
254 {                                              \
255     SD(in0, (pdst))                            \
256     SD(in1, (pdst) + stride);                  \
257     SD(in2, (pdst) + 2 * stride);              \
258     SD(in3, (pdst) + 3 * stride);              \
259 }
260
261 /* Description : Load vector elements with stride
262    Arguments   : Inputs  - psrc    (source pointer to load from)
263                          - stride
264                  Outputs - out0, out1
265                  Return Type - as per RTYPE
266    Details     : Loads elements in 'out0' from (psrc)
267                  Loads elements in 'out1' from (psrc + stride)
268 */
269 #define LD_V2(RTYPE, psrc, stride, out0, out1)  \
270 {                                               \
271     out0 = LD_V(RTYPE, (psrc));                 \
272     out1 = LD_V(RTYPE, (psrc) + stride);        \
273 }
274 #define LD_UB2(...) LD_V2(v16u8, __VA_ARGS__)
275 #define LD_SB2(...) LD_V2(v16i8, __VA_ARGS__)
276 #define LD_UH2(...) LD_V2(v8u16, __VA_ARGS__)
277 #define LD_SH2(...) LD_V2(v8i16, __VA_ARGS__)
278 #define LD_SW2(...) LD_V2(v4i32, __VA_ARGS__)
279
280 #define LD_V3(RTYPE, psrc, stride, out0, out1, out2)  \
281 {                                                     \
282     LD_V2(RTYPE, (psrc), stride, out0, out1);         \
283     out2 = LD_V(RTYPE, (psrc) + 2 * stride);          \
284 }
285 #define LD_UB3(...) LD_V3(v16u8, __VA_ARGS__)
286 #define LD_SB3(...) LD_V3(v16i8, __VA_ARGS__)
287
288 #define LD_V4(RTYPE, psrc, stride, out0, out1, out2, out3)   \
289 {                                                            \
290     LD_V2(RTYPE, (psrc), stride, out0, out1);                \
291     LD_V2(RTYPE, (psrc) + 2 * stride , stride, out2, out3);  \
292 }
293 #define LD_UB4(...) LD_V4(v16u8, __VA_ARGS__)
294 #define LD_SB4(...) LD_V4(v16i8, __VA_ARGS__)
295 #define LD_UH4(...) LD_V4(v8u16, __VA_ARGS__)
296 #define LD_SH4(...) LD_V4(v8i16, __VA_ARGS__)
297
298 #define LD_V5(RTYPE, psrc, stride, out0, out1, out2, out3, out4)  \
299 {                                                                 \
300     LD_V4(RTYPE, (psrc), stride, out0, out1, out2, out3);         \
301     out4 = LD_V(RTYPE, (psrc) + 4 * stride);                      \
302 }
303 #define LD_UB5(...) LD_V5(v16u8, __VA_ARGS__)
304 #define LD_SB5(...) LD_V5(v16i8, __VA_ARGS__)
305
306 #define LD_V6(RTYPE, psrc, stride, out0, out1, out2, out3, out4, out5)  \
307 {                                                                       \
308     LD_V4(RTYPE, (psrc), stride, out0, out1, out2, out3);               \
309     LD_V2(RTYPE, (psrc) + 4 * stride, stride, out4, out5);              \
310 }
311 #define LD_UB6(...) LD_V6(v16u8, __VA_ARGS__)
312 #define LD_SB6(...) LD_V6(v16i8, __VA_ARGS__)
313 #define LD_UH6(...) LD_V6(v8u16, __VA_ARGS__)
314 #define LD_SH6(...) LD_V6(v8i16, __VA_ARGS__)
315
316 #define LD_V7(RTYPE, psrc, stride,                               \
317               out0, out1, out2, out3, out4, out5, out6)          \
318 {                                                                \
319     LD_V5(RTYPE, (psrc), stride, out0, out1, out2, out3, out4);  \
320     LD_V2(RTYPE, (psrc) + 5 * stride, stride, out5, out6);       \
321 }
322 #define LD_UB7(...) LD_V7(v16u8, __VA_ARGS__)
323 #define LD_SB7(...) LD_V7(v16i8, __VA_ARGS__)
324
325 #define LD_V8(RTYPE, psrc, stride,                                      \
326               out0, out1, out2, out3, out4, out5, out6, out7)           \
327 {                                                                       \
328     LD_V4(RTYPE, (psrc), stride, out0, out1, out2, out3);               \
329     LD_V4(RTYPE, (psrc) + 4 * stride, stride, out4, out5, out6, out7);  \
330 }
331 #define LD_UB8(...) LD_V8(v16u8, __VA_ARGS__)
332 #define LD_SB8(...) LD_V8(v16i8, __VA_ARGS__)
333 #define LD_UH8(...) LD_V8(v8u16, __VA_ARGS__)
334 #define LD_SH8(...) LD_V8(v8i16, __VA_ARGS__)
335
336 #define LD_V16(RTYPE, psrc, stride,                                   \
337                out0, out1, out2, out3, out4, out5, out6, out7,        \
338                out8, out9, out10, out11, out12, out13, out14, out15)  \
339 {                                                                     \
340     LD_V8(RTYPE, (psrc), stride,                                      \
341           out0, out1, out2, out3, out4, out5, out6, out7);            \
342     LD_V8(RTYPE, (psrc) + 8 * stride, stride,                         \
343           out8, out9, out10, out11, out12, out13, out14, out15);      \
344 }
345 #define LD_SH16(...) LD_V16(v8i16, __VA_ARGS__)
346
347 /* Description : Load as 4x4 block of signed halfword elements from 1D source
348                  data into 4 vectors (Each vector with 4 signed halfwords)
349    Arguments   : Inputs  - psrc
350                  Outputs - out0, out1, out2, out3
351 */
352 #define LD4x4_SH(psrc, out0, out1, out2, out3)                \
353 {                                                             \
354     out0 = LD_SH(psrc);                                       \
355     out2 = LD_SH(psrc + 8);                                   \
356     out1 = (v8i16) __msa_ilvl_d((v2i64) out0, (v2i64) out0);  \
357     out3 = (v8i16) __msa_ilvl_d((v2i64) out2, (v2i64) out2);  \
358 }
359
360 /* Description : Store vectors with stride
361    Arguments   : Inputs  - in0, in1, stride
362                  Outputs - pdst    (destination pointer to store to)
363    Details     : Stores elements from 'in0' to (pdst)
364                  Stores elements from 'in1' to (pdst + stride)
365 */
366 #define ST_V2(RTYPE, in0, in1, pdst, stride)  \
367 {                                             \
368     ST_V(RTYPE, in0, (pdst));                 \
369     ST_V(RTYPE, in1, (pdst) + stride);        \
370 }
371 #define ST_UB2(...) ST_V2(v16u8, __VA_ARGS__)
372 #define ST_SB2(...) ST_V2(v16i8, __VA_ARGS__)
373 #define ST_UH2(...) ST_V2(v8u16, __VA_ARGS__)
374 #define ST_SH2(...) ST_V2(v8i16, __VA_ARGS__)
375 #define ST_SW2(...) ST_V2(v4i32, __VA_ARGS__)
376
377 #define ST_V4(RTYPE, in0, in1, in2, in3, pdst, stride)    \
378 {                                                         \
379     ST_V2(RTYPE, in0, in1, (pdst), stride);               \
380     ST_V2(RTYPE, in2, in3, (pdst) + 2 * stride, stride);  \
381 }
382 #define ST_UB4(...) ST_V4(v16u8, __VA_ARGS__)
383 #define ST_SB4(...) ST_V4(v16i8, __VA_ARGS__)
384 #define ST_SH4(...) ST_V4(v8i16, __VA_ARGS__)
385 #define ST_SW4(...) ST_V4(v4i32, __VA_ARGS__)
386
387 #define ST_V6(RTYPE, in0, in1, in2, in3, in4, in5, pdst, stride)  \
388 {                                                                 \
389     ST_V4(RTYPE, in0, in1, in2, in3, (pdst), stride);             \
390     ST_V2(RTYPE, in4, in5, (pdst) + 4 * stride, stride);          \
391 }
392 #define ST_SH6(...) ST_V6(v8i16, __VA_ARGS__)
393
394 #define ST_V8(RTYPE, in0, in1, in2, in3, in4, in5, in6, in7, pdst, stride)  \
395 {                                                                           \
396     ST_V4(RTYPE, in0, in1, in2, in3, (pdst), stride);                       \
397     ST_V4(RTYPE, in4, in5, in6, in7, (pdst) + 4 * stride, stride);          \
398 }
399 #define ST_UB8(...) ST_V8(v16u8, __VA_ARGS__)
400 #define ST_SH8(...) ST_V8(v8i16, __VA_ARGS__)
401 #define ST_SW8(...) ST_V8(v4i32, __VA_ARGS__)
402
403 /* Description : Store as 2x4 byte block to destination memory from input vector
404    Arguments   : Inputs  - in, stidx, pdst, stride
405                  Return Type - unsigned byte
406    Details     : Index stidx halfword element from 'in' vector is copied and
407                  stored on first line
408                  Index stidx+1 halfword element from 'in' vector is copied and
409                  stored on second line
410                  Index stidx+2 halfword element from 'in' vector is copied and
411                  stored on third line
412                  Index stidx+3 halfword element from 'in' vector is copied and
413                  stored on fourth line
414 */
415 #define ST2x4_UB(in, stidx, pdst, stride)              \
416 {                                                      \
417     uint16_t out0_m, out1_m, out2_m, out3_m;           \
418     uint8_t *pblk_2x4_m = (uint8_t *) (pdst);          \
419                                                        \
420     out0_m = __msa_copy_u_h((v8i16) in, (stidx));      \
421     out1_m = __msa_copy_u_h((v8i16) in, (stidx + 1));  \
422     out2_m = __msa_copy_u_h((v8i16) in, (stidx + 2));  \
423     out3_m = __msa_copy_u_h((v8i16) in, (stidx + 3));  \
424                                                        \
425     SH(out0_m, pblk_2x4_m);                            \
426     SH(out1_m, pblk_2x4_m + stride);                   \
427     SH(out2_m, pblk_2x4_m + 2 * stride);               \
428     SH(out3_m, pblk_2x4_m + 3 * stride);               \
429 }
430
431 /* Description : Store as 4x2 byte block to destination memory from input vector
432    Arguments   : Inputs  - in, pdst, stride
433                  Return Type - unsigned byte
434    Details     : Index 0 word element from input vector is copied and stored
435                  on first line
436                  Index 1 word element from input vector is copied and stored
437                  on second line
438 */
439 #define ST4x2_UB(in, pdst, stride)             \
440 {                                              \
441     uint32_t out0_m, out1_m;                   \
442     uint8_t *pblk_4x2_m = (uint8_t *) (pdst);  \
443                                                \
444     out0_m = __msa_copy_u_w((v4i32) in, 0);    \
445     out1_m = __msa_copy_u_w((v4i32) in, 1);    \
446                                                \
447     SW(out0_m, pblk_4x2_m);                    \
448     SW(out1_m, pblk_4x2_m + stride);           \
449 }
450
451 /* Description : Store as 4x4 byte block to destination memory from input vector
452    Arguments   : Inputs  - in0, in1, pdst, stride
453                  Return Type - unsigned byte
454    Details     : Idx0 word element from input vector 'in0' is copied and stored
455                  on first line
456                  Idx1 word element from input vector 'in0' is copied and stored
457                  on second line
458                  Idx2 word element from input vector 'in1' is copied and stored
459                  on third line
460                  Idx3 word element from input vector 'in1' is copied and stored
461                  on fourth line
462 */
463 #define ST4x4_UB(in0, in1, idx0, idx1, idx2, idx3, pdst, stride)  \
464 {                                                                 \
465     uint32_t out0_m, out1_m, out2_m, out3_m;                      \
466     uint8_t *pblk_4x4_m = (uint8_t *) (pdst);                     \
467                                                                   \
468     out0_m = __msa_copy_u_w((v4i32) in0, idx0);                   \
469     out1_m = __msa_copy_u_w((v4i32) in0, idx1);                   \
470     out2_m = __msa_copy_u_w((v4i32) in1, idx2);                   \
471     out3_m = __msa_copy_u_w((v4i32) in1, idx3);                   \
472                                                                   \
473     SW4(out0_m, out1_m, out2_m, out3_m, pblk_4x4_m, stride);      \
474 }
475 #define ST4x8_UB(in0, in1, pdst, stride)                            \
476 {                                                                   \
477     uint8_t *pblk_4x8 = (uint8_t *) (pdst);                         \
478                                                                     \
479     ST4x4_UB(in0, in0, 0, 1, 2, 3, pblk_4x8, stride);               \
480     ST4x4_UB(in1, in1, 0, 1, 2, 3, pblk_4x8 + 4 * stride, stride);  \
481 }
482
483 /* Description : Store as 6x4 byte block to destination memory from input
484                  vectors
485    Arguments   : Inputs  - in0, in1, pdst, stride
486                  Return Type - unsigned byte
487    Details     : Index 0 word element from input vector 'in0' is copied and
488                  stored on first line followed by index 2 halfword element
489                  Index 2 word element from input vector 'in0' is copied and
490                  stored on second line followed by index 2 halfword element
491                  Index 0 word element from input vector 'in1' is copied and
492                  stored on third line followed by index 2 halfword element
493                  Index 2 word element from input vector 'in1' is copied and
494                  stored on fourth line followed by index 2 halfword element
495 */
496 #define ST6x4_UB(in0, in1, pdst, stride)       \
497 {                                              \
498     uint32_t out0_m, out1_m, out2_m, out3_m;   \
499     uint16_t out4_m, out5_m, out6_m, out7_m;   \
500     uint8_t *pblk_6x4_m = (uint8_t *) (pdst);  \
501                                                \
502     out0_m = __msa_copy_u_w((v4i32) in0, 0);   \
503     out1_m = __msa_copy_u_w((v4i32) in0, 2);   \
504     out2_m = __msa_copy_u_w((v4i32) in1, 0);   \
505     out3_m = __msa_copy_u_w((v4i32) in1, 2);   \
506                                                \
507     out4_m = __msa_copy_u_h((v8i16) in0, 2);   \
508     out5_m = __msa_copy_u_h((v8i16) in0, 6);   \
509     out6_m = __msa_copy_u_h((v8i16) in1, 2);   \
510     out7_m = __msa_copy_u_h((v8i16) in1, 6);   \
511                                                \
512     SW(out0_m, pblk_6x4_m);                    \
513     SH(out4_m, (pblk_6x4_m + 4));              \
514     pblk_6x4_m += stride;                      \
515     SW(out1_m, pblk_6x4_m);                    \
516     SH(out5_m, (pblk_6x4_m + 4));              \
517     pblk_6x4_m += stride;                      \
518     SW(out2_m, pblk_6x4_m);                    \
519     SH(out6_m, (pblk_6x4_m + 4));              \
520     pblk_6x4_m += stride;                      \
521     SW(out3_m, pblk_6x4_m);                    \
522     SH(out7_m, (pblk_6x4_m + 4));              \
523 }
524
525 /* Description : Store as 8x1 byte block to destination memory from input vector
526    Arguments   : Inputs  - in, pdst
527    Details     : Index 0 double word element from input vector 'in' is copied
528                  and stored to destination memory at (pdst)
529 */
530 #define ST8x1_UB(in, pdst)                   \
531 {                                            \
532     uint64_t out0_m;                         \
533     out0_m = __msa_copy_u_d((v2i64) in, 0);  \
534     SD(out0_m, pdst);                        \
535 }
536
537 /* Description : Store as 8x2 byte block to destination memory from input vector
538    Arguments   : Inputs  - in, pdst, stride
539    Details     : Index 0 double word element from input vector 'in' is copied
540                  and stored to destination memory at (pdst)
541                  Index 1 double word element from input vector 'in' is copied
542                  and stored to destination memory at (pdst + stride)
543 */
544 #define ST8x2_UB(in, pdst, stride)             \
545 {                                              \
546     uint64_t out0_m, out1_m;                   \
547     uint8_t *pblk_8x2_m = (uint8_t *) (pdst);  \
548                                                \
549     out0_m = __msa_copy_u_d((v2i64) in, 0);    \
550     out1_m = __msa_copy_u_d((v2i64) in, 1);    \
551                                                \
552     SD(out0_m, pblk_8x2_m);                    \
553     SD(out1_m, pblk_8x2_m + stride);           \
554 }
555
556 /* Description : Store as 8x4 byte block to destination memory from input
557                  vectors
558    Arguments   : Inputs  - in0, in1, pdst, stride
559    Details     : Index 0 double word element from input vector 'in0' is copied
560                  and stored to destination memory at (pblk_8x4_m)
561                  Index 1 double word element from input vector 'in0' is copied
562                  and stored to destination memory at (pblk_8x4_m + stride)
563                  Index 0 double word element from input vector 'in1' is copied
564                  and stored to destination memory at (pblk_8x4_m + 2 * stride)
565                  Index 1 double word element from input vector 'in1' is copied
566                  and stored to destination memory at (pblk_8x4_m + 3 * stride)
567 */
568 #define ST8x4_UB(in0, in1, pdst, stride)                      \
569 {                                                             \
570     uint64_t out0_m, out1_m, out2_m, out3_m;                  \
571     uint8_t *pblk_8x4_m = (uint8_t *) (pdst);                 \
572                                                               \
573     out0_m = __msa_copy_u_d((v2i64) in0, 0);                  \
574     out1_m = __msa_copy_u_d((v2i64) in0, 1);                  \
575     out2_m = __msa_copy_u_d((v2i64) in1, 0);                  \
576     out3_m = __msa_copy_u_d((v2i64) in1, 1);                  \
577                                                               \
578     SD4(out0_m, out1_m, out2_m, out3_m, pblk_8x4_m, stride);  \
579 }
580 #define ST8x8_UB(in0, in1, in2, in3, pdst, stride)        \
581 {                                                         \
582     uint8_t *pblk_8x8_m = (uint8_t *) (pdst);             \
583                                                           \
584     ST8x4_UB(in0, in1, pblk_8x8_m, stride);               \
585     ST8x4_UB(in2, in3, pblk_8x8_m + 4 * stride, stride);  \
586 }
587 #define ST12x4_UB(in0, in1, in2, pdst, stride)                \
588 {                                                             \
589     uint8_t *pblk_12x4_m = (uint8_t *) (pdst);                \
590                                                               \
591     /* left 8x4 */                                            \
592     ST8x4_UB(in0, in1, pblk_12x4_m, stride);                  \
593     /* right 4x4 */                                           \
594     ST4x4_UB(in2, in2, 0, 1, 2, 3, pblk_12x4_m + 8, stride);  \
595 }
596
597 /* Description : Store as 12x8 byte block to destination memory from
598                  input vectors
599    Arguments   : Inputs  - in0, in1, in2, in3, in4, in5, in6, in7, pdst, stride
600    Details     : Index 0 double word element from input vector 'in0' is copied
601                  and stored to destination memory at (pblk_12x8_m) followed by
602                  index 2 word element from same input vector 'in0' at
603                  (pblk_12x8_m + 8)
604                  Similar to remaining lines
605 */
606 #define ST12x8_UB(in0, in1, in2, in3, in4, in5, in6, in7, pdst, stride)  \
607 {                                                                        \
608     uint64_t out0_m, out1_m, out2_m, out3_m;                             \
609     uint64_t out4_m, out5_m, out6_m, out7_m;                             \
610     uint32_t out8_m, out9_m, out10_m, out11_m;                           \
611     uint32_t out12_m, out13_m, out14_m, out15_m;                         \
612     uint8_t *pblk_12x8_m = (uint8_t *) (pdst);                           \
613                                                                          \
614     out0_m = __msa_copy_u_d((v2i64) in0, 0);                             \
615     out1_m = __msa_copy_u_d((v2i64) in1, 0);                             \
616     out2_m = __msa_copy_u_d((v2i64) in2, 0);                             \
617     out3_m = __msa_copy_u_d((v2i64) in3, 0);                             \
618     out4_m = __msa_copy_u_d((v2i64) in4, 0);                             \
619     out5_m = __msa_copy_u_d((v2i64) in5, 0);                             \
620     out6_m = __msa_copy_u_d((v2i64) in6, 0);                             \
621     out7_m = __msa_copy_u_d((v2i64) in7, 0);                             \
622                                                                          \
623     out8_m =  __msa_copy_u_w((v4i32) in0, 2);                            \
624     out9_m =  __msa_copy_u_w((v4i32) in1, 2);                            \
625     out10_m = __msa_copy_u_w((v4i32) in2, 2);                            \
626     out11_m = __msa_copy_u_w((v4i32) in3, 2);                            \
627     out12_m = __msa_copy_u_w((v4i32) in4, 2);                            \
628     out13_m = __msa_copy_u_w((v4i32) in5, 2);                            \
629     out14_m = __msa_copy_u_w((v4i32) in6, 2);                            \
630     out15_m = __msa_copy_u_w((v4i32) in7, 2);                            \
631                                                                          \
632     SD(out0_m, pblk_12x8_m);                                             \
633     SW(out8_m, pblk_12x8_m + 8);                                         \
634     pblk_12x8_m += stride;                                               \
635     SD(out1_m, pblk_12x8_m);                                             \
636     SW(out9_m, pblk_12x8_m + 8);                                         \
637     pblk_12x8_m += stride;                                               \
638     SD(out2_m, pblk_12x8_m);                                             \
639     SW(out10_m, pblk_12x8_m + 8);                                        \
640     pblk_12x8_m += stride;                                               \
641     SD(out3_m, pblk_12x8_m);                                             \
642     SW(out11_m, pblk_12x8_m + 8);                                        \
643     pblk_12x8_m += stride;                                               \
644     SD(out4_m, pblk_12x8_m);                                             \
645     SW(out12_m, pblk_12x8_m + 8);                                        \
646     pblk_12x8_m += stride;                                               \
647     SD(out5_m, pblk_12x8_m);                                             \
648     SW(out13_m, pblk_12x8_m + 8);                                        \
649     pblk_12x8_m += stride;                                               \
650     SD(out6_m, pblk_12x8_m);                                             \
651     SW(out14_m, pblk_12x8_m + 8);                                        \
652     pblk_12x8_m += stride;                                               \
653     SD(out7_m, pblk_12x8_m);                                             \
654     SW(out15_m, pblk_12x8_m + 8);                                        \
655 }
656
657 /* Description : average with rounding (in0 + in1 + 1) / 2.
658    Arguments   : Inputs  - in0, in1, in2, in3,
659                  Outputs - out0, out1
660                  Return Type - as per RTYPE
661    Details     : Each byte element from 'in0' vector is added with each byte
662                  element from 'in1' vector. The addition of the elements plus 1
663                 (for rounding) is done unsigned with full precision,
664                 i.e. the result has one extra bit. Unsigned division by 2
665                 (or logical shift right by one bit) is performed before writing
666                 the result to vector 'out0'
667                 Similar for the pair of 'in2' and 'in3'
668 */
669 #define AVER_UB2(RTYPE, in0, in1, in2, in3, out0, out1)       \
670 {                                                             \
671     out0 = (RTYPE) __msa_aver_u_b((v16u8) in0, (v16u8) in1);  \
672     out1 = (RTYPE) __msa_aver_u_b((v16u8) in2, (v16u8) in3);  \
673 }
674 #define AVER_UB2_UB(...) AVER_UB2(v16u8, __VA_ARGS__)
675
676 #define AVER_UB4(RTYPE, in0, in1, in2, in3, in4, in5, in6, in7, \
677                  out0, out1, out2, out3)                        \
678 {                                                               \
679     AVER_UB2(RTYPE, in0, in1, in2, in3, out0, out1)             \
680     AVER_UB2(RTYPE, in4, in5, in6, in7, out2, out3)             \
681 }
682 #define AVER_UB4_UB(...) AVER_UB4(v16u8, __VA_ARGS__)
683
684 /* Description : Immediate number of columns to slide with zero
685    Arguments   : Inputs  - in0, in1, slide_val
686                  Outputs - out0, out1
687                  Return Type - as per RTYPE
688    Details     : Byte elements from 'zero_m' vector are slide into 'in0' by
689                  number of elements specified by 'slide_val'
690 */
691 #define SLDI_B2_0(RTYPE, in0, in1, out0, out1, slide_val)                 \
692 {                                                                         \
693     v16i8 zero_m = { 0 };                                                 \
694     out0 = (RTYPE) __msa_sldi_b((v16i8) zero_m, (v16i8) in0, slide_val);  \
695     out1 = (RTYPE) __msa_sldi_b((v16i8) zero_m, (v16i8) in1, slide_val);  \
696 }
697 #define SLDI_B2_0_UB(...) SLDI_B2_0(v16u8, __VA_ARGS__)
698 #define SLDI_B2_0_SB(...) SLDI_B2_0(v16i8, __VA_ARGS__)
699 #define SLDI_B2_0_SW(...) SLDI_B2_0(v4i32, __VA_ARGS__)
700
701 #define SLDI_B3_0(RTYPE, in0, in1, in2, out0, out1, out2,  slide_val)     \
702 {                                                                         \
703     v16i8 zero_m = { 0 };                                                 \
704     SLDI_B2_0(RTYPE, in0, in1, out0, out1, slide_val);                    \
705     out2 = (RTYPE) __msa_sldi_b((v16i8) zero_m, (v16i8) in2, slide_val);  \
706 }
707 #define SLDI_B3_0_UB(...) SLDI_B3_0(v16u8, __VA_ARGS__)
708 #define SLDI_B3_0_SB(...) SLDI_B3_0(v16i8, __VA_ARGS__)
709
710 #define SLDI_B4_0(RTYPE, in0, in1, in2, in3,            \
711                   out0, out1, out2, out3, slide_val)    \
712 {                                                       \
713     SLDI_B2_0(RTYPE, in0, in1, out0, out1, slide_val);  \
714     SLDI_B2_0(RTYPE, in2, in3, out2, out3, slide_val);  \
715 }
716 #define SLDI_B4_0_UB(...) SLDI_B4_0(v16u8, __VA_ARGS__)
717 #define SLDI_B4_0_SB(...) SLDI_B4_0(v16i8, __VA_ARGS__)
718 #define SLDI_B4_0_SH(...) SLDI_B4_0(v8i16, __VA_ARGS__)
719
720 /* Description : Immediate number of columns to slide
721    Arguments   : Inputs  - in0_0, in0_1, in1_0, in1_1, slide_val
722                  Outputs - out0, out1
723                  Return Type - as per RTYPE
724    Details     : Byte elements from 'in0_0' vector are slide into 'in1_0' by
725                  number of elements specified by 'slide_val'
726 */
727 #define SLDI_B2(RTYPE, in0_0, in0_1, in1_0, in1_1, out0, out1, slide_val)  \
728 {                                                                          \
729     out0 = (RTYPE) __msa_sldi_b((v16i8) in0_0, (v16i8) in1_0, slide_val);  \
730     out1 = (RTYPE) __msa_sldi_b((v16i8) in0_1, (v16i8) in1_1, slide_val);  \
731 }
732 #define SLDI_B2_UB(...) SLDI_B2(v16u8, __VA_ARGS__)
733 #define SLDI_B2_SB(...) SLDI_B2(v16i8, __VA_ARGS__)
734 #define SLDI_B2_SH(...) SLDI_B2(v8i16, __VA_ARGS__)
735
736 #define SLDI_B3(RTYPE, in0_0, in0_1, in0_2, in1_0, in1_1, in1_2,           \
737                 out0, out1, out2, slide_val)                               \
738 {                                                                          \
739     SLDI_B2(RTYPE, in0_0, in0_1, in1_0, in1_1, out0, out1, slide_val)      \
740     out2 = (RTYPE) __msa_sldi_b((v16i8) in0_2, (v16i8) in1_2, slide_val);  \
741 }
742 #define SLDI_B3_SB(...) SLDI_B3(v16i8, __VA_ARGS__)
743 #define SLDI_B3_UH(...) SLDI_B3(v8u16, __VA_ARGS__)
744
745 /* Description : Shuffle byte vector elements as per mask vector
746    Arguments   : Inputs  - in0, in1, in2, in3, mask0, mask1
747                  Outputs - out0, out1
748                  Return Type - as per RTYPE
749    Details     : Selective byte elements from in0 & in1 are copied to out0 as
750                  per control vector mask0
751                  Selective byte elements from in2 & in3 are copied to out1 as
752                  per control vector mask1
753 */
754 #define VSHF_B2(RTYPE, in0, in1, in2, in3, mask0, mask1, out0, out1)       \
755 {                                                                          \
756     out0 = (RTYPE) __msa_vshf_b((v16i8) mask0, (v16i8) in1, (v16i8) in0);  \
757     out1 = (RTYPE) __msa_vshf_b((v16i8) mask1, (v16i8) in3, (v16i8) in2);  \
758 }
759 #define VSHF_B2_UB(...) VSHF_B2(v16u8, __VA_ARGS__)
760 #define VSHF_B2_SB(...) VSHF_B2(v16i8, __VA_ARGS__)
761 #define VSHF_B2_UH(...) VSHF_B2(v8u16, __VA_ARGS__)
762 #define VSHF_B2_SH(...) VSHF_B2(v8i16, __VA_ARGS__)
763
764 #define VSHF_B3(RTYPE, in0, in1, in2, in3, in4, in5, mask0, mask1, mask2,  \
765                 out0, out1, out2)                                          \
766 {                                                                          \
767     VSHF_B2(RTYPE, in0, in1, in2, in3, mask0, mask1, out0, out1);          \
768     out2 = (RTYPE) __msa_vshf_b((v16i8) mask2, (v16i8) in5, (v16i8) in4);  \
769 }
770 #define VSHF_B3_SB(...) VSHF_B3(v16i8, __VA_ARGS__)
771
772 #define VSHF_B4(RTYPE, in0, in1, mask0, mask1, mask2, mask3,       \
773                 out0, out1, out2, out3)                            \
774 {                                                                  \
775     VSHF_B2(RTYPE, in0, in1, in0, in1, mask0, mask1, out0, out1);  \
776     VSHF_B2(RTYPE, in0, in1, in0, in1, mask2, mask3, out2, out3);  \
777 }
778 #define VSHF_B4_SB(...) VSHF_B4(v16i8, __VA_ARGS__)
779 #define VSHF_B4_SH(...) VSHF_B4(v8i16, __VA_ARGS__)
780
781 /* Description : Shuffle halfword vector elements as per mask vector
782    Arguments   : Inputs  - in0, in1, in2, in3, mask0, mask1
783                  Outputs - out0, out1
784                  Return Type - as per RTYPE
785    Details     : Selective halfword elements from in0 & in1 are copied to out0
786                  as per control vector mask0
787                  Selective halfword elements from in2 & in3 are copied to out1
788                  as per control vector mask1
789 */
790 #define VSHF_H2(RTYPE, in0, in1, in2, in3, mask0, mask1, out0, out1)       \
791 {                                                                          \
792     out0 = (RTYPE) __msa_vshf_h((v8i16) mask0, (v8i16) in1, (v8i16) in0);  \
793     out1 = (RTYPE) __msa_vshf_h((v8i16) mask1, (v8i16) in3, (v8i16) in2);  \
794 }
795 #define VSHF_H2_SH(...) VSHF_H2(v8i16, __VA_ARGS__)
796
797 #define VSHF_H3(RTYPE, in0, in1, in2, in3, in4, in5, mask0, mask1, mask2,  \
798                 out0, out1, out2)                                          \
799 {                                                                          \
800     VSHF_H2(RTYPE, in0, in1, in2, in3, mask0, mask1, out0, out1);          \
801     out2 = (RTYPE) __msa_vshf_h((v8i16) mask2, (v8i16) in5, (v8i16) in4);  \
802 }
803 #define VSHF_H3_SH(...) VSHF_H3(v8i16, __VA_ARGS__)
804
805 /* Description : Shuffle byte vector elements as per mask vector
806    Arguments   : Inputs  - in0, in1, in2, in3, mask0, mask1
807                  Outputs - out0, out1
808                  Return Type - as per RTYPE
809    Details     : Selective byte elements from in0 & in1 are copied to out0 as
810                  per control vector mask0
811                  Selective byte elements from in2 & in3 are copied to out1 as
812                  per control vector mask1
813 */
814 #define VSHF_W2(RTYPE, in0, in1, in2, in3, mask0, mask1, out0, out1)      \
815 {                                                                         \
816     out0 = (RTYPE) __msa_vshf_w((v4i32) mask0, (v4i32) in1, (v4i32) in0); \
817     out1 = (RTYPE) __msa_vshf_w((v4i32) mask1, (v4i32) in3, (v4i32) in2); \
818 }
819 #define VSHF_W2_SB(...) VSHF_W2(v16i8, __VA_ARGS__)
820
821 /* Description : Dot product of byte vector elements
822    Arguments   : Inputs  - mult0, mult1
823                            cnst0, cnst1
824                  Outputs - out0, out1
825                  Return Type - as per RTYPE
826    Details     : Unsigned byte elements from mult0 are multiplied with
827                  unsigned byte elements from cnst0 producing a result
828                  twice the size of input i.e. unsigned halfword.
829                  Then this multiplication results of adjacent odd-even elements
830                  are added together and stored to the out vector
831                  (2 unsigned halfword results)
832 */
833 #define DOTP_UB2(RTYPE, mult0, mult1, cnst0, cnst1, out0, out1)   \
834 {                                                                 \
835     out0 = (RTYPE) __msa_dotp_u_h((v16u8) mult0, (v16u8) cnst0);  \
836     out1 = (RTYPE) __msa_dotp_u_h((v16u8) mult1, (v16u8) cnst1);  \
837 }
838 #define DOTP_UB2_UH(...) DOTP_UB2(v8u16, __VA_ARGS__)
839
840 #define DOTP_UB4(RTYPE, mult0, mult1, mult2, mult3,           \
841                  cnst0, cnst1, cnst2, cnst3,                  \
842                  out0, out1, out2, out3)                      \
843 {                                                             \
844     DOTP_UB2(RTYPE, mult0, mult1, cnst0, cnst1, out0, out1);  \
845     DOTP_UB2(RTYPE, mult2, mult3, cnst2, cnst3, out2, out3);  \
846 }
847 #define DOTP_UB4_UH(...) DOTP_UB4(v8u16, __VA_ARGS__)
848
849 /* Description : Dot product of byte vector elements
850    Arguments   : Inputs  - mult0, mult1
851                            cnst0, cnst1
852                  Outputs - out0, out1
853                  Return Type - as per RTYPE
854    Details     : Signed byte elements from mult0 are multiplied with
855                  signed byte elements from cnst0 producing a result
856                  twice the size of input i.e. signed halfword.
857                  Then this multiplication results of adjacent odd-even elements
858                  are added together and stored to the out vector
859                  (2 signed halfword results)
860 */
861 #define DOTP_SB2(RTYPE, mult0, mult1, cnst0, cnst1, out0, out1)   \
862 {                                                                 \
863     out0 = (RTYPE) __msa_dotp_s_h((v16i8) mult0, (v16i8) cnst0);  \
864     out1 = (RTYPE) __msa_dotp_s_h((v16i8) mult1, (v16i8) cnst1);  \
865 }
866 #define DOTP_SB2_SH(...) DOTP_SB2(v8i16, __VA_ARGS__)
867
868 #define DOTP_SB3(RTYPE, mult0, mult1, mult2, cnst0, cnst1, cnst2,  \
869                  out0, out1, out2)                                 \
870 {                                                                  \
871     DOTP_SB2(RTYPE, mult0, mult1, cnst0, cnst1, out0, out1);       \
872     out2 = (RTYPE) __msa_dotp_s_h((v16i8) mult2, (v16i8) cnst2);   \
873 }
874 #define DOTP_SB3_SH(...) DOTP_SB3(v8i16, __VA_ARGS__)
875
876 #define DOTP_SB4(RTYPE, mult0, mult1, mult2, mult3,                   \
877                  cnst0, cnst1, cnst2, cnst3, out0, out1, out2, out3)  \
878 {                                                                     \
879     DOTP_SB2(RTYPE, mult0, mult1, cnst0, cnst1, out0, out1);          \
880     DOTP_SB2(RTYPE, mult2, mult3, cnst2, cnst3, out2, out3);          \
881 }
882 #define DOTP_SB4_SH(...) DOTP_SB4(v8i16, __VA_ARGS__)
883
884 /* Description : Dot product of halfword vector elements
885    Arguments   : Inputs  - mult0, mult1
886                            cnst0, cnst1
887                  Outputs - out0, out1
888                  Return Type - as per RTYPE
889    Details     : Signed halfword elements from mult0 are multiplied with
890                  signed halfword elements from cnst0 producing a result
891                  twice the size of input i.e. signed word.
892                  Then this multiplication results of adjacent odd-even elements
893                  are added together and stored to the out vector
894                  (2 signed word results)
895 */
896 #define DOTP_SH2(RTYPE, mult0, mult1, cnst0, cnst1, out0, out1)   \
897 {                                                                 \
898     out0 = (RTYPE) __msa_dotp_s_w((v8i16) mult0, (v8i16) cnst0);  \
899     out1 = (RTYPE) __msa_dotp_s_w((v8i16) mult1, (v8i16) cnst1);  \
900 }
901 #define DOTP_SH2_SW(...) DOTP_SH2(v4i32, __VA_ARGS__)
902
903 #define DOTP_SH4(RTYPE, mult0, mult1, mult2, mult3,           \
904                  cnst0, cnst1, cnst2, cnst3,                  \
905                  out0, out1, out2, out3)                      \
906 {                                                             \
907     DOTP_SH2(RTYPE, mult0, mult1, cnst0, cnst1, out0, out1);  \
908     DOTP_SH2(RTYPE, mult2, mult3, cnst2, cnst3, out2, out3);  \
909 }
910 #define DOTP_SH4_SW(...) DOTP_SH4(v4i32, __VA_ARGS__)
911
912 /* Description : Dot product & addition of byte vector elements
913    Arguments   : Inputs  - mult0, mult1
914                            cnst0, cnst1
915                  Outputs - out0, out1
916                  Return Type - as per RTYPE
917    Details     : Signed byte elements from mult0 are multiplied with
918                  signed byte elements from cnst0 producing a result
919                  twice the size of input i.e. signed halfword.
920                  Then this multiplication results of adjacent odd-even elements
921                  are added to the out vector
922                  (2 signed halfword results)
923 */
924 #define DPADD_SB2(RTYPE, mult0, mult1, cnst0, cnst1, out0, out1)   \
925 {                                                                  \
926     out0 = (RTYPE) __msa_dpadd_s_h((v8i16) out0,                   \
927                                    (v16i8) mult0, (v16i8) cnst0);  \
928     out1 = (RTYPE) __msa_dpadd_s_h((v8i16) out1,                   \
929                                    (v16i8) mult1, (v16i8) cnst1);  \
930 }
931 #define DPADD_SB2_SH(...) DPADD_SB2(v8i16, __VA_ARGS__)
932
933 #define DPADD_SB4(RTYPE, mult0, mult1, mult2, mult3,                   \
934                   cnst0, cnst1, cnst2, cnst3, out0, out1, out2, out3)  \
935 {                                                                      \
936     DPADD_SB2(RTYPE, mult0, mult1, cnst0, cnst1, out0, out1);          \
937     DPADD_SB2(RTYPE, mult2, mult3, cnst2, cnst3, out2, out3);          \
938 }
939 #define DPADD_SB4_SH(...) DPADD_SB4(v8i16, __VA_ARGS__)
940
941 /* Description : Dot product & addition of byte vector elements
942    Arguments   : Inputs  - mult0, mult1
943                            cnst0, cnst1
944                  Outputs - out0, out1
945                  Return Type - as per RTYPE
946    Details     : Unsigned byte elements from mult0 are multiplied with
947                  unsigned byte elements from cnst0 producing a result
948                  twice the size of input i.e. unsigned halfword.
949                  Then this multiplication results of adjacent odd-even elements
950                  are added to the out vector
951                  (2 unsigned halfword results)
952 */
953 #define DPADD_UB2(RTYPE, mult0, mult1, cnst0, cnst1, out0, out1)   \
954 {                                                                  \
955     out0 = (RTYPE) __msa_dpadd_u_h((v8u16) out0,                   \
956                                    (v16u8) mult0, (v16u8) cnst0);  \
957     out1 = (RTYPE) __msa_dpadd_u_h((v8u16) out1,                   \
958                                    (v16u8) mult1, (v16u8) cnst1);  \
959 }
960 #define DPADD_UB2_UH(...) DPADD_UB2(v8u16, __VA_ARGS__)
961
962 /* Description : Dot product & addition of halfword vector elements
963    Arguments   : Inputs  - mult0, mult1
964                            cnst0, cnst1
965                  Outputs - out0, out1
966                  Return Type - as per RTYPE
967    Details     : Signed halfword elements from mult0 are multiplied with
968                  signed halfword elements from cnst0 producing a result
969                  twice the size of input i.e. signed word.
970                  Then this multiplication results of adjacent odd-even elements
971                  are added to the out vector
972                  (2 signed word results)
973 */
974 #define DPADD_SH2(RTYPE, mult0, mult1, cnst0, cnst1, out0, out1)   \
975 {                                                                  \
976     out0 = (RTYPE) __msa_dpadd_s_w((v4i32) out0,                   \
977                                    (v8i16) mult0, (v8i16) cnst0);  \
978     out1 = (RTYPE) __msa_dpadd_s_w((v4i32) out1,                   \
979                                    (v8i16) mult1, (v8i16) cnst1);  \
980 }
981 #define DPADD_SH2_SW(...) DPADD_SH2(v4i32, __VA_ARGS__)
982
983 #define DPADD_SH4(RTYPE, mult0, mult1, mult2, mult3,                   \
984                   cnst0, cnst1, cnst2, cnst3, out0, out1, out2, out3)  \
985 {                                                                      \
986     DPADD_SH2(RTYPE, mult0, mult1, cnst0, cnst1, out0, out1);          \
987     DPADD_SH2(RTYPE, mult2, mult3, cnst2, cnst3, out2, out3);          \
988 }
989 #define DPADD_SH4_SW(...) DPADD_SH4(v4i32, __VA_ARGS__)
990
991 /* Description : Minimum values between unsigned elements of
992                  either vector are copied to the output vector
993    Arguments   : Inputs  - in0, in1, min_vec
994                  Outputs - in0, in1, (in place)
995                  Return Type - as per RTYPE
996    Details     : Minimum of unsigned halfword element values from 'in0' and
997                  'min_value' are written to output vector 'in0'
998 */
999 #define MIN_UH2(RTYPE, in0, in1, min_vec)               \
1000 {                                                       \
1001     in0 = (RTYPE) __msa_min_u_h((v8u16) in0, min_vec);  \
1002     in1 = (RTYPE) __msa_min_u_h((v8u16) in1, min_vec);  \
1003 }
1004 #define MIN_UH2_UH(...) MIN_UH2(v8u16, __VA_ARGS__)
1005
1006 #define MIN_UH4(RTYPE, in0, in1, in2, in3, min_vec)  \
1007 {                                                    \
1008     MIN_UH2(RTYPE, in0, in1, min_vec);               \
1009     MIN_UH2(RTYPE, in2, in3, min_vec);               \
1010 }
1011 #define MIN_UH4_UH(...) MIN_UH4(v8u16, __VA_ARGS__)
1012
1013 /* Description : Clips all halfword elements of input vector between min & max
1014                  out = ((in) < (min)) ? (min) : (((in) > (max)) ? (max) : (in))
1015    Arguments   : Inputs  - in       (input vector)
1016                          - min      (min threshold)
1017                          - max      (max threshold)
1018                  Outputs - out_m    (output vector with clipped elements)
1019                  Return Type - signed halfword
1020 */
1021 #define CLIP_SH(in, min, max)                           \
1022 ( {                                                     \
1023     v8i16 out_m;                                        \
1024                                                         \
1025     out_m = __msa_max_s_h((v8i16) min, (v8i16) in);     \
1026     out_m = __msa_min_s_h((v8i16) max, (v8i16) out_m);  \
1027     out_m;                                              \
1028 } )
1029
1030 /* Description : Clips all signed halfword elements of input vector
1031                  between 0 & 255
1032    Arguments   : Inputs  - in       (input vector)
1033                  Outputs - out_m    (output vector with clipped elements)
1034                  Return Type - signed halfword
1035 */
1036 #define CLIP_SH_0_255(in)                                 \
1037 ( {                                                       \
1038     v8i16 max_m = __msa_ldi_h(255);                       \
1039     v8i16 out_m;                                          \
1040                                                           \
1041     out_m = __msa_maxi_s_h((v8i16) in, 0);                \
1042     out_m = __msa_min_s_h((v8i16) max_m, (v8i16) out_m);  \
1043     out_m;                                                \
1044 } )
1045 #define CLIP_SH2_0_255(in0, in1)  \
1046 {                                 \
1047     in0 = CLIP_SH_0_255(in0);     \
1048     in1 = CLIP_SH_0_255(in1);     \
1049 }
1050 #define CLIP_SH4_0_255(in0, in1, in2, in3)  \
1051 {                                           \
1052     CLIP_SH2_0_255(in0, in1);               \
1053     CLIP_SH2_0_255(in2, in3);               \
1054 }
1055
1056 #define CLIP_SH_0_255_MAX_SATU(in)                    \
1057 ( {                                                   \
1058     v8i16 out_m;                                      \
1059                                                       \
1060     out_m = __msa_maxi_s_h((v8i16) in, 0);            \
1061     out_m = (v8i16) __msa_sat_u_h((v8u16) out_m, 7);  \
1062     out_m;                                            \
1063 } )
1064 #define CLIP_SH2_0_255_MAX_SATU(in0, in1)  \
1065 {                                          \
1066     in0 = CLIP_SH_0_255_MAX_SATU(in0);     \
1067     in1 = CLIP_SH_0_255_MAX_SATU(in1);     \
1068 }
1069 #define CLIP_SH4_0_255_MAX_SATU(in0, in1, in2, in3)  \
1070 {                                                    \
1071     CLIP_SH2_0_255_MAX_SATU(in0, in1);               \
1072     CLIP_SH2_0_255_MAX_SATU(in2, in3);               \
1073 }
1074
1075 /* Description : Clips all signed word elements of input vector
1076                  between 0 & 255
1077    Arguments   : Inputs  - in       (input vector)
1078                  Outputs - out_m    (output vector with clipped elements)
1079                  Return Type - signed word
1080 */
1081 #define CLIP_SW_0_255(in)                                 \
1082 ( {                                                       \
1083     v4i32 max_m = __msa_ldi_w(255);                       \
1084     v4i32 out_m;                                          \
1085                                                           \
1086     out_m = __msa_maxi_s_w((v4i32) in, 0);                \
1087     out_m = __msa_min_s_w((v4i32) max_m, (v4i32) out_m);  \
1088     out_m;                                                \
1089 } )
1090
1091 /* Description : Addition of 4 signed word elements
1092                  4 signed word elements of input vector are added together and
1093                  resulted integer sum is returned
1094    Arguments   : Inputs  - in       (signed word vector)
1095                  Outputs - sum_m    (i32 sum)
1096                  Return Type - signed word
1097 */
1098 #define HADD_SW_S32(in)                               \
1099 ( {                                                   \
1100     v2i64 res0_m, res1_m;                             \
1101     int32_t sum_m;                                    \
1102                                                       \
1103     res0_m = __msa_hadd_s_d((v4i32) in, (v4i32) in);  \
1104     res1_m = __msa_splati_d(res0_m, 1);               \
1105     res0_m += res1_m;                                 \
1106     sum_m = __msa_copy_s_w((v4i32) res0_m, 0);        \
1107     sum_m;                                            \
1108 } )
1109
1110 /* Description : Addition of 8 unsigned halfword elements
1111                  8 unsigned halfword elements of input vector are added
1112                  together and resulted integer sum is returned
1113    Arguments   : Inputs  - in       (unsigned halfword vector)
1114                  Outputs - sum_m    (u32 sum)
1115                  Return Type - unsigned word
1116 */
1117 #define HADD_UH_U32(in)                                  \
1118 ( {                                                      \
1119     v4u32 res_m;                                         \
1120     v2u64 res0_m, res1_m;                                \
1121     uint32_t sum_m;                                      \
1122                                                          \
1123     res_m = __msa_hadd_u_w((v8u16) in, (v8u16) in);      \
1124     res0_m = __msa_hadd_u_d(res_m, res_m);               \
1125     res1_m = (v2u64) __msa_splati_d((v2i64) res0_m, 1);  \
1126     res0_m += res1_m;                                    \
1127     sum_m = __msa_copy_u_w((v4i32) res0_m, 0);           \
1128     sum_m;                                               \
1129 } )
1130
1131 /* Description : Horizontal addition of signed byte vector elements
1132    Arguments   : Inputs  - in0, in1
1133                  Outputs - out0, out1
1134                  Return Type - as per RTYPE
1135    Details     : Each signed odd byte element from 'in0' is added to
1136                  even signed byte element from 'in0' (pairwise) and the
1137                  halfword result is stored in 'out0'
1138 */
1139 #define HADD_SB2(RTYPE, in0, in1, out0, out1)                 \
1140 {                                                             \
1141     out0 = (RTYPE) __msa_hadd_s_h((v16i8) in0, (v16i8) in0);  \
1142     out1 = (RTYPE) __msa_hadd_s_h((v16i8) in1, (v16i8) in1);  \
1143 }
1144 #define HADD_SB2_SH(...) HADD_SB2(v8i16, __VA_ARGS__)
1145
1146 #define HADD_SB4(RTYPE, in0, in1, in2, in3, out0, out1, out2, out3)  \
1147 {                                                                    \
1148     HADD_SB2(RTYPE, in0, in1, out0, out1);                           \
1149     HADD_SB2(RTYPE, in2, in3, out2, out3);                           \
1150 }
1151 #define HADD_SB4_UH(...) HADD_SB4(v8u16, __VA_ARGS__)
1152 #define HADD_SB4_SH(...) HADD_SB4(v8i16, __VA_ARGS__)
1153
1154 /* Description : Horizontal addition of unsigned byte vector elements
1155    Arguments   : Inputs  - in0, in1
1156                  Outputs - out0, out1
1157                  Return Type - as per RTYPE
1158    Details     : Each unsigned odd byte element from 'in0' is added to
1159                  even unsigned byte element from 'in0' (pairwise) and the
1160                  halfword result is stored in 'out0'
1161 */
1162 #define HADD_UB2(RTYPE, in0, in1, out0, out1)                 \
1163 {                                                             \
1164     out0 = (RTYPE) __msa_hadd_u_h((v16u8) in0, (v16u8) in0);  \
1165     out1 = (RTYPE) __msa_hadd_u_h((v16u8) in1, (v16u8) in1);  \
1166 }
1167 #define HADD_UB2_UH(...) HADD_UB2(v8u16, __VA_ARGS__)
1168
1169 #define HADD_UB3(RTYPE, in0, in1, in2, out0, out1, out2)      \
1170 {                                                             \
1171     HADD_UB2(RTYPE, in0, in1, out0, out1);                    \
1172     out2 = (RTYPE) __msa_hadd_u_h((v16u8) in2, (v16u8) in2);  \
1173 }
1174 #define HADD_UB3_UH(...) HADD_UB3(v8u16, __VA_ARGS__)
1175
1176 #define HADD_UB4(RTYPE, in0, in1, in2, in3, out0, out1, out2, out3)  \
1177 {                                                                    \
1178     HADD_UB2(RTYPE, in0, in1, out0, out1);                           \
1179     HADD_UB2(RTYPE, in2, in3, out2, out3);                           \
1180 }
1181 #define HADD_UB4_UB(...) HADD_UB4(v16u8, __VA_ARGS__)
1182 #define HADD_UB4_UH(...) HADD_UB4(v8u16, __VA_ARGS__)
1183 #define HADD_UB4_SH(...) HADD_UB4(v8i16, __VA_ARGS__)
1184
1185 /* Description : Horizontal subtraction of unsigned byte vector elements
1186    Arguments   : Inputs  - in0, in1
1187                  Outputs - out0, out1
1188                  Return Type - as per RTYPE
1189    Details     : Each unsigned odd byte element from 'in0' is subtracted from
1190                  even unsigned byte element from 'in0' (pairwise) and the
1191                  halfword result is stored in 'out0'
1192 */
1193 #define HSUB_UB2(RTYPE, in0, in1, out0, out1)                 \
1194 {                                                             \
1195     out0 = (RTYPE) __msa_hsub_u_h((v16u8) in0, (v16u8) in0);  \
1196     out1 = (RTYPE) __msa_hsub_u_h((v16u8) in1, (v16u8) in1);  \
1197 }
1198 #define HSUB_UB2_UH(...) HSUB_UB2(v8u16, __VA_ARGS__)
1199 #define HSUB_UB2_SH(...) HSUB_UB2(v8i16, __VA_ARGS__)
1200
1201 #define HSUB_UB4(RTYPE, in0, in1, in2, in3, out0, out1, out2, out3)  \
1202 {                                                                    \
1203     HSUB_UB2(RTYPE, in0, in1, out0, out1);                           \
1204     HSUB_UB2(RTYPE, in2, in3, out2, out3);                           \
1205 }
1206 #define HSUB_UB4_UH(...) HSUB_UB4(v8u16, __VA_ARGS__)
1207 #define HSUB_UB4_SH(...) HSUB_UB4(v8i16, __VA_ARGS__)
1208
1209 /* Description : SAD (Sum of Absolute Difference)
1210    Arguments   : Inputs  - in0, in1, ref0, ref1  (unsigned byte src & ref)
1211                  Outputs - sad_m                 (halfword vector with sad)
1212                  Return Type - unsigned halfword
1213    Details     : Absolute difference of all the byte elements from 'in0' with
1214                  'ref0' is calculated and preserved in 'diff0'. From the 16
1215                  unsigned absolute diff values, even-odd pairs are added
1216                  together to generate 8 halfword results.
1217 */
1218 #define SAD_UB2_UH(in0, in1, ref0, ref1)                        \
1219 ( {                                                             \
1220     v16u8 diff0_m, diff1_m;                                     \
1221     v8u16 sad_m = { 0 };                                        \
1222                                                                 \
1223     diff0_m = __msa_asub_u_b((v16u8) in0, (v16u8) ref0);        \
1224     diff1_m = __msa_asub_u_b((v16u8) in1, (v16u8) ref1);        \
1225                                                                 \
1226     sad_m += __msa_hadd_u_h((v16u8) diff0_m, (v16u8) diff0_m);  \
1227     sad_m += __msa_hadd_u_h((v16u8) diff1_m, (v16u8) diff1_m);  \
1228                                                                 \
1229     sad_m;                                                      \
1230 } )
1231
1232 /* Description : Insert specified word elements from input vectors to 1
1233                  destination vector
1234    Arguments   : Inputs  - in0, in1, in2, in3 (4 input vectors)
1235                  Outputs - out                (output vector)
1236                  Return Type - as per RTYPE
1237 */
1238 #define INSERT_W2(RTYPE, in0, in1, out)                 \
1239 {                                                       \
1240     out = (RTYPE) __msa_insert_w((v4i32) out, 0, in0);  \
1241     out = (RTYPE) __msa_insert_w((v4i32) out, 1, in1);  \
1242 }
1243 #define INSERT_W2_UB(...) INSERT_W2(v16u8, __VA_ARGS__)
1244 #define INSERT_W2_SB(...) INSERT_W2(v16i8, __VA_ARGS__)
1245
1246 #define INSERT_W4(RTYPE, in0, in1, in2, in3, out)       \
1247 {                                                       \
1248     out = (RTYPE) __msa_insert_w((v4i32) out, 0, in0);  \
1249     out = (RTYPE) __msa_insert_w((v4i32) out, 1, in1);  \
1250     out = (RTYPE) __msa_insert_w((v4i32) out, 2, in2);  \
1251     out = (RTYPE) __msa_insert_w((v4i32) out, 3, in3);  \
1252 }
1253 #define INSERT_W4_UB(...) INSERT_W4(v16u8, __VA_ARGS__)
1254 #define INSERT_W4_SB(...) INSERT_W4(v16i8, __VA_ARGS__)
1255 #define INSERT_W4_SW(...) INSERT_W4(v4i32, __VA_ARGS__)
1256
1257 /* Description : Insert specified double word elements from input vectors to 1
1258                  destination vector
1259    Arguments   : Inputs  - in0, in1      (2 input vectors)
1260                  Outputs - out           (output vector)
1261                  Return Type - as per RTYPE
1262 */
1263 #define INSERT_D2(RTYPE, in0, in1, out)                 \
1264 {                                                       \
1265     out = (RTYPE) __msa_insert_d((v2i64) out, 0, in0);  \
1266     out = (RTYPE) __msa_insert_d((v2i64) out, 1, in1);  \
1267 }
1268 #define INSERT_D2_UB(...) INSERT_D2(v16u8, __VA_ARGS__)
1269 #define INSERT_D2_SB(...) INSERT_D2(v16i8, __VA_ARGS__)
1270 #define INSERT_D2_SD(...) INSERT_D2(v2i64, __VA_ARGS__)
1271
1272 /* Description : Interleave even byte elements from vectors
1273    Arguments   : Inputs  - in0, in1, in2, in3
1274                  Outputs - out0, out1
1275                  Return Type - as per RTYPE
1276    Details     : Even byte elements of 'in0' and even byte
1277                  elements of 'in1' are interleaved and copied to 'out0'
1278                  Even byte elements of 'in2' and even byte
1279                  elements of 'in3' are interleaved and copied to 'out1'
1280 */
1281 #define ILVEV_B2(RTYPE, in0, in1, in2, in3, out0, out1)      \
1282 {                                                            \
1283     out0 = (RTYPE) __msa_ilvev_b((v16i8) in1, (v16i8) in0);  \
1284     out1 = (RTYPE) __msa_ilvev_b((v16i8) in3, (v16i8) in2);  \
1285 }
1286 #define ILVEV_B2_UB(...) ILVEV_B2(v16u8, __VA_ARGS__)
1287 #define ILVEV_B2_SB(...) ILVEV_B2(v16i8, __VA_ARGS__)
1288 #define ILVEV_B2_SH(...) ILVEV_B2(v8i16, __VA_ARGS__)
1289 #define ILVEV_B2_SD(...) ILVEV_B2(v2i64, __VA_ARGS__)
1290
1291 /* Description : Interleave even halfword elements from vectors
1292    Arguments   : Inputs  - in0, in1, in2, in3
1293                  Outputs - out0, out1
1294                  Return Type - as per RTYPE
1295    Details     : Even halfword elements of 'in0' and even halfword
1296                  elements of 'in1' are interleaved and copied to 'out0'
1297                  Even halfword elements of 'in2' and even halfword
1298                  elements of 'in3' are interleaved and copied to 'out1'
1299 */
1300 #define ILVEV_H2(RTYPE, in0, in1, in2, in3, out0, out1)      \
1301 {                                                            \
1302     out0 = (RTYPE) __msa_ilvev_h((v8i16) in1, (v8i16) in0);  \
1303     out1 = (RTYPE) __msa_ilvev_h((v8i16) in3, (v8i16) in2);  \
1304 }
1305 #define ILVEV_H2_UB(...) ILVEV_H2(v16u8, __VA_ARGS__)
1306 #define ILVEV_H2_SH(...) ILVEV_H2(v8i16, __VA_ARGS__)
1307 #define ILVEV_H2_SW(...) ILVEV_H2(v4i32, __VA_ARGS__)
1308
1309 /* Description : Interleave even word elements from vectors
1310    Arguments   : Inputs  - in0, in1, in2, in3
1311                  Outputs - out0, out1
1312                  Return Type - as per RTYPE
1313    Details     : Even word elements of 'in0' and even word
1314                  elements of 'in1' are interleaved and copied to 'out0'
1315                  Even word elements of 'in2' and even word
1316                  elements of 'in3' are interleaved and copied to 'out1'
1317 */
1318 #define ILVEV_W2(RTYPE, in0, in1, in2, in3, out0, out1)      \
1319 {                                                            \
1320     out0 = (RTYPE) __msa_ilvev_w((v4i32) in1, (v4i32) in0);  \
1321     out1 = (RTYPE) __msa_ilvev_w((v4i32) in3, (v4i32) in2);  \
1322 }
1323 #define ILVEV_W2_UB(...) ILVEV_W2(v16u8, __VA_ARGS__)
1324 #define ILVEV_W2_SB(...) ILVEV_W2(v16i8, __VA_ARGS__)
1325 #define ILVEV_W2_UH(...) ILVEV_W2(v8u16, __VA_ARGS__)
1326 #define ILVEV_W2_SD(...) ILVEV_W2(v2i64, __VA_ARGS__)
1327
1328 /* Description : Interleave even double word elements from vectors
1329    Arguments   : Inputs  - in0, in1, in2, in3
1330                  Outputs - out0, out1
1331                  Return Type - as per RTYPE
1332    Details     : Even double word elements of 'in0' and even double word
1333                  elements of 'in1' are interleaved and copied to 'out0'
1334                  Even double word elements of 'in2' and even double word
1335                  elements of 'in3' are interleaved and copied to 'out1'
1336 */
1337 #define ILVEV_D2(RTYPE, in0, in1, in2, in3, out0, out1)      \
1338 {                                                            \
1339     out0 = (RTYPE) __msa_ilvev_d((v2i64) in1, (v2i64) in0);  \
1340     out1 = (RTYPE) __msa_ilvev_d((v2i64) in3, (v2i64) in2);  \
1341 }
1342 #define ILVEV_D2_UB(...) ILVEV_D2(v16u8, __VA_ARGS__)
1343 #define ILVEV_D2_SB(...) ILVEV_D2(v16i8, __VA_ARGS__)
1344 #define ILVEV_D2_SW(...) ILVEV_D2(v4i32, __VA_ARGS__)
1345
1346 /* Description : Interleave left half of byte elements from vectors
1347    Arguments   : Inputs  - in0, in1, in2, in3
1348                  Outputs - out0, out1
1349                  Return Type - as per RTYPE
1350    Details     : Left half of byte elements of in0 and left half of byte
1351                  elements of in1 are interleaved and copied to out0.
1352                  Left half of byte elements of in2 and left half of byte
1353                  elements of in3 are interleaved and copied to out1.
1354 */
1355 #define ILVL_B2(RTYPE, in0, in1, in2, in3, out0, out1)      \
1356 {                                                           \
1357     out0 = (RTYPE) __msa_ilvl_b((v16i8) in0, (v16i8) in1);  \
1358     out1 = (RTYPE) __msa_ilvl_b((v16i8) in2, (v16i8) in3);  \
1359 }
1360 #define ILVL_B2_UB(...) ILVL_B2(v16u8, __VA_ARGS__)
1361 #define ILVL_B2_SB(...) ILVL_B2(v16i8, __VA_ARGS__)
1362 #define ILVL_B2_UH(...) ILVL_B2(v8u16, __VA_ARGS__)
1363 #define ILVL_B2_SH(...) ILVL_B2(v8i16, __VA_ARGS__)
1364
1365 #define ILVL_B4(RTYPE, in0, in1, in2, in3, in4, in5, in6, in7,  \
1366                 out0, out1, out2, out3)                         \
1367 {                                                               \
1368     ILVL_B2(RTYPE, in0, in1, in2, in3, out0, out1);             \
1369     ILVL_B2(RTYPE, in4, in5, in6, in7, out2, out3);             \
1370 }
1371 #define ILVL_B4_UB(...) ILVL_B4(v16u8, __VA_ARGS__)
1372 #define ILVL_B4_SB(...) ILVL_B4(v16i8, __VA_ARGS__)
1373 #define ILVL_B4_UH(...) ILVL_B4(v8u16, __VA_ARGS__)
1374 #define ILVL_B4_SH(...) ILVL_B4(v8i16, __VA_ARGS__)
1375
1376 /* Description : Interleave left half of halfword elements from vectors
1377    Arguments   : Inputs  - in0, in1, in2, in3
1378                  Outputs - out0, out1
1379                  Return Type - as per RTYPE
1380    Details     : Left half of halfword elements of in0 and left half of halfword
1381                  elements of in1 are interleaved and copied to out0.
1382                  Left half of halfword elements of in2 and left half of halfword
1383                  elements of in3 are interleaved and copied to out1.
1384 */
1385 #define ILVL_H2(RTYPE, in0, in1, in2, in3, out0, out1)      \
1386 {                                                           \
1387     out0 = (RTYPE) __msa_ilvl_h((v8i16) in0, (v8i16) in1);  \
1388     out1 = (RTYPE) __msa_ilvl_h((v8i16) in2, (v8i16) in3);  \
1389 }
1390 #define ILVL_H2_SH(...) ILVL_H2(v8i16, __VA_ARGS__)
1391 #define ILVL_H2_SW(...) ILVL_H2(v4i32, __VA_ARGS__)
1392
1393 #define ILVL_H4(RTYPE, in0, in1, in2, in3, in4, in5, in6, in7,  \
1394                 out0, out1, out2, out3)                         \
1395 {                                                               \
1396     ILVL_H2(RTYPE, in0, in1, in2, in3, out0, out1);             \
1397     ILVL_H2(RTYPE, in4, in5, in6, in7, out2, out3);             \
1398 }
1399 #define ILVL_H4_SH(...) ILVL_H4(v8i16, __VA_ARGS__)
1400 #define ILVL_H4_SW(...) ILVL_H4(v4i32, __VA_ARGS__)
1401
1402 /* Description : Interleave left half of word elements from vectors
1403    Arguments   : Inputs  - in0, in1, in2, in3
1404                  Outputs - out0, out1
1405                  Return Type - as per RTYPE
1406    Details     : Left half of word elements of in0 and left half of word
1407                  elements of in1 are interleaved and copied to out0.
1408                  Left half of word elements of in2 and left half of word
1409                  elements of in3 are interleaved and copied to out1.
1410 */
1411 #define ILVL_W2(RTYPE, in0, in1, in2, in3, out0, out1)      \
1412 {                                                           \
1413     out0 = (RTYPE) __msa_ilvl_w((v4i32) in0, (v4i32) in1);  \
1414     out1 = (RTYPE) __msa_ilvl_w((v4i32) in2, (v4i32) in3);  \
1415 }
1416 #define ILVL_W2_UB(...) ILVL_W2(v16u8, __VA_ARGS__)
1417 #define ILVL_W2_SB(...) ILVL_W2(v16i8, __VA_ARGS__)
1418 #define ILVL_W2_SH(...) ILVL_W2(v8i16, __VA_ARGS__)
1419
1420 /* Description : Interleave right half of byte elements from vectors
1421    Arguments   : Inputs  - in0, in1, in2, in3, in4, in5, in6, in7
1422                  Outputs - out0, out1, out2, out3
1423                  Return Type - as per RTYPE
1424    Details     : Right half of byte elements of in0 and right half of byte
1425                  elements of in1 are interleaved and copied to out0.
1426                  Right half of byte elements of in2 and right half of byte
1427                  elements of in3 are interleaved and copied to out1.
1428                  Similar for other pairs
1429 */
1430 #define ILVR_B2(RTYPE, in0, in1, in2, in3, out0, out1)      \
1431 {                                                           \
1432     out0 = (RTYPE) __msa_ilvr_b((v16i8) in0, (v16i8) in1);  \
1433     out1 = (RTYPE) __msa_ilvr_b((v16i8) in2, (v16i8) in3);  \
1434 }
1435 #define ILVR_B2_UB(...) ILVR_B2(v16u8, __VA_ARGS__)
1436 #define ILVR_B2_SB(...) ILVR_B2(v16i8, __VA_ARGS__)
1437 #define ILVR_B2_UH(...) ILVR_B2(v8u16, __VA_ARGS__)
1438 #define ILVR_B2_SH(...) ILVR_B2(v8i16, __VA_ARGS__)
1439 #define ILVR_B2_SW(...) ILVR_B2(v4i32, __VA_ARGS__)
1440
1441 #define ILVR_B3(RTYPE, in0, in1, in2, in3, in4, in5, out0, out1, out2)  \
1442 {                                                                       \
1443     ILVR_B2(RTYPE, in0, in1, in2, in3, out0, out1);                     \
1444     out2 = (RTYPE) __msa_ilvr_b((v16i8) in4, (v16i8) in5);              \
1445 }
1446 #define ILVR_B3_UB(...) ILVR_B3(v16u8, __VA_ARGS__)
1447 #define ILVR_B3_UH(...) ILVR_B3(v8u16, __VA_ARGS__)
1448 #define ILVR_B3_SH(...) ILVR_B3(v8i16, __VA_ARGS__)
1449
1450 #define ILVR_B4(RTYPE, in0, in1, in2, in3, in4, in5, in6, in7,  \
1451                 out0, out1, out2, out3)                         \
1452 {                                                               \
1453     ILVR_B2(RTYPE, in0, in1, in2, in3, out0, out1);             \
1454     ILVR_B2(RTYPE, in4, in5, in6, in7, out2, out3);             \
1455 }
1456 #define ILVR_B4_UB(...) ILVR_B4(v16u8, __VA_ARGS__)
1457 #define ILVR_B4_SB(...) ILVR_B4(v16i8, __VA_ARGS__)
1458 #define ILVR_B4_UH(...) ILVR_B4(v8u16, __VA_ARGS__)
1459 #define ILVR_B4_SH(...) ILVR_B4(v8i16, __VA_ARGS__)
1460 #define ILVR_B4_SW(...) ILVR_B4(v4i32, __VA_ARGS__)
1461
1462 #define ILVR_B8(RTYPE, in0, in1, in2, in3, in4, in5, in6, in7,    \
1463                 in8, in9, in10, in11, in12, in13, in14, in15,     \
1464                 out0, out1, out2, out3, out4, out5, out6, out7)   \
1465 {                                                                 \
1466     ILVR_B4(RTYPE, in0, in1, in2, in3, in4, in5, in6, in7,        \
1467             out0, out1, out2, out3);                              \
1468     ILVR_B4(RTYPE, in8, in9, in10, in11, in12, in13, in14, in15,  \
1469             out4, out5, out6, out7);                              \
1470 }
1471 #define ILVR_B8_UH(...) ILVR_B8(v8u16, __VA_ARGS__)
1472
1473 /* Description : Interleave right half of halfword elements from vectors
1474    Arguments   : Inputs  - in0, in1, in2, in3, in4, in5, in6, in7
1475                  Outputs - out0, out1, out2, out3
1476                  Return Type - as per RTYPE
1477    Details     : Right half of halfword elements of in0 and right half of
1478                  halfword elements of in1 are interleaved and copied to out0.
1479                  Right half of halfword elements of in2 and right half of
1480                  halfword elements of in3 are interleaved and copied to out1.
1481                  Similar for other pairs
1482 */
1483 #define ILVR_H2(RTYPE, in0, in1, in2, in3, out0, out1)      \
1484 {                                                           \
1485     out0 = (RTYPE) __msa_ilvr_h((v8i16) in0, (v8i16) in1);  \
1486     out1 = (RTYPE) __msa_ilvr_h((v8i16) in2, (v8i16) in3);  \
1487 }
1488 #define ILVR_H2_SH(...) ILVR_H2(v8i16, __VA_ARGS__)
1489 #define ILVR_H2_SW(...) ILVR_H2(v4i32, __VA_ARGS__)
1490
1491 #define ILVR_H3(RTYPE, in0, in1, in2, in3, in4, in5, out0, out1, out2)  \
1492 {                                                                       \
1493     ILVR_H2(RTYPE, in0, in1, in2, in3, out0, out1);                     \
1494     out2 = (RTYPE) __msa_ilvr_h((v8i16) in4, (v8i16) in5);              \
1495 }
1496 #define ILVR_H3_SH(...) ILVR_H3(v8i16, __VA_ARGS__)
1497
1498 #define ILVR_H4(RTYPE, in0, in1, in2, in3, in4, in5, in6, in7,  \
1499                 out0, out1, out2, out3)                         \
1500 {                                                               \
1501     ILVR_H2(RTYPE, in0, in1, in2, in3, out0, out1);             \
1502     ILVR_H2(RTYPE, in4, in5, in6, in7, out2, out3);             \
1503 }
1504 #define ILVR_H4_SH(...) ILVR_H4(v8i16, __VA_ARGS__)
1505 #define ILVR_H4_SW(...) ILVR_H4(v4i32, __VA_ARGS__)
1506
1507 #define ILVR_W2(RTYPE, in0, in1, in2, in3, out0, out1)      \
1508 {                                                           \
1509     out0 = (RTYPE) __msa_ilvr_w((v4i32) in0, (v4i32) in1);  \
1510     out1 = (RTYPE) __msa_ilvr_w((v4i32) in2, (v4i32) in3);  \
1511 }
1512 #define ILVR_W2_UB(...) ILVR_W2(v16u8, __VA_ARGS__)
1513 #define ILVR_W2_SB(...) ILVR_W2(v16i8, __VA_ARGS__)
1514 #define ILVR_W2_SH(...) ILVR_W2(v8i16, __VA_ARGS__)
1515
1516 #define ILVR_W4(RTYPE, in0, in1, in2, in3, in4, in5, in6, in7,  \
1517                 out0, out1, out2, out3)                         \
1518 {                                                               \
1519     ILVR_W2(RTYPE, in0, in1, in2, in3, out0, out1);             \
1520     ILVR_W2(RTYPE, in4, in5, in6, in7, out2, out3);             \
1521 }
1522 #define ILVR_W4_SB(...) ILVR_W4(v16i8, __VA_ARGS__)
1523 #define ILVR_W4_UB(...) ILVR_W4(v16u8, __VA_ARGS__)
1524
1525 /* Description : Interleave right half of double word elements from vectors
1526    Arguments   : Inputs  - in0, in1, in2, in3, in4, in5, in6, in7
1527                  Outputs - out0, out1, out2, out3
1528                  Return Type - as per RTYPE
1529    Details     : Right half of double word elements of in0 and right half of
1530                  double word elements of in1 are interleaved and copied to out0.
1531                  Right half of double word elements of in2 and right half of
1532                  double word elements of in3 are interleaved and copied to out1.
1533 */
1534 #define ILVR_D2(RTYPE, in0, in1, in2, in3, out0, out1)      \
1535 {                                                           \
1536     out0 = (RTYPE) __msa_ilvr_d((v2i64) in0, (v2i64) in1);  \
1537     out1 = (RTYPE) __msa_ilvr_d((v2i64) in2, (v2i64) in3);  \
1538 }
1539 #define ILVR_D2_UB(...) ILVR_D2(v16u8, __VA_ARGS__)
1540 #define ILVR_D2_SB(...) ILVR_D2(v16i8, __VA_ARGS__)
1541 #define ILVR_D2_SH(...) ILVR_D2(v8i16, __VA_ARGS__)
1542
1543 #define ILVR_D3(RTYPE, in0, in1, in2, in3, in4, in5, out0, out1, out2)  \
1544 {                                                                       \
1545     ILVR_D2(RTYPE, in0, in1, in2, in3, out0, out1);                     \
1546     out2 = (RTYPE) __msa_ilvr_d((v2i64) in4, (v2i64) in5);              \
1547 }
1548 #define ILVR_D3_SB(...) ILVR_D3(v16i8, __VA_ARGS__)
1549
1550 #define ILVR_D4(RTYPE, in0, in1, in2, in3, in4, in5, in6, in7,  \
1551                 out0, out1, out2, out3)                         \
1552 {                                                               \
1553     ILVR_D2(RTYPE, in0, in1, in2, in3, out0, out1);             \
1554     ILVR_D2(RTYPE, in4, in5, in6, in7, out2, out3);             \
1555 }
1556 #define ILVR_D4_SB(...) ILVR_D4(v16i8, __VA_ARGS__)
1557 #define ILVR_D4_UB(...) ILVR_D4(v16u8, __VA_ARGS__)
1558
1559 /* Description : Interleave left half of double word elements from vectors
1560    Arguments   : Inputs  - in0, in1, in2, in3
1561                  Outputs - out0, out1
1562                  Return Type - as per RTYPE
1563    Details     : Left half of double word elements of in0 and left half of
1564                  double word elements of in1 are interleaved and copied to out0.
1565                  Left half of double word elements of in2 and left half of
1566                  double word elements of in3 are interleaved and copied to out1.
1567 */
1568 #define ILVL_D2(RTYPE, in0, in1, in2, in3, out0, out1)      \
1569 {                                                           \
1570     out0 = (RTYPE) __msa_ilvl_d((v2i64) in0, (v2i64) in1);  \
1571     out1 = (RTYPE) __msa_ilvl_d((v2i64) in2, (v2i64) in3);  \
1572 }
1573 #define ILVL_D2_UB(...) ILVL_D2(v16u8, __VA_ARGS__)
1574 #define ILVL_D2_SB(...) ILVL_D2(v16i8, __VA_ARGS__)
1575 #define ILVL_D2_SH(...) ILVL_D2(v8i16, __VA_ARGS__)
1576
1577 /* Description : Interleave both left and right half of input vectors
1578    Arguments   : Inputs  - in0, in1
1579                  Outputs - out0, out1
1580                  Return Type - as per RTYPE
1581    Details     : Right half of byte elements from 'in0' and 'in1' are
1582                  interleaved and stored to 'out0'
1583                  Left half of byte elements from 'in0' and 'in1' are
1584                  interleaved and stored to 'out1'
1585 */
1586 #define ILVRL_B2(RTYPE, in0, in1, out0, out1)               \
1587 {                                                           \
1588     out0 = (RTYPE) __msa_ilvr_b((v16i8) in0, (v16i8) in1);  \
1589     out1 = (RTYPE) __msa_ilvl_b((v16i8) in0, (v16i8) in1);  \
1590 }
1591 #define ILVRL_B2_UB(...) ILVRL_B2(v16u8, __VA_ARGS__)
1592 #define ILVRL_B2_SB(...) ILVRL_B2(v16i8, __VA_ARGS__)
1593 #define ILVRL_B2_UH(...) ILVRL_B2(v8u16, __VA_ARGS__)
1594 #define ILVRL_B2_SH(...) ILVRL_B2(v8i16, __VA_ARGS__)
1595 #define ILVRL_B2_SW(...) ILVRL_B2(v4i32, __VA_ARGS__)
1596
1597 #define ILVRL_H2(RTYPE, in0, in1, out0, out1)               \
1598 {                                                           \
1599     out0 = (RTYPE) __msa_ilvr_h((v8i16) in0, (v8i16) in1);  \
1600     out1 = (RTYPE) __msa_ilvl_h((v8i16) in0, (v8i16) in1);  \
1601 }
1602 #define ILVRL_H2_UB(...) ILVRL_H2(v16u8, __VA_ARGS__)
1603 #define ILVRL_H2_SB(...) ILVRL_H2(v16i8, __VA_ARGS__)
1604 #define ILVRL_H2_SH(...) ILVRL_H2(v8i16, __VA_ARGS__)
1605 #define ILVRL_H2_SW(...) ILVRL_H2(v4i32, __VA_ARGS__)
1606
1607 #define ILVRL_W2(RTYPE, in0, in1, out0, out1)               \
1608 {                                                           \
1609     out0 = (RTYPE) __msa_ilvr_w((v4i32) in0, (v4i32) in1);  \
1610     out1 = (RTYPE) __msa_ilvl_w((v4i32) in0, (v4i32) in1);  \
1611 }
1612 #define ILVRL_W2_UB(...) ILVRL_W2(v16u8, __VA_ARGS__)
1613 #define ILVRL_W2_SH(...) ILVRL_W2(v8i16, __VA_ARGS__)
1614 #define ILVRL_W2_SW(...) ILVRL_W2(v4i32, __VA_ARGS__)
1615
1616 /* Description : Maximum values between signed elements of vector and
1617                  5-bit signed immediate value are copied to the output vector
1618    Arguments   : Inputs  - in0, in1, in2, in3, max_val
1619                  Outputs - in0, in1, in2, in3 (in place)
1620                  Return Type - as per RTYPE
1621    Details     : Maximum of signed halfword element values from 'in0' and
1622                  'max_val' are written to output vector 'in0'
1623 */
1624 #define MAXI_SH2(RTYPE, in0, in1, max_val)               \
1625 {                                                        \
1626     in0 = (RTYPE) __msa_maxi_s_h((v8i16) in0, max_val);  \
1627     in1 = (RTYPE) __msa_maxi_s_h((v8i16) in1, max_val);  \
1628 }
1629 #define MAXI_SH2_UH(...) MAXI_SH2(v8u16, __VA_ARGS__)
1630 #define MAXI_SH2_SH(...) MAXI_SH2(v8i16, __VA_ARGS__)
1631
1632 #define MAXI_SH4(RTYPE, in0, in1, in2, in3, max_val)  \
1633 {                                                     \
1634     MAXI_SH2(RTYPE, in0, in1, max_val);               \
1635     MAXI_SH2(RTYPE, in2, in3, max_val);               \
1636 }
1637 #define MAXI_SH4_UH(...) MAXI_SH4(v8u16, __VA_ARGS__)
1638
1639 /* Description : Saturate the halfword element values to the max
1640                  unsigned value of (sat_val+1 bits)
1641                  The element data width remains unchanged
1642    Arguments   : Inputs  - in0, in1, in2, in3, sat_val
1643                  Outputs - in0, in1, in2, in3 (in place)
1644                  Return Type - as per RTYPE
1645    Details     : Each unsigned halfword element from 'in0' is saturated to the
1646                  value generated with (sat_val+1) bit range
1647                  Results are in placed to original vectors
1648 */
1649 #define SAT_UH2(RTYPE, in0, in1, sat_val)               \
1650 {                                                       \
1651     in0 = (RTYPE) __msa_sat_u_h((v8u16) in0, sat_val);  \
1652     in1 = (RTYPE) __msa_sat_u_h((v8u16) in1, sat_val);  \
1653 }
1654 #define SAT_UH2_UH(...) SAT_UH2(v8u16, __VA_ARGS__)
1655 #define SAT_UH2_SH(...) SAT_UH2(v8i16, __VA_ARGS__)
1656
1657 #define SAT_UH4(RTYPE, in0, in1, in2, in3, sat_val)  \
1658 {                                                    \
1659     SAT_UH2(RTYPE, in0, in1, sat_val);               \
1660     SAT_UH2(RTYPE, in2, in3, sat_val);               \
1661 }
1662 #define SAT_UH4_UH(...) SAT_UH4(v8u16, __VA_ARGS__)
1663
1664 /* Description : Saturate the halfword element values to the max
1665                  unsigned value of (sat_val+1 bits)
1666                  The element data width remains unchanged
1667    Arguments   : Inputs  - in0, in1, in2, in3, sat_val
1668                  Outputs - in0, in1, in2, in3 (in place)
1669                  Return Type - as per RTYPE
1670    Details     : Each unsigned halfword element from 'in0' is saturated to the
1671                  value generated with (sat_val+1) bit range
1672                  Results are in placed to original vectors
1673 */
1674 #define SAT_SH2(RTYPE, in0, in1, sat_val)               \
1675 {                                                       \
1676     in0 = (RTYPE) __msa_sat_s_h((v8i16) in0, sat_val);  \
1677     in1 = (RTYPE) __msa_sat_s_h((v8i16) in1, sat_val);  \
1678 }
1679 #define SAT_SH2_SH(...) SAT_SH2(v8i16, __VA_ARGS__)
1680
1681 #define SAT_SH3(RTYPE, in0, in1, in2, sat_val)          \
1682 {                                                       \
1683     SAT_SH2(RTYPE, in0, in1, sat_val);                  \
1684     in2 = (RTYPE) __msa_sat_s_h((v8i16) in2, sat_val);  \
1685 }
1686 #define SAT_SH3_SH(...) SAT_SH3(v8i16, __VA_ARGS__)
1687
1688 #define SAT_SH4(RTYPE, in0, in1, in2, in3, sat_val)  \
1689 {                                                    \
1690     SAT_SH2(RTYPE, in0, in1, sat_val);               \
1691     SAT_SH2(RTYPE, in2, in3, sat_val);               \
1692 }
1693 #define SAT_SH4_SH(...) SAT_SH4(v8i16, __VA_ARGS__)
1694
1695 /* Description : Saturate the word element values to the max
1696                  unsigned value of (sat_val+1 bits)
1697                  The element data width remains unchanged
1698    Arguments   : Inputs  - in0, in1, in2, in3, sat_val
1699                  Outputs - in0, in1, in2, in3 (in place)
1700                  Return Type - as per RTYPE
1701    Details     : Each unsigned word element from 'in0' is saturated to the
1702                  value generated with (sat_val+1) bit range
1703                  Results are in placed to original vectors
1704 */
1705 #define SAT_SW2(RTYPE, in0, in1, sat_val)               \
1706 {                                                       \
1707     in0 = (RTYPE) __msa_sat_s_w((v4i32) in0, sat_val);  \
1708     in1 = (RTYPE) __msa_sat_s_w((v4i32) in1, sat_val);  \
1709 }
1710 #define SAT_SW2_SW(...) SAT_SW2(v4i32, __VA_ARGS__)
1711
1712 #define SAT_SW4(RTYPE, in0, in1, in2, in3, sat_val)  \
1713 {                                                    \
1714     SAT_SW2(RTYPE, in0, in1, sat_val);               \
1715     SAT_SW2(RTYPE, in2, in3, sat_val);               \
1716 }
1717 #define SAT_SW4_SW(...) SAT_SW4(v4i32, __VA_ARGS__)
1718
1719 /* Description : Indexed halfword element values are replicated to all
1720                  elements in output vector
1721    Arguments   : Inputs  - in, idx0, idx1
1722                  Outputs - out0, out1
1723                  Return Type - as per RTYPE
1724    Details     : 'idx0' element value from 'in' vector is replicated to all
1725                   elements in 'out0' vector
1726                   Valid index range for halfword operation is 0-7
1727 */
1728 #define SPLATI_H2(RTYPE, in, idx0, idx1, out0, out1)  \
1729 {                                                     \
1730     out0 = (RTYPE) __msa_splati_h((v8i16) in, idx0);  \
1731     out1 = (RTYPE) __msa_splati_h((v8i16) in, idx1);  \
1732 }
1733 #define SPLATI_H2_SB(...) SPLATI_H2(v16i8, __VA_ARGS__)
1734 #define SPLATI_H2_SH(...) SPLATI_H2(v8i16, __VA_ARGS__)
1735
1736 #define SPLATI_H3(RTYPE, in, idx0, idx1, idx2,        \
1737                   out0, out1, out2)                   \
1738 {                                                     \
1739     SPLATI_H2(RTYPE, in, idx0, idx1, out0, out1);     \
1740     out2 = (RTYPE) __msa_splati_h((v8i16) in, idx2);  \
1741 }
1742 #define SPLATI_H3_SB(...) SPLATI_H3(v16i8, __VA_ARGS__)
1743 #define SPLATI_H3_SH(...) SPLATI_H3(v8i16, __VA_ARGS__)
1744
1745 #define SPLATI_H4(RTYPE, in, idx0, idx1, idx2, idx3,  \
1746                   out0, out1, out2, out3)             \
1747 {                                                     \
1748     SPLATI_H2(RTYPE, in, idx0, idx1, out0, out1);     \
1749     SPLATI_H2(RTYPE, in, idx2, idx3, out2, out3);     \
1750 }
1751 #define SPLATI_H4_SB(...) SPLATI_H4(v16i8, __VA_ARGS__)
1752 #define SPLATI_H4_SH(...) SPLATI_H4(v8i16, __VA_ARGS__)
1753
1754 /* Description : Indexed word element values are replicated to all
1755                  elements in output vector
1756    Arguments   : Inputs  - in, stidx
1757                  Outputs - out0, out1
1758                  Return Type - as per RTYPE
1759    Details     : 'stidx' element value from 'in' vector is replicated to all
1760                   elements in 'out0' vector
1761                  'stidx + 1' element value from 'in' vector is replicated to all
1762                   elements in 'out1' vector
1763                   Valid index range for halfword operation is 0-3
1764 */
1765 #define SPLATI_W2(RTYPE, in, stidx, out0, out1)            \
1766 {                                                          \
1767     out0 = (RTYPE) __msa_splati_w((v4i32) in, stidx);      \
1768     out1 = (RTYPE) __msa_splati_w((v4i32) in, (stidx+1));  \
1769 }
1770 #define SPLATI_W2_SH(...) SPLATI_W2(v8i16, __VA_ARGS__)
1771 #define SPLATI_W2_SW(...) SPLATI_W2(v4i32, __VA_ARGS__)
1772
1773 #define SPLATI_W4(RTYPE, in, out0, out1, out2, out3)  \
1774 {                                                     \
1775     SPLATI_W2(RTYPE, in, 0, out0, out1);              \
1776     SPLATI_W2(RTYPE, in, 2, out2, out3);              \
1777 }
1778 #define SPLATI_W4_SH(...) SPLATI_W4(v8i16, __VA_ARGS__)
1779 #define SPLATI_W4_SW(...) SPLATI_W4(v4i32, __VA_ARGS__)
1780
1781 /* Description : Pack even byte elements of vector pairs
1782    Arguments   : Inputs  - in0, in1, in2, in3
1783                  Outputs - out0, out1
1784                  Return Type - as per RTYPE
1785    Details     : Even byte elements of in0 are copied to the left half of
1786                  out0 & even byte elements of in1 are copied to the right
1787                  half of out0.
1788                  Even byte elements of in2 are copied to the left half of
1789                  out1 & even byte elements of in3 are copied to the right
1790                  half of out1.
1791 */
1792 #define PCKEV_B2(RTYPE, in0, in1, in2, in3, out0, out1)      \
1793 {                                                            \
1794     out0 = (RTYPE) __msa_pckev_b((v16i8) in0, (v16i8) in1);  \
1795     out1 = (RTYPE) __msa_pckev_b((v16i8) in2, (v16i8) in3);  \
1796 }
1797 #define PCKEV_B2_SB(...) PCKEV_B2(v16i8, __VA_ARGS__)
1798 #define PCKEV_B2_UB(...) PCKEV_B2(v16u8, __VA_ARGS__)
1799 #define PCKEV_B2_SH(...) PCKEV_B2(v8i16, __VA_ARGS__)
1800 #define PCKEV_B2_SW(...) PCKEV_B2(v4i32, __VA_ARGS__)
1801
1802 #define PCKEV_B3(RTYPE, in0, in1, in2, in3, in4, in5, out0, out1, out2)  \
1803 {                                                                        \
1804     PCKEV_B2(RTYPE, in0, in1, in2, in3, out0, out1);                     \
1805     out2 = (RTYPE) __msa_pckev_b((v16i8) in4, (v16i8) in5);              \
1806 }
1807 #define PCKEV_B3_UB(...) PCKEV_B3(v16u8, __VA_ARGS__)
1808 #define PCKEV_B3_SB(...) PCKEV_B3(v16i8, __VA_ARGS__)
1809
1810 #define PCKEV_B4(RTYPE, in0, in1, in2, in3, in4, in5, in6, in7,  \
1811                  out0, out1, out2, out3)                         \
1812 {                                                                \
1813     PCKEV_B2(RTYPE, in0, in1, in2, in3, out0, out1);             \
1814     PCKEV_B2(RTYPE, in4, in5, in6, in7, out2, out3);             \
1815 }
1816 #define PCKEV_B4_SB(...) PCKEV_B4(v16i8, __VA_ARGS__)
1817 #define PCKEV_B4_UB(...) PCKEV_B4(v16u8, __VA_ARGS__)
1818 #define PCKEV_B4_SH(...) PCKEV_B4(v8i16, __VA_ARGS__)
1819 #define PCKEV_B4_SW(...) PCKEV_B4(v4i32, __VA_ARGS__)
1820
1821 /* Description : Pack even halfword elements of vector pairs
1822    Arguments   : Inputs  - in0, in1, in2, in3
1823                  Outputs - out0, out1
1824                  Return Type - as per RTYPE
1825    Details     : Even halfword elements of in0 are copied to the left half of
1826                  out0 & even halfword elements of in1 are copied to the right
1827                  half of out0.
1828                  Even halfword elements of in2 are copied to the left half of
1829                  out1 & even halfword elements of in3 are copied to the right
1830                  half of out1.
1831 */
1832 #define PCKEV_H2(RTYPE, in0, in1, in2, in3, out0, out1)      \
1833 {                                                            \
1834     out0 = (RTYPE) __msa_pckev_h((v8i16) in0, (v8i16) in1);  \
1835     out1 = (RTYPE) __msa_pckev_h((v8i16) in2, (v8i16) in3);  \
1836 }
1837 #define PCKEV_H2_SH(...) PCKEV_H2(v8i16, __VA_ARGS__)
1838 #define PCKEV_H2_SW(...) PCKEV_H2(v4i32, __VA_ARGS__)
1839
1840 #define PCKEV_H4(RTYPE, in0, in1, in2, in3, in4, in5, in6, in7,  \
1841                  out0, out1, out2, out3)                         \
1842 {                                                                \
1843     PCKEV_H2(RTYPE, in0, in1, in2, in3, out0, out1);             \
1844     PCKEV_H2(RTYPE, in4, in5, in6, in7, out2, out3);             \
1845 }
1846 #define PCKEV_H4_SH(...) PCKEV_H4(v8i16, __VA_ARGS__)
1847 #define PCKEV_H4_SW(...) PCKEV_H4(v4i32, __VA_ARGS__)
1848
1849 /* Description : Pack even double word elements of vector pairs
1850    Arguments   : Inputs  - in0, in1, in2, in3
1851                  Outputs - out0, out1
1852                  Return Type - as per RTYPE
1853    Details     : Even double elements of in0 are copied to the left half of
1854                  out0 & even double elements of in1 are copied to the right
1855                  half of out0.
1856                  Even double elements of in2 are copied to the left half of
1857                  out1 & even double elements of in3 are copied to the right
1858                  half of out1.
1859 */
1860 #define PCKEV_D2(RTYPE, in0, in1, in2, in3, out0, out1)      \
1861 {                                                            \
1862     out0 = (RTYPE) __msa_pckev_d((v2i64) in0, (v2i64) in1);  \
1863     out1 = (RTYPE) __msa_pckev_d((v2i64) in2, (v2i64) in3);  \
1864 }
1865 #define PCKEV_D2_UB(...) PCKEV_D2(v16u8, __VA_ARGS__)
1866 #define PCKEV_D2_SB(...) PCKEV_D2(v16i8, __VA_ARGS__)
1867 #define PCKEV_D2_SH(...) PCKEV_D2(v8i16, __VA_ARGS__)
1868
1869 #define PCKEV_D4(RTYPE, in0, in1, in2, in3, in4, in5, in6, in7,  \
1870                  out0, out1, out2, out3)                         \
1871 {                                                                \
1872     PCKEV_D2(RTYPE, in0, in1, in2, in3, out0, out1);             \
1873     PCKEV_D2(RTYPE, in4, in5, in6, in7, out2, out3);             \
1874 }
1875 #define PCKEV_D4_UB(...) PCKEV_D4(v16u8, __VA_ARGS__)
1876
1877 /* Description : Pack odd double word elements of vector pairs
1878    Arguments   : Inputs  - in0, in1
1879                  Outputs - out0, out1
1880                  Return Type - as per RTYPE
1881    Details     : As operation is on same input 'in0' vector, index 1 double word
1882                  element is overwritten to index 0 and result is written to out0
1883                  As operation is on same input 'in1' vector, index 1 double word
1884                  element is overwritten to index 0 and result is written to out1
1885 */
1886 #define PCKOD_D2(RTYPE, in0, in1, in2, in3, out0, out1)      \
1887 {                                                            \
1888     out0 = (RTYPE) __msa_pckod_d((v2i64) in0, (v2i64) in1);  \
1889     out1 = (RTYPE) __msa_pckod_d((v2i64) in2, (v2i64) in3);  \
1890 }
1891 #define PCKOD_D2_UB(...) PCKOD_D2(v16u8, __VA_ARGS__)
1892 #define PCKOD_D2_SH(...) PCKOD_D2(v8i16, __VA_ARGS__)
1893 #define PCKOD_D2_SD(...) PCKOD_D2(v2i64, __VA_ARGS__)
1894
1895 /* Description : Each byte element is logically xor'ed with immediate 128
1896    Arguments   : Inputs  - in0, in1
1897                  Outputs - in0, in1 (in-place)
1898                  Return Type - as per RTYPE
1899    Details     : Each unsigned byte element from input vector 'in0' is
1900                  logically xor'ed with 128 and result is in-place stored in
1901                  'in0' vector
1902                  Each unsigned byte element from input vector 'in1' is
1903                  logically xor'ed with 128 and result is in-place stored in
1904                  'in1' vector
1905                  Similar for other pairs
1906 */
1907 #define XORI_B2_128(RTYPE, in0, in1)               \
1908 {                                                  \
1909     in0 = (RTYPE) __msa_xori_b((v16u8) in0, 128);  \
1910     in1 = (RTYPE) __msa_xori_b((v16u8) in1, 128);  \
1911 }
1912 #define XORI_B2_128_UB(...) XORI_B2_128(v16u8, __VA_ARGS__)
1913 #define XORI_B2_128_SB(...) XORI_B2_128(v16i8, __VA_ARGS__)
1914 #define XORI_B2_128_SH(...) XORI_B2_128(v8i16, __VA_ARGS__)
1915
1916 #define XORI_B3_128(RTYPE, in0, in1, in2)          \
1917 {                                                  \
1918     XORI_B2_128(RTYPE, in0, in1);                  \
1919     in2 = (RTYPE) __msa_xori_b((v16u8) in2, 128);  \
1920 }
1921 #define XORI_B3_128_SB(...) XORI_B3_128(v16i8, __VA_ARGS__)
1922
1923 #define XORI_B4_128(RTYPE, in0, in1, in2, in3)  \
1924 {                                               \
1925     XORI_B2_128(RTYPE, in0, in1);               \
1926     XORI_B2_128(RTYPE, in2, in3);               \
1927 }
1928 #define XORI_B4_128_UB(...) XORI_B4_128(v16u8, __VA_ARGS__)
1929 #define XORI_B4_128_SB(...) XORI_B4_128(v16i8, __VA_ARGS__)
1930 #define XORI_B4_128_SH(...) XORI_B4_128(v8i16, __VA_ARGS__)
1931
1932 #define XORI_B5_128(RTYPE, in0, in1, in2, in3, in4)  \
1933 {                                                    \
1934     XORI_B3_128(RTYPE, in0, in1, in2);               \
1935     XORI_B2_128(RTYPE, in3, in4);                    \
1936 }
1937 #define XORI_B5_128_SB(...) XORI_B5_128(v16i8, __VA_ARGS__)
1938
1939 #define XORI_B6_128(RTYPE, in0, in1, in2, in3, in4, in5)  \
1940 {                                                         \
1941     XORI_B4_128(RTYPE, in0, in1, in2, in3);               \
1942     XORI_B2_128(RTYPE, in4, in5);                         \
1943 }
1944 #define XORI_B6_128_SB(...) XORI_B6_128(v16i8, __VA_ARGS__)
1945
1946 #define XORI_B7_128(RTYPE, in0, in1, in2, in3, in4, in5, in6)  \
1947 {                                                              \
1948     XORI_B4_128(RTYPE, in0, in1, in2, in3);                    \
1949     XORI_B3_128(RTYPE, in4, in5, in6);                         \
1950 }
1951 #define XORI_B7_128_SB(...) XORI_B7_128(v16i8, __VA_ARGS__)
1952
1953 #define XORI_B8_128(RTYPE, in0, in1, in2, in3, in4, in5, in6, in7)  \
1954 {                                                                   \
1955     XORI_B4_128(RTYPE, in0, in1, in2, in3);                         \
1956     XORI_B4_128(RTYPE, in4, in5, in6, in7);                         \
1957 }
1958 #define XORI_B8_128_SB(...) XORI_B8_128(v16i8, __VA_ARGS__)
1959
1960 /* Description : Addition of signed halfword elements and signed saturation
1961    Arguments   : Inputs  - in0, in1, in2, in3
1962                  Outputs - out0, out1
1963                  Return Type - as per RTYPE
1964    Details     : Signed halfword elements from 'in0' are added to signed
1965                  halfword elements of 'in1'. The result is then signed saturated
1966                  between -32768 to +32767 (as per halfword data type)
1967                  Similar for other pairs
1968 */
1969 #define ADDS_SH2(RTYPE, in0, in1, in2, in3, out0, out1)       \
1970 {                                                             \
1971     out0 = (RTYPE) __msa_adds_s_h((v8i16) in0, (v8i16) in1);  \
1972     out1 = (RTYPE) __msa_adds_s_h((v8i16) in2, (v8i16) in3);  \
1973 }
1974 #define ADDS_SH2_SH(...) ADDS_SH2(v8i16, __VA_ARGS__)
1975
1976 #define ADDS_SH4(RTYPE, in0, in1, in2, in3, in4, in5, in6, in7,  \
1977                  out0, out1, out2, out3)                         \
1978 {                                                                \
1979     ADDS_SH2(RTYPE, in0, in1, in2, in3, out0, out1);             \
1980     ADDS_SH2(RTYPE, in4, in5, in6, in7, out2, out3);             \
1981 }
1982 #define ADDS_SH4_UH(...) ADDS_SH4(v8u16, __VA_ARGS__)
1983 #define ADDS_SH4_SH(...) ADDS_SH4(v8i16, __VA_ARGS__)
1984
1985 /* Description : Shift left all elements of vector (generic for all data types)
1986    Arguments   : Inputs  - in0, in1, in2, in3, shift
1987                  Outputs - in0, in1, in2, in3 (in place)
1988                  Return Type - as per input vector RTYPE
1989    Details     : Each element of vector 'in0' is left shifted by 'shift' and
1990                  result is in place written to 'in0'
1991                  Similar for other pairs
1992 */
1993 #define SLLI_2V(in0, in1, shift)  \
1994 {                                 \
1995     in0 = in0 << shift;           \
1996     in1 = in1 << shift;           \
1997 }
1998 #define SLLI_4V(in0, in1, in2, in3, shift)  \
1999 {                                           \
2000     in0 = in0 << shift;                     \
2001     in1 = in1 << shift;                     \
2002     in2 = in2 << shift;                     \
2003     in3 = in3 << shift;                     \
2004 }
2005
2006 /* Description : Arithmetic shift right all elements of vector
2007                  (generic for all data types)
2008    Arguments   : Inputs  - in0, in1, in2, in3, shift
2009                  Outputs - in0, in1, in2, in3 (in place)
2010                  Return Type - as per input vector RTYPE
2011    Details     : Each element of vector 'in0' is right shifted by 'shift' and
2012                  result is in place written to 'in0'
2013                  Here, 'shift' is GP variable passed in
2014                  Similar for other pairs
2015 */
2016 #define SRA_4V(in0, in1, in2, in3, shift)  \
2017 {                                          \
2018     in0 = in0 >> shift;                    \
2019     in1 = in1 >> shift;                    \
2020     in2 = in2 >> shift;                    \
2021     in3 = in3 >> shift;                    \
2022 }
2023
2024 /* Description : Shift right logical all halfword elements of vector
2025    Arguments   : Inputs  - in0, in1, in2, in3, shift
2026                  Outputs - in0, in1, in2, in3 (in place)
2027                  Return Type - as per RTYPE
2028    Details     : Each element of vector 'in0' is shifted right logical by
2029                  number of bits respective element holds in vector 'shift' and
2030                  result is in place written to 'in0'
2031                  Here, 'shift' is a vector passed in
2032                  Similar for other pairs
2033 */
2034 #define SRL_H4(RTYPE, in0, in1, in2, in3, shift)            \
2035 {                                                           \
2036     in0 = (RTYPE) __msa_srl_h((v8i16) in0, (v8i16) shift);  \
2037     in1 = (RTYPE) __msa_srl_h((v8i16) in1, (v8i16) shift);  \
2038     in2 = (RTYPE) __msa_srl_h((v8i16) in2, (v8i16) shift);  \
2039     in3 = (RTYPE) __msa_srl_h((v8i16) in3, (v8i16) shift);  \
2040 }
2041 #define SRL_H4_UH(...) SRL_H4(v8u16, __VA_ARGS__)
2042
2043 /* Description : Shift right arithmetic rounded halfwords
2044    Arguments   : Inputs  - in0, in1, shift
2045                  Outputs - in0, in1, (in place)
2046                  Return Type - as per RTYPE
2047    Details     : Each element of vector 'in0' is shifted right arithmetic by
2048                  number of bits respective element holds in vector 'shift'.
2049                  The last discarded bit is added to shifted value for rounding
2050                  and the result is in place written to 'in0'
2051                  Here, 'shift' is a vector passed in
2052                  Similar for other pairs
2053 */
2054 #define SRAR_H2(RTYPE, in0, in1, shift)                      \
2055 {                                                            \
2056     in0 = (RTYPE) __msa_srar_h((v8i16) in0, (v8i16) shift);  \
2057     in1 = (RTYPE) __msa_srar_h((v8i16) in1, (v8i16) shift);  \
2058 }
2059 #define SRAR_H2_UH(...) SRAR_H2(v8u16, __VA_ARGS__)
2060 #define SRAR_H2_SH(...) SRAR_H2(v8i16, __VA_ARGS__)
2061
2062 #define SRAR_H3(RTYPE, in0, in1, in2, shift)                 \
2063 {                                                            \
2064     SRAR_H2(RTYPE, in0, in1, shift)                          \
2065     in2 = (RTYPE) __msa_srar_h((v8i16) in2, (v8i16) shift);  \
2066 }
2067 #define SRAR_H3_SH(...) SRAR_H3(v8i16, __VA_ARGS__)
2068
2069 #define SRAR_H4(RTYPE, in0, in1, in2, in3, shift)  \
2070 {                                                  \
2071     SRAR_H2(RTYPE, in0, in1, shift)                \
2072     SRAR_H2(RTYPE, in2, in3, shift)                \
2073 }
2074 #define SRAR_H4_UH(...) SRAR_H4(v8u16, __VA_ARGS__)
2075 #define SRAR_H4_SH(...) SRAR_H4(v8i16, __VA_ARGS__)
2076
2077 /* Description : Shift right arithmetic rounded words
2078    Arguments   : Inputs  - in0, in1, shift
2079                  Outputs - in0, in1, (in place)
2080                  Return Type - as per RTYPE
2081    Details     : Each element of vector 'in0' is shifted right arithmetic by
2082                  number of bits respective element holds in vector 'shift'.
2083                  The last discarded bit is added to shifted value for rounding
2084                  and the result is in place written to 'in0'
2085                  Here, 'shift' is a vector passed in
2086                  Similar for other pairs
2087 */
2088 #define SRAR_W2(RTYPE, in0, in1, shift)                      \
2089 {                                                            \
2090     in0 = (RTYPE) __msa_srar_w((v4i32) in0, (v4i32) shift);  \
2091     in1 = (RTYPE) __msa_srar_w((v4i32) in1, (v4i32) shift);  \
2092 }
2093 #define SRAR_W2_SW(...) SRAR_W2(v4i32, __VA_ARGS__)
2094
2095 #define SRAR_W4(RTYPE, in0, in1, in2, in3, shift)  \
2096 {                                                  \
2097     SRAR_W2(RTYPE, in0, in1, shift)                \
2098     SRAR_W2(RTYPE, in2, in3, shift)                \
2099 }
2100 #define SRAR_W4_SW(...) SRAR_W4(v4i32, __VA_ARGS__)
2101
2102 /* Description : Shift right arithmetic rounded (immediate)
2103    Arguments   : Inputs  - in0, in1, in2, in3, shift
2104                  Outputs - in0, in1, in2, in3 (in place)
2105                  Return Type - as per RTYPE
2106    Details     : Each element of vector 'in0' is shifted right arithmetic by
2107                  value in 'shift'.
2108                  The last discarded bit is added to shifted value for rounding
2109                  and the result is in place written to 'in0'
2110                  Similar for other pairs
2111 */
2112 #define SRARI_H2(RTYPE, in0, in1, shift)              \
2113 {                                                     \
2114     in0 = (RTYPE) __msa_srari_h((v8i16) in0, shift);  \
2115     in1 = (RTYPE) __msa_srari_h((v8i16) in1, shift);  \
2116 }
2117 #define SRARI_H2_UH(...) SRARI_H2(v8u16, __VA_ARGS__)
2118 #define SRARI_H2_SH(...) SRARI_H2(v8i16, __VA_ARGS__)
2119
2120 #define SRARI_H4(RTYPE, in0, in1, in2, in3, shift)    \
2121 {                                                     \
2122     SRARI_H2(RTYPE, in0, in1, shift);                 \
2123     SRARI_H2(RTYPE, in2, in3, shift);                 \
2124 }
2125 #define SRARI_H4_UH(...) SRARI_H4(v8u16, __VA_ARGS__)
2126 #define SRARI_H4_SH(...) SRARI_H4(v8i16, __VA_ARGS__)
2127
2128 /* Description : Shift right arithmetic rounded (immediate)
2129    Arguments   : Inputs  - in0, in1, shift
2130                  Outputs - in0, in1     (in place)
2131                  Return Type - as per RTYPE
2132    Details     : Each element of vector 'in0' is shifted right arithmetic by
2133                  value in 'shift'.
2134                  The last discarded bit is added to shifted value for rounding
2135                  and the result is in place written to 'in0'
2136                  Similar for other pairs
2137 */
2138 #define SRARI_W2(RTYPE, in0, in1, shift)              \
2139 {                                                     \
2140     in0 = (RTYPE) __msa_srari_w((v4i32) in0, shift);  \
2141     in1 = (RTYPE) __msa_srari_w((v4i32) in1, shift);  \
2142 }
2143 #define SRARI_W2_SW(...) SRARI_W2(v4i32, __VA_ARGS__)
2144
2145 #define SRARI_W4(RTYPE, in0, in1, in2, in3, shift)  \
2146 {                                                   \
2147     SRARI_W2(RTYPE, in0, in1, shift);               \
2148     SRARI_W2(RTYPE, in2, in3, shift);               \
2149 }
2150 #define SRARI_W4_SH(...) SRARI_W4(v8i16, __VA_ARGS__)
2151 #define SRARI_W4_SW(...) SRARI_W4(v4i32, __VA_ARGS__)
2152
2153 /* Description : Multiplication of pairs of vectors
2154    Arguments   : Inputs  - in0, in1, in2, in3
2155                  Outputs - out0, out1
2156    Details     : Each element from 'in0' is multiplied with elements from 'in1'
2157                  and result is written to 'out0'
2158                  Similar for other pairs
2159 */
2160 #define MUL2(in0, in1, in2, in3, out0, out1)  \
2161 {                                             \
2162     out0 = in0 * in1;                         \
2163     out1 = in2 * in3;                         \
2164 }
2165 #define MUL4(in0, in1, in2, in3, in4, in5, in6, in7, out0, out1, out2, out3)  \
2166 {                                                                             \
2167     MUL2(in0, in1, in2, in3, out0, out1);                                     \
2168     MUL2(in4, in5, in6, in7, out2, out3);                                     \
2169 }
2170
2171 /* Description : Addition of 2 pairs of vectors
2172    Arguments   : Inputs  - in0, in1, in2, in3
2173                  Outputs - out0, out1
2174    Details     : Each element from 2 pairs vectors is added and 2 results are
2175                  produced
2176 */
2177 #define ADD2(in0, in1, in2, in3, out0, out1)  \
2178 {                                             \
2179     out0 = in0 + in1;                         \
2180     out1 = in2 + in3;                         \
2181 }
2182 #define ADD4(in0, in1, in2, in3, in4, in5, in6, in7, out0, out1, out2, out3)  \
2183 {                                                                             \
2184     ADD2(in0, in1, in2, in3, out0, out1);                                     \
2185     ADD2(in4, in5, in6, in7, out2, out3);                                     \
2186 }
2187
2188 /* Description : Subtraction of 2 pairs of vectors
2189    Arguments   : Inputs  - in0, in1, in2, in3
2190                  Outputs - out0, out1
2191    Details     : Each element from 2 pairs vectors is subtracted and 2 results
2192                  are produced
2193 */
2194 #define SUB2(in0, in1, in2, in3, out0, out1)  \
2195 {                                             \
2196     out0 = in0 - in1;                         \
2197     out1 = in2 - in3;                         \
2198 }
2199 #define SUB4(in0, in1, in2, in3, in4, in5, in6, in7, out0, out1, out2, out3)  \
2200 {                                                                             \
2201     out0 = in0 - in1;                                                         \
2202     out1 = in2 - in3;                                                         \
2203     out2 = in4 - in5;                                                         \
2204     out3 = in6 - in7;                                                         \
2205 }
2206
2207 /* Description : Sign extend halfword elements from right half of the vector
2208    Arguments   : Inputs  - in    (input halfword vector)
2209                  Outputs - out   (sign extended word vectors)
2210                  Return Type - signed word
2211    Details     : Sign bit of halfword elements from input vector 'in' is
2212                  extracted and interleaved with same vector 'in0' to generate
2213                  4 word elements keeping sign intact
2214 */
2215 #define UNPCK_R_SH_SW(in, out)                       \
2216 {                                                    \
2217     v8i16 sign_m;                                    \
2218                                                      \
2219     sign_m = __msa_clti_s_h((v8i16) in, 0);          \
2220     out = (v4i32) __msa_ilvr_h(sign_m, (v8i16) in);  \
2221 }
2222
2223 /* Description : Sign extend byte elements from input vector and return
2224                  halfword results in pair of vectors
2225    Arguments   : Inputs  - in           (1 input byte vector)
2226                  Outputs - out0, out1   (sign extended 2 halfword vectors)
2227                  Return Type - signed halfword
2228    Details     : Sign bit of byte elements from input vector 'in' is
2229                  extracted and interleaved right with same vector 'in0' to
2230                  generate 8 signed halfword elements in 'out0'
2231                  Then interleaved left with same vector 'in0' to
2232                  generate 8 signed halfword elements in 'out1'
2233 */
2234 #define UNPCK_SB_SH(in, out0, out1)                  \
2235 {                                                    \
2236     v16i8 tmp_m;                                     \
2237                                                      \
2238     tmp_m = __msa_clti_s_b((v16i8) in, 0);           \
2239     ILVRL_B2_SH(tmp_m, in, out0, out1);              \
2240 }
2241
2242 /* Description : Zero extend unsigned byte elements to halfword elements
2243    Arguments   : Inputs  - in           (1 input unsigned byte vector)
2244                  Outputs - out0, out1   (unsigned 2 halfword vectors)
2245                  Return Type - signed halfword
2246    Details     : Zero extended right half of vector is returned in 'out0'
2247                  Zero extended left half of vector is returned in 'out1'
2248 */
2249 #define UNPCK_UB_SH(in, out0, out1)                   \
2250 {                                                     \
2251     v16i8 zero_m = { 0 };                             \
2252                                                       \
2253     ILVRL_B2_SH(zero_m, in, out0, out1);              \
2254 }
2255
2256 /* Description : Sign extend halfword elements from input vector and return
2257                  result in pair of vectors
2258    Arguments   : Inputs  - in           (1 input halfword vector)
2259                  Outputs - out0, out1   (sign extended 2 word vectors)
2260                  Return Type - signed word
2261    Details     : Sign bit of halfword elements from input vector 'in' is
2262                  extracted and interleaved right with same vector 'in0' to
2263                  generate 4 signed word elements in 'out0'
2264                  Then interleaved left with same vector 'in0' to
2265                  generate 4 signed word elements in 'out1'
2266 */
2267 #define UNPCK_SH_SW(in, out0, out1)                  \
2268 {                                                    \
2269     v8i16 tmp_m;                                     \
2270                                                      \
2271     tmp_m = __msa_clti_s_h((v8i16) in, 0);           \
2272     ILVRL_H2_SW(tmp_m, in, out0, out1);              \
2273 }
2274
2275 /* Description : Swap two variables
2276    Arguments   : Inputs  - in0, in1
2277                  Outputs - in0, in1 (in-place)
2278    Details     : Swapping of two input variables using xor
2279 */
2280 #define SWAP(in0, in1)  \
2281 {                       \
2282     in0 = in0 ^ in1;    \
2283     in1 = in0 ^ in1;    \
2284     in0 = in0 ^ in1;    \
2285 }
2286
2287 /* Description : Butterfly of 4 input vectors
2288    Arguments   : Inputs  - in0, in1, in2, in3
2289                  Outputs - out0, out1, out2, out3
2290    Details     : Butterfly operation
2291 */
2292 #define BUTTERFLY_4(in0, in1, in2, in3, out0, out1, out2, out3)  \
2293 {                                                                \
2294     out0 = in0 + in3;                                            \
2295     out1 = in1 + in2;                                            \
2296                                                                  \
2297     out2 = in1 - in2;                                            \
2298     out3 = in0 - in3;                                            \
2299 }
2300
2301 /* Description : Butterfly of 8 input vectors
2302    Arguments   : Inputs  - in0 ...  in7
2303                  Outputs - out0 .. out7
2304    Details     : Butterfly operation
2305 */
2306 #define BUTTERFLY_8(in0, in1, in2, in3, in4, in5, in6, in7,          \
2307                     out0, out1, out2, out3, out4, out5, out6, out7)  \
2308 {                                                                    \
2309     out0 = in0 + in7;                                                \
2310     out1 = in1 + in6;                                                \
2311     out2 = in2 + in5;                                                \
2312     out3 = in3 + in4;                                                \
2313                                                                      \
2314     out4 = in3 - in4;                                                \
2315     out5 = in2 - in5;                                                \
2316     out6 = in1 - in6;                                                \
2317     out7 = in0 - in7;                                                \
2318 }
2319
2320 /* Description : Butterfly of 16 input vectors
2321    Arguments   : Inputs  - in0 ...  in15
2322                  Outputs - out0 .. out15
2323    Details     : Butterfly operation
2324 */
2325 #define BUTTERFLY_16(in0, in1, in2, in3, in4, in5, in6, in7,                \
2326                      in8, in9,  in10, in11, in12, in13, in14, in15,         \
2327                      out0, out1, out2, out3, out4, out5, out6, out7,        \
2328                      out8, out9, out10, out11, out12, out13, out14, out15)  \
2329 {                                                                           \
2330     out0 = in0 + in15;                                                      \
2331     out1 = in1 + in14;                                                      \
2332     out2 = in2 + in13;                                                      \
2333     out3 = in3 + in12;                                                      \
2334     out4 = in4 + in11;                                                      \
2335     out5 = in5 + in10;                                                      \
2336     out6 = in6 + in9;                                                       \
2337     out7 = in7 + in8;                                                       \
2338                                                                             \
2339     out8 = in7 - in8;                                                       \
2340     out9 = in6 - in9;                                                       \
2341     out10 = in5 - in10;                                                     \
2342     out11 = in4 - in11;                                                     \
2343     out12 = in3 - in12;                                                     \
2344     out13 = in2 - in13;                                                     \
2345     out14 = in1 - in14;                                                     \
2346     out15 = in0 - in15;                                                     \
2347 }
2348
2349 /* Description : Transposes input 4x4 byte block
2350    Arguments   : Inputs  - in0, in1, in2, in3      (input 4x4 byte block)
2351                  Outputs - out0, out1, out2, out3  (output 4x4 byte block)
2352                  Return Type - unsigned byte
2353    Details     :
2354 */
2355 #define TRANSPOSE4x4_UB_UB(in0, in1, in2, in3, out0, out1, out2, out3)  \
2356 {                                                                       \
2357     v16i8 zero_m = { 0 };                                               \
2358     v16i8 s0_m, s1_m, s2_m, s3_m;                                       \
2359                                                                         \
2360     ILVR_D2_SB(in1, in0, in3, in2, s0_m, s1_m);                         \
2361     ILVRL_B2_SB(s1_m, s0_m, s2_m, s3_m);                                \
2362                                                                         \
2363     out0 = (v16u8) __msa_ilvr_b(s3_m, s2_m);                            \
2364     out1 = (v16u8) __msa_sldi_b(zero_m, (v16i8) out0, 4);               \
2365     out2 = (v16u8) __msa_sldi_b(zero_m, (v16i8) out1, 4);               \
2366     out3 = (v16u8) __msa_sldi_b(zero_m, (v16i8) out2, 4);               \
2367 }
2368
2369 /* Description : Transposes input 8x4 byte block into 4x8
2370    Arguments   : Inputs  - in0, in1, in2, in3      (input 8x4 byte block)
2371                  Outputs - out0, out1, out2, out3  (output 4x8 byte block)
2372                  Return Type - as per RTYPE
2373    Details     :
2374 */
2375 #define TRANSPOSE8x4_UB(RTYPE, in0, in1, in2, in3, in4, in5, in6, in7,  \
2376                         out0, out1, out2, out3)                         \
2377 {                                                                       \
2378     v16i8 tmp0_m, tmp1_m, tmp2_m, tmp3_m;                               \
2379                                                                         \
2380     ILVEV_W2_SB(in0, in4, in1, in5, tmp0_m, tmp1_m);                    \
2381     tmp2_m = __msa_ilvr_b(tmp1_m, tmp0_m);                              \
2382     ILVEV_W2_SB(in2, in6, in3, in7, tmp0_m, tmp1_m);                    \
2383                                                                         \
2384     tmp3_m = __msa_ilvr_b(tmp1_m, tmp0_m);                              \
2385     ILVRL_H2_SB(tmp3_m, tmp2_m, tmp0_m, tmp1_m);                        \
2386                                                                         \
2387     ILVRL_W2(RTYPE, tmp1_m, tmp0_m, out0, out2);                        \
2388     out1 = (RTYPE) __msa_ilvl_d((v2i64) out2, (v2i64) out0);            \
2389     out3 = (RTYPE) __msa_ilvl_d((v2i64) out0, (v2i64) out2);            \
2390 }
2391 #define TRANSPOSE8x4_UB_UB(...) TRANSPOSE8x4_UB(v16u8, __VA_ARGS__)
2392 #define TRANSPOSE8x4_UB_UH(...) TRANSPOSE8x4_UB(v8u16, __VA_ARGS__)
2393
2394 /* Description : Transposes input 8x8 byte block
2395    Arguments   : Inputs  - in0, in1, in2, in3, in4, in5, in6, in7
2396                            (input 8x8 byte block)
2397                  Outputs - out0, out1, out2, out3, out4, out5, out6, out7
2398                            (output 8x8 byte block)
2399                  Return Type - as per RTYPE
2400    Details     :
2401 */
2402 #define TRANSPOSE8x8_UB(RTYPE, in0, in1, in2, in3, in4, in5, in6, in7,   \
2403                         out0, out1, out2, out3, out4, out5, out6, out7)  \
2404 {                                                                        \
2405     v16i8 tmp0_m, tmp1_m, tmp2_m, tmp3_m;                                \
2406     v16i8 tmp4_m, tmp5_m, tmp6_m, tmp7_m;                                \
2407                                                                          \
2408     ILVR_B4_SB(in2, in0, in3, in1, in6, in4, in7, in5,                   \
2409                tmp0_m, tmp1_m, tmp2_m, tmp3_m);                          \
2410     ILVRL_B2_SB(tmp1_m, tmp0_m, tmp4_m, tmp5_m);                         \
2411     ILVRL_B2_SB(tmp3_m, tmp2_m, tmp6_m, tmp7_m);                         \
2412     ILVRL_W2(RTYPE, tmp6_m, tmp4_m, out0, out2);                         \
2413     ILVRL_W2(RTYPE, tmp7_m, tmp5_m, out4, out6);                         \
2414     SLDI_B2_0(RTYPE, out0, out2, out1, out3, 8);                         \
2415     SLDI_B2_0(RTYPE, out4, out6, out5, out7, 8);                         \
2416 }
2417 #define TRANSPOSE8x8_UB_UB(...) TRANSPOSE8x8_UB(v16u8, __VA_ARGS__)
2418 #define TRANSPOSE8x8_UB_UH(...) TRANSPOSE8x8_UB(v8u16, __VA_ARGS__)
2419
2420 /* Description : Transposes 16x4 block into 4x16 with byte elements in vectors
2421    Arguments   : Inputs  - in0, in1, in2, in3, in4, in5, in6, in7,
2422                            in8, in9, in10, in11, in12, in13, in14, in15
2423                  Outputs - out0, out1, out2, out3
2424                  Return Type - unsigned byte
2425    Details     :
2426 */
2427 #define TRANSPOSE16x4_UB_UB(in0, in1, in2, in3, in4, in5, in6, in7,        \
2428                             in8, in9, in10, in11, in12, in13, in14, in15,  \
2429                             out0, out1, out2, out3)                        \
2430 {                                                                          \
2431     v2i64 tmp0_m, tmp1_m, tmp2_m, tmp3_m;                                  \
2432                                                                            \
2433     ILVEV_W2_SD(in0, in4, in8, in12, tmp0_m, tmp1_m);                      \
2434     out1 = (v16u8) __msa_ilvev_d(tmp1_m, tmp0_m);                          \
2435                                                                            \
2436     ILVEV_W2_SD(in1, in5, in9, in13, tmp0_m, tmp1_m);                      \
2437     out3 = (v16u8) __msa_ilvev_d(tmp1_m, tmp0_m);                          \
2438                                                                            \
2439     ILVEV_W2_SD(in2, in6, in10, in14, tmp0_m, tmp1_m);                     \
2440                                                                            \
2441     tmp2_m = __msa_ilvev_d(tmp1_m, tmp0_m);                                \
2442     ILVEV_W2_SD(in3, in7, in11, in15, tmp0_m, tmp1_m);                     \
2443                                                                            \
2444     tmp3_m = __msa_ilvev_d(tmp1_m, tmp0_m);                                \
2445     ILVEV_B2_SD(out1, out3, tmp2_m, tmp3_m, tmp0_m, tmp1_m);               \
2446     out0 = (v16u8) __msa_ilvev_h((v8i16) tmp1_m, (v8i16) tmp0_m);          \
2447     out2 = (v16u8) __msa_ilvod_h((v8i16) tmp1_m, (v8i16) tmp0_m);          \
2448                                                                            \
2449     tmp0_m = (v2i64) __msa_ilvod_b((v16i8) out3, (v16i8) out1);            \
2450     tmp1_m = (v2i64) __msa_ilvod_b((v16i8) tmp3_m, (v16i8) tmp2_m);        \
2451     out1 = (v16u8) __msa_ilvev_h((v8i16) tmp1_m, (v8i16) tmp0_m);          \
2452     out3 = (v16u8) __msa_ilvod_h((v8i16) tmp1_m, (v8i16) tmp0_m);          \
2453 }
2454
2455 /* Description : Transposes 16x8 block into 8x16 with byte elements in vectors
2456    Arguments   : Inputs  - in0, in1, in2, in3, in4, in5, in6, in7,
2457                            in8, in9, in10, in11, in12, in13, in14, in15
2458                  Outputs - out0, out1, out2, out3, out4, out5, out6, out7
2459                  Return Type - unsigned byte
2460    Details     :
2461 */
2462 #define TRANSPOSE16x8_UB_UB(in0, in1, in2, in3, in4, in5, in6, in7,          \
2463                             in8, in9, in10, in11, in12, in13, in14, in15,    \
2464                             out0, out1, out2, out3, out4, out5, out6, out7)  \
2465 {                                                                            \
2466     v16u8 tmp0_m, tmp1_m, tmp2_m, tmp3_m;                                    \
2467     v16u8 tmp4_m, tmp5_m, tmp6_m, tmp7_m;                                    \
2468                                                                              \
2469     ILVEV_D2_UB(in0, in8, in1, in9, out7, out6);                             \
2470     ILVEV_D2_UB(in2, in10, in3, in11, out5, out4);                           \
2471     ILVEV_D2_UB(in4, in12, in5, in13, out3, out2);                           \
2472     ILVEV_D2_UB(in6, in14, in7, in15, out1, out0);                           \
2473                                                                              \
2474     tmp0_m = (v16u8) __msa_ilvev_b((v16i8) out6, (v16i8) out7);              \
2475     tmp4_m = (v16u8) __msa_ilvod_b((v16i8) out6, (v16i8) out7);              \
2476     tmp1_m = (v16u8) __msa_ilvev_b((v16i8) out4, (v16i8) out5);              \
2477     tmp5_m = (v16u8) __msa_ilvod_b((v16i8) out4, (v16i8) out5);              \
2478     out5 = (v16u8) __msa_ilvev_b((v16i8) out2, (v16i8) out3);                \
2479     tmp6_m = (v16u8) __msa_ilvod_b((v16i8) out2, (v16i8) out3);              \
2480     out7 = (v16u8) __msa_ilvev_b((v16i8) out0, (v16i8) out1);                \
2481     tmp7_m = (v16u8) __msa_ilvod_b((v16i8) out0, (v16i8) out1);              \
2482                                                                              \
2483     ILVEV_H2_UB(tmp0_m, tmp1_m, out5, out7, tmp2_m, tmp3_m);                 \
2484     out0 = (v16u8) __msa_ilvev_w((v4i32) tmp3_m, (v4i32) tmp2_m);            \
2485     out4 = (v16u8) __msa_ilvod_w((v4i32) tmp3_m, (v4i32) tmp2_m);            \
2486                                                                              \
2487     tmp2_m = (v16u8) __msa_ilvod_h((v8i16) tmp1_m, (v8i16) tmp0_m);          \
2488     tmp3_m = (v16u8) __msa_ilvod_h((v8i16) out7, (v8i16) out5);              \
2489     out2 = (v16u8) __msa_ilvev_w((v4i32) tmp3_m, (v4i32) tmp2_m);            \
2490     out6 = (v16u8) __msa_ilvod_w((v4i32) tmp3_m, (v4i32) tmp2_m);            \
2491                                                                              \
2492     ILVEV_H2_UB(tmp4_m, tmp5_m, tmp6_m, tmp7_m, tmp2_m, tmp3_m);             \
2493     out1 = (v16u8) __msa_ilvev_w((v4i32) tmp3_m, (v4i32) tmp2_m);            \
2494     out5 = (v16u8) __msa_ilvod_w((v4i32) tmp3_m, (v4i32) tmp2_m);            \
2495                                                                              \
2496     tmp2_m = (v16u8) __msa_ilvod_h((v8i16) tmp5_m, (v8i16) tmp4_m);          \
2497     tmp2_m = (v16u8) __msa_ilvod_h((v8i16) tmp5_m, (v8i16) tmp4_m);          \
2498     tmp3_m = (v16u8) __msa_ilvod_h((v8i16) tmp7_m, (v8i16) tmp6_m);          \
2499     tmp3_m = (v16u8) __msa_ilvod_h((v8i16) tmp7_m, (v8i16) tmp6_m);          \
2500     out3 = (v16u8) __msa_ilvev_w((v4i32) tmp3_m, (v4i32) tmp2_m);            \
2501     out7 = (v16u8) __msa_ilvod_w((v4i32) tmp3_m, (v4i32) tmp2_m);            \
2502 }
2503
2504 /* Description : Transposes 4x4 block with half word elements in vectors
2505    Arguments   : Inputs  - in0, in1, in2, in3
2506                  Outputs - out0, out1, out2, out3
2507                  Return Type - signed halfword
2508    Details     :
2509 */
2510 #define TRANSPOSE4x4_SH_SH(in0, in1, in2, in3, out0, out1, out2, out3)  \
2511 {                                                                       \
2512     v8i16 s0_m, s1_m;                                                   \
2513                                                                         \
2514     ILVR_H2_SH(in1, in0, in3, in2, s0_m, s1_m);                         \
2515     ILVRL_W2_SH(s1_m, s0_m, out0, out2);                                \
2516     out1 = (v8i16) __msa_ilvl_d((v2i64) out0, (v2i64) out0);            \
2517     out3 = (v8i16) __msa_ilvl_d((v2i64) out0, (v2i64) out2);            \
2518 }
2519
2520 /* Description : Transposes 8x8 block with half word elements in vectors
2521    Arguments   : Inputs  - in0, in1, in2, in3, in4, in5, in6, in7
2522                  Outputs - out0, out1, out2, out3, out4, out5, out6, out7
2523                  Return Type - as per RTYPE
2524    Details     :
2525 */
2526 #define TRANSPOSE8x8_H(RTYPE, in0, in1, in2, in3, in4, in5, in6, in7,   \
2527                        out0, out1, out2, out3, out4, out5, out6, out7)  \
2528 {                                                                       \
2529     v8i16 s0_m, s1_m;                                                   \
2530     v8i16 tmp0_m, tmp1_m, tmp2_m, tmp3_m;                               \
2531     v8i16 tmp4_m, tmp5_m, tmp6_m, tmp7_m;                               \
2532                                                                         \
2533     ILVR_H2_SH(in6, in4, in7, in5, s0_m, s1_m);                         \
2534     ILVRL_H2_SH(s1_m, s0_m, tmp0_m, tmp1_m);                            \
2535     ILVL_H2_SH(in6, in4, in7, in5, s0_m, s1_m);                         \
2536     ILVRL_H2_SH(s1_m, s0_m, tmp2_m, tmp3_m);                            \
2537     ILVR_H2_SH(in2, in0, in3, in1, s0_m, s1_m);                         \
2538     ILVRL_H2_SH(s1_m, s0_m, tmp4_m, tmp5_m);                            \
2539     ILVL_H2_SH(in2, in0, in3, in1, s0_m, s1_m);                         \
2540     ILVRL_H2_SH(s1_m, s0_m, tmp6_m, tmp7_m);                            \
2541     PCKEV_D4(RTYPE, tmp0_m, tmp4_m, tmp1_m, tmp5_m, tmp2_m, tmp6_m,     \
2542              tmp3_m, tmp7_m, out0, out2, out4, out6);                   \
2543     out1 = (RTYPE) __msa_pckod_d((v2i64) tmp0_m, (v2i64) tmp4_m);       \
2544     out3 = (RTYPE) __msa_pckod_d((v2i64) tmp1_m, (v2i64) tmp5_m);       \
2545     out5 = (RTYPE) __msa_pckod_d((v2i64) tmp2_m, (v2i64) tmp6_m);       \
2546     out7 = (RTYPE) __msa_pckod_d((v2i64) tmp3_m, (v2i64) tmp7_m);       \
2547 }
2548 #define TRANSPOSE8x8_UH_UH(...) TRANSPOSE8x8_H(v8u16, __VA_ARGS__)
2549 #define TRANSPOSE8x8_SH_SH(...) TRANSPOSE8x8_H(v8i16, __VA_ARGS__)
2550
2551 /* Description : Transposes 4x4 block with word elements in vectors
2552    Arguments   : Inputs  - in0, in1, in2, in3
2553                  Outputs - out0, out1, out2, out3
2554                  Return Type - signed word
2555    Details     :
2556 */
2557 #define TRANSPOSE4x4_SW_SW(in0, in1, in2, in3, out0, out1, out2, out3)  \
2558 {                                                                       \
2559     v4i32 s0_m, s1_m, s2_m, s3_m;                                       \
2560                                                                         \
2561     ILVRL_W2_SW(in1, in0, s0_m, s1_m);                                  \
2562     ILVRL_W2_SW(in3, in2, s2_m, s3_m);                                  \
2563                                                                         \
2564     out0 = (v4i32) __msa_ilvr_d((v2i64) s2_m, (v2i64) s0_m);            \
2565     out1 = (v4i32) __msa_ilvl_d((v2i64) s2_m, (v2i64) s0_m);            \
2566     out2 = (v4i32) __msa_ilvr_d((v2i64) s3_m, (v2i64) s1_m);            \
2567     out3 = (v4i32) __msa_ilvl_d((v2i64) s3_m, (v2i64) s1_m);            \
2568 }
2569
2570 /* Description : Average byte elements from pair of vectors and store 8x4 byte
2571                  block in destination memory
2572    Arguments   : Inputs  - in0, in1, in2, in3, in4, in5, in6, in7, pdst, stride
2573    Details     : Each byte element from input vector pair 'in0' and 'in1' are
2574                  averaged (a + b)/2 and stored in 'tmp0_m'
2575                  Each byte element from input vector pair 'in2' and 'in3' are
2576                  averaged (a + b)/2 and stored in 'tmp1_m'
2577                  Each byte element from input vector pair 'in4' and 'in5' are
2578                  averaged (a + b)/2 and stored in 'tmp2_m'
2579                  Each byte element from input vector pair 'in6' and 'in7' are
2580                  averaged (a + b)/2 and stored in 'tmp3_m'
2581                  The half vector results from all 4 vectors are stored in
2582                  destination memory as 8x4 byte block
2583 */
2584 #define AVE_ST8x4_UB(in0, in1, in2, in3, in4, in5, in6, in7, pdst, stride)  \
2585 {                                                                           \
2586     uint64_t out0_m, out1_m, out2_m, out3_m;                                \
2587     v16u8 tmp0_m, tmp1_m, tmp2_m, tmp3_m;                                   \
2588                                                                             \
2589     tmp0_m = __msa_ave_u_b((v16u8) in0, (v16u8) in1);                       \
2590     tmp1_m = __msa_ave_u_b((v16u8) in2, (v16u8) in3);                       \
2591     tmp2_m = __msa_ave_u_b((v16u8) in4, (v16u8) in5);                       \
2592     tmp3_m = __msa_ave_u_b((v16u8) in6, (v16u8) in7);                       \
2593                                                                             \
2594     out0_m = __msa_copy_u_d((v2i64) tmp0_m, 0);                             \
2595     out1_m = __msa_copy_u_d((v2i64) tmp1_m, 0);                             \
2596     out2_m = __msa_copy_u_d((v2i64) tmp2_m, 0);                             \
2597     out3_m = __msa_copy_u_d((v2i64) tmp3_m, 0);                             \
2598     SD4(out0_m, out1_m, out2_m, out3_m, pdst, stride);                      \
2599 }
2600
2601 /* Description : Average byte elements from pair of vectors and store 16x4 byte
2602                  block in destination memory
2603    Arguments   : Inputs  - in0, in1, in2, in3, in4, in5, in6, in7, pdst, stride
2604    Details     : Each byte element from input vector pair 'in0' and 'in1' are
2605                  averaged (a + b)/2 and stored in 'tmp0_m'
2606                  Each byte element from input vector pair 'in2' and 'in3' are
2607                  averaged (a + b)/2 and stored in 'tmp1_m'
2608                  Each byte element from input vector pair 'in4' and 'in5' are
2609                  averaged (a + b)/2 and stored in 'tmp2_m'
2610                  Each byte element from input vector pair 'in6' and 'in7' are
2611                  averaged (a + b)/2 and stored in 'tmp3_m'
2612                  The results from all 4 vectors are stored in destination
2613                  memory as 16x4 byte block
2614 */
2615 #define AVE_ST16x4_UB(in0, in1, in2, in3, in4, in5, in6, in7, pdst, stride)  \
2616 {                                                                            \
2617     v16u8 tmp0_m, tmp1_m, tmp2_m, tmp3_m;                                    \
2618                                                                              \
2619     tmp0_m = __msa_ave_u_b((v16u8) in0, (v16u8) in1);                        \
2620     tmp1_m = __msa_ave_u_b((v16u8) in2, (v16u8) in3);                        \
2621     tmp2_m = __msa_ave_u_b((v16u8) in4, (v16u8) in5);                        \
2622     tmp3_m = __msa_ave_u_b((v16u8) in6, (v16u8) in7);                        \
2623                                                                              \
2624     ST_UB4(tmp0_m, tmp1_m, tmp2_m, tmp3_m, pdst, stride);                    \
2625 }
2626
2627 /* Description : Average rounded byte elements from pair of vectors and store
2628                  8x4 byte block in destination memory
2629    Arguments   : Inputs  - in0, in1, in2, in3, in4, in5, in6, in7, pdst, stride
2630    Details     : Each byte element from input vector pair 'in0' and 'in1' are
2631                  average rounded (a + b + 1)/2 and stored in 'tmp0_m'
2632                  Each byte element from input vector pair 'in2' and 'in3' are
2633                  average rounded (a + b + 1)/2 and stored in 'tmp1_m'
2634                  Each byte element from input vector pair 'in4' and 'in5' are
2635                  average rounded (a + b + 1)/2 and stored in 'tmp2_m'
2636                  Each byte element from input vector pair 'in6' and 'in7' are
2637                  average rounded (a + b + 1)/2 and stored in 'tmp3_m'
2638                  The half vector results from all 4 vectors are stored in
2639                  destination memory as 8x4 byte block
2640 */
2641 #define AVER_ST8x4_UB(in0, in1, in2, in3, in4, in5, in6, in7, pdst, stride)  \
2642 {                                                                            \
2643     uint64_t out0_m, out1_m, out2_m, out3_m;                                 \
2644     v16u8 tp0_m, tp1_m, tp2_m, tp3_m;                                        \
2645                                                                              \
2646     AVER_UB4_UB(in0, in1, in2, in3, in4, in5, in6, in7,                      \
2647                 tp0_m, tp1_m, tp2_m, tp3_m);                                 \
2648                                                                              \
2649     out0_m = __msa_copy_u_d((v2i64) tp0_m, 0);                               \
2650     out1_m = __msa_copy_u_d((v2i64) tp1_m, 0);                               \
2651     out2_m = __msa_copy_u_d((v2i64) tp2_m, 0);                               \
2652     out3_m = __msa_copy_u_d((v2i64) tp3_m, 0);                               \
2653     SD4(out0_m, out1_m, out2_m, out3_m, pdst, stride);                       \
2654 }
2655
2656 /* Description : Average rounded byte elements from pair of vectors and store
2657                  16x4 byte block in destination memory
2658    Arguments   : Inputs  - in0, in1, in2, in3, in4, in5, in6, in7, pdst, stride
2659    Details     : Each byte element from input vector pair 'in0' and 'in1' are
2660                  average rounded (a + b + 1)/2 and stored in 'tmp0_m'
2661                  Each byte element from input vector pair 'in2' and 'in3' are
2662                  average rounded (a + b + 1)/2 and stored in 'tmp1_m'
2663                  Each byte element from input vector pair 'in4' and 'in5' are
2664                  average rounded (a + b + 1)/2 and stored in 'tmp2_m'
2665                  Each byte element from input vector pair 'in6' and 'in7' are
2666                  average rounded (a + b + 1)/2 and stored in 'tmp3_m'
2667                  The vector results from all 4 vectors are stored in
2668                  destination memory as 16x4 byte block
2669 */
2670 #define AVER_ST16x4_UB(in0, in1, in2, in3, in4, in5, in6, in7, pdst, stride)  \
2671 {                                                                             \
2672     v16u8 t0_m, t1_m, t2_m, t3_m;                                             \
2673                                                                               \
2674     AVER_UB4_UB(in0, in1, in2, in3, in4, in5, in6, in7,                       \
2675                 t0_m, t1_m, t2_m, t3_m);                                      \
2676     ST_UB4(t0_m, t1_m, t2_m, t3_m, pdst, stride);                             \
2677 }
2678
2679 /* Description : Average rounded byte elements from pair of vectors,
2680                  average rounded with destination and store 8x4 byte block
2681                  in destination memory
2682    Arguments   : Inputs  - in0, in1, in2, in3, in4, in5, in6, in7, pdst, stride
2683    Details     : Each byte element from input vector pair 'in0' and 'in1' are
2684                  average rounded (a + b + 1)/2 and stored in 'tmp0_m'
2685                  Each byte element from input vector pair 'in2' and 'in3' are
2686                  average rounded (a + b + 1)/2 and stored in 'tmp1_m'
2687                  Each byte element from input vector pair 'in4' and 'in5' are
2688                  average rounded (a + b + 1)/2 and stored in 'tmp2_m'
2689                  Each byte element from input vector pair 'in6' and 'in7' are
2690                  average rounded (a + b + 1)/2 and stored in 'tmp3_m'
2691                  The half vector results from all 4 vectors are stored in
2692                  destination memory as 8x4 byte block
2693 */
2694 #define AVER_DST_ST8x4_UB(in0, in1, in2, in3, in4, in5, in6, in7,  \
2695                           pdst, stride)                            \
2696 {                                                                  \
2697     v16u8 tmp0_m, tmp1_m, tmp2_m, tmp3_m;                          \
2698     v16u8 dst0_m, dst1_m, dst2_m, dst3_m;                          \
2699                                                                    \
2700     LD_UB4(pdst, stride, dst0_m, dst1_m, dst2_m, dst3_m);          \
2701     AVER_UB4_UB(in0, in1, in2, in3, in4, in5, in6, in7,            \
2702                 tmp0_m, tmp1_m, tmp2_m, tmp3_m);                   \
2703     AVER_ST8x4_UB(dst0_m, tmp0_m, dst1_m, tmp1_m,                  \
2704                   dst2_m, tmp2_m, dst3_m, tmp3_m, pdst, stride);   \
2705 }
2706
2707 /* Description : Average rounded byte elements from pair of vectors,
2708                  average rounded with destination and store 16x4 byte block
2709                  in destination memory
2710    Arguments   : Inputs  - in0, in1, in2, in3, in4, in5, in6, in7, pdst, stride
2711    Details     : Each byte element from input vector pair 'in0' and 'in1' are
2712                  average rounded (a + b + 1)/2 and stored in 'tmp0_m'
2713                  Each byte element from input vector pair 'in2' and 'in3' are
2714                  average rounded (a + b + 1)/2 and stored in 'tmp1_m'
2715                  Each byte element from input vector pair 'in4' and 'in5' are
2716                  average rounded (a + b + 1)/2 and stored in 'tmp2_m'
2717                  Each byte element from input vector pair 'in6' and 'in7' are
2718                  average rounded (a + b + 1)/2 and stored in 'tmp3_m'
2719                  The vector results from all 4 vectors are stored in
2720                  destination memory as 16x4 byte block
2721 */
2722 #define AVER_DST_ST16x4_UB(in0, in1, in2, in3, in4, in5, in6, in7,  \
2723                            pdst, stride)                            \
2724 {                                                                   \
2725     v16u8 tmp0_m, tmp1_m, tmp2_m, tmp3_m;                           \
2726     v16u8 dst0_m, dst1_m, dst2_m, dst3_m;                           \
2727                                                                     \
2728     LD_UB4(pdst, stride, dst0_m, dst1_m, dst2_m, dst3_m);           \
2729     AVER_UB4_UB(in0, in1, in2, in3, in4, in5, in6, in7,             \
2730                 tmp0_m, tmp1_m, tmp2_m, tmp3_m);                    \
2731     AVER_ST16x4_UB(dst0_m, tmp0_m, dst1_m, tmp1_m,                  \
2732                    dst2_m, tmp2_m, dst3_m, tmp3_m, pdst, stride);   \
2733 }
2734
2735 /* Description : Add block 4x4
2736    Arguments   : Inputs  - in0, in1, in2, in3, pdst, stride
2737    Details     : Least significant 4 bytes from each input vector are added to
2738                  the destination bytes, clipped between 0-255 and then stored.
2739 */
2740 #define ADDBLK_ST4x4_UB(in0, in1, in2, in3, pdst, stride)         \
2741 {                                                                 \
2742     uint32_t src0_m, src1_m, src2_m, src3_m;                      \
2743     uint32_t out0_m, out1_m, out2_m, out3_m;                      \
2744     v8i16 inp0_m, inp1_m, res0_m, res1_m;                         \
2745     v16i8 dst0_m = { 0 };                                         \
2746     v16i8 dst1_m = { 0 };                                         \
2747     v16i8 zero_m = { 0 };                                         \
2748                                                                   \
2749     ILVR_D2_SH(in1, in0, in3, in2, inp0_m, inp1_m)                \
2750     LW4(pdst, stride,  src0_m, src1_m, src2_m, src3_m);           \
2751     INSERT_W2_SB(src0_m, src1_m, dst0_m);                         \
2752     INSERT_W2_SB(src2_m, src3_m, dst1_m);                         \
2753     ILVR_B2_SH(zero_m, dst0_m, zero_m, dst1_m, res0_m, res1_m);   \
2754     ADD2(res0_m, inp0_m, res1_m, inp1_m, res0_m, res1_m);         \
2755     CLIP_SH2_0_255(res0_m, res1_m);                               \
2756     PCKEV_B2_SB(res0_m, res0_m, res1_m, res1_m, dst0_m, dst1_m);  \
2757                                                                   \
2758     out0_m = __msa_copy_u_w((v4i32) dst0_m, 0);                   \
2759     out1_m = __msa_copy_u_w((v4i32) dst0_m, 1);                   \
2760     out2_m = __msa_copy_u_w((v4i32) dst1_m, 0);                   \
2761     out3_m = __msa_copy_u_w((v4i32) dst1_m, 1);                   \
2762     SW4(out0_m, out1_m, out2_m, out3_m, pdst, stride);            \
2763 }
2764
2765 /* Description : Dot product and addition of 3 signed halfword input vectors
2766    Arguments   : Inputs  - in0, in1, in2, coeff0, coeff1, coeff2
2767                  Outputs - out0_m
2768                  Return Type - signed halfword
2769    Details     : Dot product of 'in0' with 'coeff0'
2770                  Dot product of 'in1' with 'coeff1'
2771                  Dot product of 'in2' with 'coeff2'
2772                  Addition of all the 3 vector results
2773
2774                  out0_m = (in0 * coeff0) + (in1 * coeff1) + (in2 * coeff2)
2775 */
2776 #define DPADD_SH3_SH(in0, in1, in2, coeff0, coeff1, coeff2)         \
2777 ( {                                                                 \
2778     v8i16 tmp1_m;                                                   \
2779     v8i16 out0_m;                                                   \
2780                                                                     \
2781     out0_m = __msa_dotp_s_h((v16i8) in0, (v16i8) coeff0);           \
2782     out0_m = __msa_dpadd_s_h(out0_m, (v16i8) in1, (v16i8) coeff1);  \
2783     tmp1_m = __msa_dotp_s_h((v16i8) in2, (v16i8) coeff2);           \
2784     out0_m = __msa_adds_s_h(out0_m, tmp1_m);                        \
2785                                                                     \
2786     out0_m;                                                         \
2787 } )
2788
2789 /* Description : Pack even elements of input vectors & xor with 128
2790    Arguments   : Inputs  - in0, in1
2791                  Outputs - out_m
2792                  Return Type - unsigned byte
2793    Details     : Signed byte even elements from 'in0' and 'in1' are packed
2794                  together in one vector and the resulted vector is xor'ed with
2795                  128 to shift the range from signed to unsigned byte
2796 */
2797 #define PCKEV_XORI128_UB(in0, in1)                            \
2798 ( {                                                           \
2799     v16u8 out_m;                                              \
2800     out_m = (v16u8) __msa_pckev_b((v16i8) in1, (v16i8) in0);  \
2801     out_m = (v16u8) __msa_xori_b((v16u8) out_m, 128);         \
2802     out_m;                                                    \
2803 } )
2804
2805 /* Description : Converts inputs to unsigned bytes, interleave, average & store
2806                  as 8x4 unsigned byte block
2807    Arguments   : Inputs  - in0, in1, in2, in3, dst0, dst1, pdst, stride
2808 */
2809 #define CONVERT_UB_AVG_ST8x4_UB(in0, in1, in2, in3,           \
2810                                 dst0, dst1, pdst, stride)     \
2811 {                                                             \
2812     v16u8 tmp0_m, tmp1_m;                                     \
2813     uint8_t *pdst_m = (uint8_t *) (pdst);                     \
2814                                                               \
2815     tmp0_m = PCKEV_XORI128_UB(in0, in1);                      \
2816     tmp1_m = PCKEV_XORI128_UB(in2, in3);                      \
2817     AVER_UB2_UB(tmp0_m, dst0, tmp1_m, dst1, tmp0_m, tmp1_m);  \
2818     ST8x4_UB(tmp0_m, tmp1_m, pdst_m, stride);                 \
2819 }
2820
2821 /* Description : Pack even byte elements, extract 0 & 2 index words from pair
2822                  of results and store 4 words in destination memory as per
2823                  stride
2824    Arguments   : Inputs  - in0, in1, in2, in3, pdst, stride
2825 */
2826 #define PCKEV_ST4x4_UB(in0, in1, in2, in3, pdst, stride)  \
2827 {                                                         \
2828     uint32_t out0_m, out1_m, out2_m, out3_m;              \
2829     v16i8 tmp0_m, tmp1_m;                                 \
2830                                                           \
2831     PCKEV_B2_SB(in1, in0, in3, in2, tmp0_m, tmp1_m);      \
2832                                                           \
2833     out0_m = __msa_copy_u_w((v4i32) tmp0_m, 0);           \
2834     out1_m = __msa_copy_u_w((v4i32) tmp0_m, 2);           \
2835     out2_m = __msa_copy_u_w((v4i32) tmp1_m, 0);           \
2836     out3_m = __msa_copy_u_w((v4i32) tmp1_m, 2);           \
2837                                                           \
2838     SW4(out0_m, out1_m, out2_m, out3_m, pdst, stride);    \
2839 }
2840
2841 /* Description : Pack even byte elements and store byte vector in destination
2842                  memory
2843    Arguments   : Inputs  - in0, in1, pdst
2844 */
2845 #define PCKEV_ST_SB(in0, in1, pdst)                   \
2846 {                                                     \
2847     v16i8 tmp_m;                                      \
2848     tmp_m = __msa_pckev_b((v16i8) in1, (v16i8) in0);  \
2849     ST_SB(tmp_m, (pdst));                             \
2850 }
2851
2852 /* Description : Horizontal 2 tap filter kernel code
2853    Arguments   : Inputs  - in0, in1, mask, coeff, shift
2854 */
2855 #define HORIZ_2TAP_FILT_UH(in0, in1, mask, coeff, shift)            \
2856 ( {                                                                 \
2857     v16i8 tmp0_m;                                                   \
2858     v8u16 tmp1_m;                                                   \
2859                                                                     \
2860     tmp0_m = __msa_vshf_b((v16i8) mask, (v16i8) in1, (v16i8) in0);  \
2861     tmp1_m = __msa_dotp_u_h((v16u8) tmp0_m, (v16u8) coeff);         \
2862     tmp1_m = (v8u16) __msa_srari_h((v8i16) tmp1_m, shift);          \
2863     tmp1_m = __msa_sat_u_h(tmp1_m, shift);                          \
2864                                                                     \
2865     tmp1_m;                                                         \
2866 } )
2867 #endif  /* AVUTIL_MIPS_GENERIC_MACROS_MSA_H */