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