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